5

私が取り組んでいる mailMerge スクリプトでは.replaceText()、フィールドをデータベース内の対応する値に置き換えるために使用しています。

このインターフェイスを使用すると、ドキュメントでテストして、結果が期待どおりに見えるかどうかを確認できます。また、他の値で使用できるように、フィールドを元の位置に戻すための「UNDO」関数が必要です (このスクリプトは制限されています)。サイドバーのドキュメントに移動するには、この投稿を参照してください)

以下のスクリプトは、フィールド名とその置換値をメモリに保持することで、これをうまく行っています。私を悩ませている唯一の詳細は、現在のテスト データに値がないフィールドに対して特別な「空の」ラベルを定義して、ドキュメント内でトラックが失われないようにしなければならなかったことです。(私は °vide12° のような番号付きの識別子を使用しました)。

これは完全に機能していますが、テストモードのドキュメントは、私が使用するこれらの°videoXX°のために最終ドキュメントを正確に表現していないため、理想的ではありません...

問題は次のとおりです。データがあまり目立たない場合に、置換データを「ローカライズ」するためのより良いアイデアまたは別のアプローチを誰かが持っていますか? (私はこれが奇妙に聞こえることを知っています...それが私が全体の状況を説明する理由です:-)

Google ドキュメントの構築方法を考えると、完全な要素構造を取得し、その情報からドキュメントを再構築できると考えましたが、最小の要素は段落であり、フィールドは主に単一の単語であるため、残念ながらそれは不可能です。 ..

これが私が使用するコードの関連部分です。(できれば) 明確にするためにいくつかのコメントを追加しました。

function valuesInDoc(e){ // this function replaces the fields with database values
  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){var ui = DocumentApp.getUi() ; ui.alert("Aucun champ (#chX#) trouvé dans le document... Veuillez insérer des identifiants aux endroits souhaités");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]);
    var newField = ChampSpecial(curData,realIdx,fctSpe);
    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!='dataSelection'){
    body.replaceText('#ch'+(n+1)+'#',newField);
    }
  }
  UserProperties.setProperty('replacements',replacements.join('|'));// memorize the replacement pattern
  cloakOn();// hide hidden fields
  return app;
}



function fieldsInDoc(e){ // this function does the reverse process and restores the field identifiers
  cloakOff();// show hidden fields
  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);
    }
}

function ChampSpecial(curData,idx,ref){ // this function handles a special case for a specific field, the relevant part is right below, see comment
  if(idx==-1){return''};
  if(curData[idx-1]==''){return'°vide'+idx+'°'};// this is the "empty" identifier
  if(idx<ref){return curData[idx]};
  if(idx>ref){return curData[idx-1]}
  var firstSpace = curData[idx-1].indexOf(' ');
  var apos = curData[idx-1].indexOf("'");
//Logger.log('firstSpace='+firstSpace+'  apos='+apos)
  if(firstSpace<4&&firstSpace>-1){return curData[idx-1].substring(firstSpace+1)};
  if(apos<3&&apos>-1){return curData[idx-1].substring(apos+1)};
  return curData[idx-1];
}

編集: Mogsdadの素晴らしい回答のおかげで、未使用のフィールドを非表示/表示するためにこれら2つの関数を作成しました。私の場合、Sinc は °XX° (XX=2 桁の数字) を使用して未使用のフィールドを追跡し、この特定の文字列を探すために彼のコードを変更する必要があり、2 つのループを使用してすべてのフィールドを取得しました。

これらの関数をメニューから、および置換を処理する他の 2 つの関数から呼び出します (上記のコードも更新しました)。

100回以上反復するので時間の無駄に見えるかもしれませんが、結果は瞬時です...だからわざわざ?誰かにアイデアを与える場合のコードを次に示します。

function cloakOn() {
  var doc = DocumentApp.getActiveDocument();
  var body = doc.getBody();
  var found = [];
  for(var n=1;n<23;++n){
    for(var f=0;f<5;++f){
      if(f==0){found[f] = body.findText('°'+Utilities.formatString("%02d",n)+'°')}else{found[f] = body.findText('°'+Utilities.formatString("%02d",n)+'°',found[f-1])}
      if(found[f]!=null){
        var elemTxt = found[f].getElement().asText();
        elemTxt.setFontSize(found[f].getStartOffset(), found[f].getEndOffsetInclusive(),0)
        var background = elemTxt.getBackgroundColor(found[f].getStartOffset()) || "#ffffff";
        elemTxt.setForegroundColor(found[f].getStartOffset(), found[f].getEndOffsetInclusive(), background);
      }
    }
  }
}

function cloakOff() {
  var doc = DocumentApp.getActiveDocument();
  var body = doc.getBody();
  var found = [];
  for(var n=1;n<23;++n){
    for(var f=0;f<5;++f){
      if(f==0){found[f] = body.findText('°'+Utilities.formatString("%02d",n)+'°')}else{found[f] = body.findText('°'+Utilities.formatString("%02d",n)+'°',found[f-1])}
      if(found[f]!=null){
        var elemTxt = found[f].getElement().asText();
        var size = elemTxt.getParent().getFontSize();
        elemTxt.setFontSize(found[f].getStartOffset(), found[f].getEndOffsetInclusive(),size)
        var background = elemTxt.getBackgroundColor(found[f].getStartOffset()) || "#000000";
        elemTxt.setForegroundColor(found[f].getStartOffset(), found[f].getEndOffsetInclusive(), background);
      }
    }
  }
}
4

1 に答える 1