我有以下脚本,它从电子表格中获取行a,并在列名匹配时替换文档中的占位符。我使用%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});
}
你没有说,但显然你正在使用一个库,"ScriptsLib"。我已经做了搜索,但找不到getRowsData
和getKeys
方法的任何公共代码,所以它可能是一个私有库。
我需要猜测一下这两个函数是做什么的。如果您可以从ScriptsLib中提供它们的源代码,它将有助于验证或修改我的猜测,它们是:
- ScriptsLib是基于使用电子表格数据的示例代码,其中包含getRowsData和一些支持函数。
- 方法
getKeys
与类UserProperties中的同名函数类似。
getRowsData
方法通过调用getObjects
创建一个对象数组。getObjects
方法在给定范围内迭代,从每行创建一个具有命名属性的对象数组。如果一行中有空白单元格,则不会有该列的名称属性。
在您的代码中,您遍历data[0]
中包含的键,由于getObjects
的工作方式,当源数据中有空白时,它将是不完整的(缺少属性)。这意味着你从来没有真正处理过这些空白,也没有机会用"N/A"替换相关的键。
您需要做的是循环遍历模板文档中的关键值—这些值可能由电子表格中的标题表示。(…归一化后为camelCase,即)。
var keys = ScriptsLib.normalizeHeaders(sheet.getRange('A1:1').getValues()[0]);
这将为我们提供要迭代的键的完整列表。但我们还没做完呢。
在检查是否有属性的逻辑中有一个错误。看这一行:
if (data[0][keys[key]] != null || data[0][keys[key]] != ''){
如果有OR操作符,则在下列情况下执行IF块data[0][keys[key]]
为null。你写了一个else子句,它应该用"N/a "替换一个键,但它不会被执行。
:: when data[0][keys[key]] == null
data[0][keys[key]] != null :: false
data[0][keys[key]] != '' :: true (because null != '')
你可能想用AND。
if (data[0][keys[key]] != null && data[0][keys[key]] != ''){
那应该使事情按照你想要的方式工作。但我建议明确地处理数据对象不具有具有特定键名的属性的可能性,并同时解决这个问题和/或错误。JavaScript为我们提供了hasOwnProperty()
。
if (data[0].hasOwnProperty(keys[key])) // property is present
重构后的代码变成:
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});
}
您可以查看代码的以下部分,我在几行末尾添加了两个注释:
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');
}
}