一种可能的解决方案是防止文档中的示例字段包含正则表达式特殊字符,因此必须在正向过程中进行替换,而不是在反向过程中进行(如另一个答案中所建议)。在字段值中转义这些字符不起作用*所以我最终用连字符进行了简单替换(在大多数情况下替换斜杠或“+”是有意义的)。
(*) 反向过程使用保存在内存中的值,因此转义符号会干扰该函数中的替换,从而阻止它正常工作。
最终的工作代码就像这样:
//(in the first function)
var newField = ChampSpecial(curData,realIdx,fctSpe).replace(/([*+?^=!:${}()|\[\]\/\\])/g, "-");// replace every occurrence of *+?^... by '-' (global search)
关于评论指出这种方法是一个坏主意,我只能说恐怕没有其他方法可以实现这种行为,并且如果最终出现错误的可能性非常低,因为邮件合并的主要用途是插入模板本身很少出现的专有名称、地址、电子邮件和电话号码。
至于字段指示符,它们永远不会有相同的名称,因为它们是数字索引的 (#chXX#)。
编辑:在 Taras 的评论之后,我将尝试另一种解决方案,如果它按预期工作,稍后会更新。
编辑 6 月 19 日 ,Yesssss ......找到了。
我终于找到了一个更好的解决方案,它不使用正则表达式,所以我不会被迫转义特殊字符......该.find()
方法接受任何字符串。代码有点复杂,但结果值得痛苦:-))
如果有人寻找类似的东西,这里是 2 个函数的完整代码。
function valuesInDoc(e){
var lock = LockService.getPrivateLock(); // just in case one clicks the second button before this one ends
var success = lock.tryLock(5000);
if (!success) {
Logger.log('tryLock failed to get the lock');
return
}
colorize('#ffffff');// this function removes the color tags on the field marlers
var app = UiApp.getActiveApplication();
var listVal = UserProperties.getProperty('listSel').split(',');
var replacements = [];
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var find = body.findText('#ch');
if(find == null){return app };
var curData = UserProperties.getProperty('selItem').split('|');
var Headers = [];
var OriHeaders = UserProperties.getProperty('Headers').split('|');
for(n=0;n<OriHeaders.length;++n){
Headers.push('#'+OriHeaders[n]+'#');
}
var fctSpe = 0 ;
for(var i in Headers){if(Headers[i].indexOf('SS')>-1){fctSpe = i}}
for(var n=0;n<listVal.length;++n){
var realIdx = Number(listVal[n]);
Logger.log(n);
var newField = ChampSpecial(curData,realIdx,fctSpe);
//Logger.log(newField);
app.getElementById('textField'+(n+1)).setHTML(ChampSpecial(curData,realIdx,fctSpe));
if(e.parameter.source=='insertInText'){
var found = body.findText('#ch'+(n+1)+'#');// look for every field markers in the whole doc
while(found!=null){
var elemTxt = found.getElement().asText();
var startOffset = found.getStartOffset();
var len = ('#ch'+(n+1)+'#').length;
elemTxt.deleteText(startOffset, found.getEndOffsetInclusive())
elemTxt.insertText(startOffset,newField);// remove the marker and write the sample value in place
Logger.log('n='+n+' newField = '+newField+' for '+'#ch'+(n+1)+'#'+' at position '+startOffset)
replacements.push(newField+'∏'+'#ch'+(n+1)+'#'+'∏'+startOffset);// memorize the change that just occured
found = body.findText('#ch'+(n+1)+'#',found); //loop until all markers are replaced
}
}
}
UserProperties.setProperty('replacements',replacements.join('|'));
cloakOn();
colorize('#ffff44');// colorize the markers if ever one is left but it shouldn't happen
lock.releaseLock();
return app;
}
function fieldsInDoc(e){
var lock = LockService.getPrivateLock();
var success = lock.tryLock(5000);
if (!success) {
Logger.log('tryLock failed to get the lock');
return
}
cloakOff();// remet d'abord les champs vides > shows the hidden fields (markers that had no sample velue in the first function
var replacements = UserProperties.getProperty('replacements').split('|');// recover replacement data as an array
Logger.log(replacements)
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
for(var n=replacements.length-1;n>=0;n--){ // for each replacement find the data in doc and write a field marker in place
var testVal = replacements[n].split('∏')[0]; // [0] is the sample value
if(body.findText(testVal)==null){break};// this is only to handle the case one click on the wrong button trying to place markers again when they are already there ;-)
var field = replacements[n].split('∏')[1];
var testValLength = testVal.length;
var found = body.findText(testVal);
var startOffset = found.getStartOffset();
Logger.log(testVal+' = '+field+' / start: '+startOffset+' / Length: '+ testValLength)
var elemTxt = found.getElement().asText();
elemTxt.deleteText(startOffset, startOffset+testValLength-1);// remove the text
// elemTxt.deleteText(startOffset, found.getEndOffsetInclusive() )
elemTxt.insertText(startOffset,field);// and write the marker
}
colorize('#ffff44'); // colorize the marker
lock.releaseLock();// and release the lock
}