0

スプレッドシートから行を取得し、列名が一致する場合にドキュメント内のプレースホルダーを置き換える次のスクリプトがあります。フォーマットを使用してい%placeHolder%ます。メソッドは完全に機能しますが、そのフィールドが空白のreplaceText()場合、プレースホルダーを空白または「N/A」に置き換えるにはどうすればよいですか? いくつかの異なるルートを試しましたが、おそらく簡単なものが欠けています。

function formatTemplate(){
  var postFlightTemplate = DocsList.getFileById('templateKey').makeCopy().getId();

  var template = DocumentApp.openById(postFlightTemplate);
  var templateHeader = template.getHeader();
  var templateBody = template.getActiveSection();

  var flightLog = SpreadsheetApp.openById('spreadsheetKey');
  var sheet = flightLog.getSheetByName('Flight Tracking');
  var data = ScriptsLib.getRowsData(sheet, sheet.getRange('A2:2'), 1);

  var keys = ScriptsLib.getKeys(data[0]);

  for (var key in keys){
    Logger.log('key:'+keys[key]+' / value:'+data[0][keys[key]]);
    if (data[0][keys[key]] != null || data[0][keys[key]] != ''){
      templateHeader.replaceText('%'+keys[key]+'%', data[0][keys[key]]);
      templateBody.replaceText('%'+keys[key]+'%', data[0][keys[key]]);
    }else{
      Logger.log('empty key:'+keys[key]+' / value:'+data[0][keys[key]]);
      templateBody.replaceText('%'+keys[key]+'%', 'N/A');
    }
  }
  template.setName('RR-'+data[0].incidentNumber+'-'+data[0].flightNumber);
  template.saveAndClose();

  MailApp.sendEmail('email@email.com', 'Post Flight Report','See Run Report', {name: 'P1AR Flight Log', attachments: template});
}
4

2 に答える 2

2

You don't say, but apparently you're using a library, "ScriptsLib". I've done searches, but can't find any public code with both getRowsData and getKeys methods, so it's probably a private library.

I need to do some guessing about what those two functions do. If you can provide the source for them from your ScriptsLib, it would help to validate or revise my guesses, which are:

The getRowsData method creates an array of objects, by calling getObjects. The getObjects method iterates over the given range creating an array of objects with named properties from each row. If there is a blank cell in a row, there will be no property with the name for that column.

In your code, you loop over the keys contained in data[0], which will be incomplete (missing properties) when there were blanks in the source data, because of the way getObjects works. That means that you never really process the blanks, and don't have an opportunity to replace the relevant keys with "N/A".

What you need to do then, is loop over the key values that are in the template document - and those are probably represented by the headings in the spreadsheet. (...after normalization to camelCase, that is).

var keys = ScriptsLib.normalizeHeaders(sheet.getRange('A1:1').getValues()[0]); 

That will give us the full list of keys to iterate over. But we're not done yet.

You've got a bug in the logic that checks whether you have a property. Look at this line:

if (data[0][keys[key]] != null || data[0][keys[key]] != ''){

With an OR operator there, you will end up executing the IF block when data[0][keys[key]] is null. You've written an else clause that should replace a key with "N/A", but it's not going to get executed.

                            :: when data[0][keys[key]] == null
data[0][keys[key]] != null  :: false
data[0][keys[key]] != ''    :: true (because null != '')

You probably meant to use AND.

if (data[0][keys[key]] != null && data[0][keys[key]] != ''){

That should make things work the way you want. But I'd suggest explicitly dealing with the possibility that a data object won't have a property with a particular key name, and getting around that and/or bug at the same time. JavaScript gives us hasOwnProperty() to do that.

if (data[0].hasOwnProperty(keys[key])) // property is present

The refactored code becomes:

function formatTemplate(){
  var postFlightTemplate = DocsList.getFileById('templateKey').makeCopy().getId();

  var template = DocumentApp.openById(postFlightTemplate);
  var templateHeader = template.getHeader();
  var templateBody = template.getActiveSection();

  var flightLog = SpreadsheetApp.openById('spreadsheetKey');
  var sheet = flightLog.getSheetByName('Flight Tracking');
  var data = ScriptsLib.getRowsData(sheet, sheet.getRange('A2:2'), 1);

  var keys = ScriptsLib.normalizeHeaders(sheet.getRange('A1:1').getValues()[0]); 

  for (var key in keys){
    if (data[0].hasOwnProperty(keys[key])) { // property is present
      Logger.log('key:'+keys[key]+' / value:'+data[0][keys[key]]);
      templateHeader.replaceText('%'+keys[key]+'%', data[0][keys[key]]);
      templateBody.replaceText('%'+keys[key]+'%', data[0][keys[key]]);
    }else{
      Logger.log('empty key:'+keys[key]+' / value:'+data[0][keys[key]]);
      templateBody.replaceText('%'+keys[key]+'%', 'N/A');
    }
  }
  template.setName('RR-'+data[0].incidentNumber+'-'+data[0].flightNumber);
  template.saveAndClose();

  MailApp.sendEmail('email@email.com', 'Post Flight Report','See Run Report', {name: 'P1AR Flight Log', attachments: template});
}
于 2013-04-30T17:13:45.613 に答える
2

コードの次のセクションを確認してください。数行の最後に 2 つのコメントを追加しました。

for (var key in keys){
    Logger.log('key:'+keys[key]+' / value:'+data[0][keys[key]]);
    if (data[0][keys[key]] != null || data[0][keys[key]] != undefined){ // I changed this to undefined
      templateHeader.replaceText('%'+keys[key]+'%', data[0][keys[key]]);
      templateBody.replaceText('%'+keys[key]+'%', data[0][keys[key]]);
    }else{
      Logger.log('empty key:'+keys[key]+' / value:'+data[0][keys[key]]);
      templateHeader.replaceText('%'+keys[key]+'%', 'N/A'); // I added this row
      templateBody.replaceText('%'+keys[key]+'%', 'N/A');
    }
  }
于 2013-04-30T16:59:46.940 に答える