我处于编程的初学者到中级的状态,在这里我足够了解将某些东西拼凑起来的过程,这些事情可能相当复杂,但也许我并没有以最好的方式去解决,陷入困境,而且它肯定没有优化
我已经构建了一个发票生成器,该发票生成器将从工作表输入的数据转换为google docs中的相同模板。我希望有一个脚本,该脚本接受报价信息,并将这些行复制到docs中的模板中,除非该行为空,在这种情况下,它会跳到下一个。
到目前为止,我已经通过将每个单元格指定为一个自变量,并分别复制它们(无论是否填充它们)来实现这一目标。
它可以工作,但是它似乎不是最有效的解决方案,并且由于我们仍然必须在生成的报价文档中修复某些格式,所以它很快变得很痛苦。
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sinput = ss.getSheetByName("QUOTE TEMPLATE");
//TO GENERATE DOCUMENT
var templateId = '1jIxHUZAoVd00a9eTZM-ORL0H7qMLfEmyat04l89GNwE';
//devis
var item1 = sinput.getRange("B18").getValues();
var item2 = sinput.getRange("B19").getValues();
var item3 = sinput.getRange("B20").getValues();
var qty1 = sinput.getRange("C18").getValues();
var qty2 = sinput.getRange("C19").getValues();
var qty3 = sinput.getRange("C20").getValues();
var unitprice1 = sinput.getRange("D18").getValues();
var unitprice2 = sinput.getRange("D19").getValues();
var unitprice3 = sinput.getRange("D20").getValues();
var total1 = sinput.getRange("E18:G18").getValues();
var total2 = sinput.getRange("E19:G19").getValues();
var total3 = sinput.getRange("E20:G20").getValues();
//Make a copy of the template file
var documentId = DriveApp.getFileById(templateId).makeCopy().getId();
//Get the document body as a variable
var body = DocumentApp.openById(documentId).getBody();
//All the text to be replaced
body.replaceText('%DESCRIPTION_STRING1%', item1 );
body.replaceText('%DESCRIPTION_STRING2%', item2 );
body.replaceText('%DESCRIPTION_STRING3%', item3 );;
body.replaceText('%Q1%', qty1 );
body.replaceText('%Q2%', qty2 );
body.replaceText('%Q3%', qty3 );
body.replaceText('%PRIC1%', unitprice1 );
body.replaceText('%PRIC2%', unitprice2 );
body.replaceText('%PRIC3%', unitprice3);;
body.replaceText('%TOTAL_1%', total1 );
body.replaceText('%TOTAL_2%', total2);
body.replaceText('%TOTAL_3%', total3 );;
}
这是简化版本,因为原始代码占20条不同的输入行,也许更多。 当前,任何空白单元格都会导致逗号(,)导出到google文档中。
我很想:
body.replaceText
但是我不知道如何正确表达代码中的“如果一行为空,只需移至下一位”。
我有大约6个月的工作经验,因此我认为自己仍然是一名学习者。感谢您提供任何帮助或见识!
答案 0 :(得分:1)
尝试一下:
function fn(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3");
var data = ss.getRange("B18:G20").getValues();
//Make a copy of the template file
var documentId = DriveApp.getFileById(templateId).makeCopy().getId();
//Get the document body as a variable
var body = DocumentApp.openById(documentId).getBody();
//All the text to be replaced
body.replaceText('%DESCRIPTION_STRING1%', data[0][0]);
body.replaceText('%DESCRIPTION_STRING2%', data[1][0]);
body.replaceText('%DESCRIPTION_STRING3%', data[2][0]);
body.replaceText('%Q1%', data[0][1]);
body.replaceText('%Q2%', data[1][1]);
body.replaceText('%Q3%', data[2][1]);
body.replaceText('%PRIC1%', data[0][2] );
body.replaceText('%PRIC2%', data[1][2]);
body.replaceText('%PRIC3%', data[2][2]);
body.replaceText('%TOTAL_1%', data[0][3] + " " + data[0][4] + " " + data[0][5]);
body.replaceText('%TOTAL_2%', data[1][3] + " " + data[1][4] + " " + data[1][5]);
body.replaceText('%TOTAL_3%', data[2][3] + " " + data[2][4] + " " + data[2][5]);
}
我假设您想要总计这些单元格中的值,如果不是这种情况,请告诉我,我将更新我的代码。
关于您所做的事情,根据Apps Script Best Practices,应避免多次调用API,因为它们是您要使用的最重的方法(尤其是getValue()
)。理想的做法是使用getValues()
获取一次值并处理返回的二维数组(Documentation here)
另一件事,当您调用body.replaceText('%DESCRIPTION_STRING1%', item1 )
,item1
,item2
和item3
都是2D数组时,因此在替换中使用它们是行不通的,这就是为什么我问你想和他们做什么。
最后,我认为body.replaceText()
的替代方法是提取正文,并对字符串进行所有搜索,然后将整个正文替换为结果。这意味着更少的API调用。