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

考えられる解決策の 1 つは、ドキュメントの例のフィールドに正規表現の特殊文字が含まれないようにすることでした。そのため、置換は逆方向ではなく順方向プロセスで行う必要がありました(他の回答で示唆されているように)。フィールド値でこれらの文字をエスケープしてもうまくいきませんでした*ので、単純にハイフンに置き換えました (ほとんどの場合、スラッシュまたは「+」を置き換えるのが理にかなっています)。

(*) 逆のプロセスはメモリに保持されている値を使用するため、エスケープ記号がその関数の置換を妨害し、適切に機能しませんでした。

最終的な作業コードは次のようになります。

//(in the first function) 
    var newField = ChampSpecial(curData,realIdx,fctSpe).replace(/([*+?^=!:${}()|\[\]\/\\])/g, "-");// replace every occurrence of *+?^... by '-' (global search)

このアプローチは悪い考えであるというコメントについては、その動作を取得する他の方法は実際にはなく、メールマージの主な使用法はテンプレート自体にはめったにない適切な名前、住所、電子メール、電話番号を挿入します。

フィールド インジケータに関しては、数値でインデックスが付けられているため (#chXX#)、同じ名前になることはありません。

編集: Tarasのコメントに従って、別の解決策を試します。期待どおりに機能する場合は後で更新します。


EDIT 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)+'#');

これは、「マーカーを元に戻す」というのは悪い考えだと言いました。差し込み印刷の 2 つのフィールドが同じ値であるか、置換テキストがドキュメント テンプレートに既に存在する場合はどうなりますか?

于 2013-06-17T11:45:55.740 に答える