0

在邮件合并应用程序中,我使用该.replace()方法将字段标识符替换为自定义值,并在反向过程中取回标识符。

第一种方法每次都有效,因为替换第一个参数是我故意选择的一个非常正常的字符串......但是当我反转这个过程时,有时会发生字符串包含不正确的正则表达式字符。这主要发生在表单中的电话号码上,+32 2 345 345甚至是一些重音字符。

鉴于我无法阻止这种情况的发生,并且我不太希望我的最终用户不会使用这种电话号码格式,我想知道是否有人可以建议一种解决方法来在出现非法字符时转义?注意:它可以在字符串中的任何位置。

下面是这两个函数的代码。

    ... (partial code)
    var newField = ChampSpecial(curData,realIdx,fctSpe);// returns the value from the database
    if(newField!=''){replacements.push(newField+'∏'+'#ch'+(n+1)+'#')};
//Logger.log('value in '+n+'='+realIdx+'  >>  '+Headers[realIdx]+'  =  '+ChampSpecial(curData,realIdx,fctSpe))
    app.getElementById('textField'+(n+1)).setHTML(ChampSpecial(curData,realIdx,fctSpe));
    if(e.parameter.source=='insertInText'){
    body.replaceText('#ch'+(n+1)+'#',newField);
    }
  }
  UserProperties.setProperty('replacements',replacements.join('|'));
  cloakOn();
  colorize('#ffff44');
  return app;
}

function fieldsInDoc(e){
  cloakOff();// remet d'abord les champs vides
  var replacements = UserProperties.getProperty('replacements').split('|');
  var doc = DocumentApp.getActiveDocument();
  var body = doc.getBody();
  for(var n=0;n<replacements.length;++n){
    var field = replacements[n].split('∏')[1];
    var testVal = replacements[n].split('∏')[0];    
    body.replaceText(testVal,field);
    }
  colorize('#ffff44');
}
4

2 回答 2

0

一种可能的解决方案是防止文档中的示例字段包含正则表达式特殊字符,因此必须在正向过程中进行替换,而不是在反向过程中进行(如另一个答案中所建议)。在字段值中转义这些字符不起作用*所以我最终用连字符进行了简单替换(在大多数情况下替换斜杠或“+”是有意义的)。

(*) 反向过程使用保存在内存中的值,因此转义符号会干扰该函数中的替换,从而阻止它正常工作。

最终的工作代码就像这样:

//(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
}
于 2013-06-18T07:37:35.980 回答
0

在相反的过程中,您正在使用提供的可以包含正则表达式特殊字符的字段值。你必须在替换之前逃脱它们:

body.replaceText(field.replace(/[[\]{}()*-+?.,\\^$|#\s]/, '\\$&'), '#ch'+(n+1)+'#');

这就是说,“替换回标记”是个坏主意。如果邮件合并的两个字段具有相同的值或文档模板中已经存在替换文本会发生什么...

于 2013-06-17T11:45:55.740 回答