我目前正在编写一个谷歌脚本,但遗憾的是运行速度太慢。 (超过6分钟的限制)。该脚本打开一个文档,替换两个字符串(在google工作表中设置),将其另存为PDF。没什么好看的。
我有大约200个这样的文档来运行这个脚本,但在6分钟的限制内,它只能通过6个。谷歌脚本是这么慢,还是我不小心制作了效率最低的谷歌脚本?
function createAllPDF() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = SpreadsheetApp.getActiveSheet().getActiveRange()
var numRows = SpreadsheetApp.getActiveSpreadsheet().getLastRow() - 1;
for(var i = 9; i <= numRows; i++) {
var thisRange = sheet.getRange("A" + n + ":C" + n);
var fond = thisRange.getCell(1, 1).getValue();
var adresse = thisRange.getCell(1, 3).getValue();
thisRange.setBackground('#cfe2f3');
genDoc(fond, adresse);
}
}
//// CREATE PDF ////////////////// FUNCTION FOR GENERATING THE PDF /////////////////////////////////
function genDoc(fond, adresse) {
// Finds the template and duplicate it into a new file.
var template = ("xxxxxxxxxxxx");
var docId = DriveApp.getFileById(template).makeCopy().getId();
// Opens the newly created Document for editing
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
// Renames the newly generated document
var newName = doc.setName(fond);
// Replaces each with the parsed variables.
body.replaceText("%FOND%", fond);
body.replaceText("%ADRESSE%", adresse);
doc.saveAndClose();
//Adds the PDF ID to the invoice_input sheet
var conv = DriveApp.getFileById(docId);
var pdf = conv.getAs("application/pdf");
var fileId = DriveApp.createFile(pdf).getId();
// Gets the PDF file by ID
var thisPDF = DriveApp.getFileById(fileId);
// The ID of the folder I'd like to put the PDF into.
var folderId = "xxxxxxxxxxx";
// Gets the folder by ID
var targetFolder = DriveApp.getFolderById(folderId);
// Adds the PDF to the Folder
targetFolder.addFile(thisPDF);
// Removes the PDF from the root.
var root = DriveApp.getRootFolder().removeFile(thisPDF);
// Deletes the duplicated document
DriveApp.getFileById(docId).setTrashed(true)
return fileId;
}
任何关于如何优化的指针都将非常受欢迎。我对谷歌脚本和编程很新,所以没什么大不了的,呵呵。 如果我正在使用此板,请道歉。请让我知道,我会纠正。
答案 0 :(得分:1)
我立即注意到你有一个未定义的变量n
。它在行:
var thisRange = sheet.getRange("A" + n + ":C" + n);
这应该使代码完全无法使用。将这些变量更改为i
后,我能够成功运行代码整整6分钟。在那段时间里,它能够循环约41.5次。它为第9-53行创建了文件,但在能够将最后一个文件添加到正确的文件夹之前停止了。
查看执行记录,您最长的操作是创建,移动和删除文件的几次调用。
您还定义了range
,然后从不使用此变量,这使得它变得不必要。
我在自己多次使用的结构和方法中重写了代码。我能够完全处理第9-59行。这种方法能够将其扩展6行。我建议添加一个超时触发器,每隔5min55秒停止一次该功能,然后在5秒后重新启动它。有关javascript时间的指南可以找到here。我也使用不同的匹配方法;使用RegEx。 RegEx有广泛的指南以及如何最大限度地缩短处理时间。我对这个领域的熟练程度不高。
function PDFCreator() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Test Sheet");
var lastRow = sheet.getLastRow();
var checkRange = sheet.getRange(9, 1, (lastRow - 8), 3);
var check = checkRange.getBackgrounds();
var lightBlue = "#cfe2f3";
var template = DriveApp.getFileById("1RslWGntAwfLTSytOv_IoOv2_iBhSmsK0ZtEVWaq3ezM");
var folder = DriveApp.getFolderById("0BwZ6LWJudkOHaTFiQjd5cFA5OG8");
for (i = 0; i < check.length; i++) {
if (check[i] == lightBlue) {
continue;
} else {
var dataRow = sheet.getRange((i + 9), 1, 1, 3);
var fond = sheet.getRange((i + 9), 1, 1, 1).getValue();
var adresse = sheet.getRange((i + 9), 3, 1, 1).getValue();
var docName = fond + ".pdf";
var docCopy = template.makeCopy(docName, folder);
var docId = docCopy.getId();
var docToEdit = DocumentApp.openById(docId);
var docBody = docToEdit.getBody();
docBody.replaceText(/\%{1}[F][O][N][D]\%{1}/g, fond);
docBody.replaceText(/\%{1}[A][D][R][E][S][S][E]\%{1}/g, adresse);
docToEdit.saveAndClose();
var fileToPDF = DriveApp.getFileById(docId);
var pdfBlob = fileToPDF.getAs(MimeType.PDF);
var pdfRoot = DriveApp.createFile(pdfBlob).setName(docName);
var pdf = pdfRoot.makeCopy(folder);
pdfRoot.setTrashed(true);
fileToPDF.setTrashed(true);
dataRow.setBackground(lightBlue);
}
}
}
你会注意到我嵌套了main函数中的for()
和if()
。这样,您不会反复在函数之间来回传递信息。通常,您可以越多地定义在之外的循环,您将需要进行的调用越少。我可以在for循环之外设置更多变量,以进一步扩展它的运行。
基本上,这是一个漫长的过程,并且它无法在6分钟内运行200次。你可以将这个行扩展到55/60行,效率很高,但此时你只需要再次运行它。
答案 1 :(得分:0)
(注意:尚未对此进行测试,但应该让您入门)
一些想法:
这样的事情:
function createAllPDF() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var numRows = sheet.getLastRow() - 1;
var range = sheet.getActiveRange();
var values = range.getValues();
var templateId = ("xxxxxxxxxxxx");
var template = DriveApp.getFileById(templateId);
// The ID of the folder I'd like to put the PDF into.
var folderId = "xxxxxxxxxxx";
// Gets the folder by ID
var targetFolder = DriveApp.getFolderById(folderId);
var rootFolder = DriveApp.getRootFolder();
for(var i = 9; i <= numRows; i++) {
var fond = values[i][1]; // TODO: check syntax.
var adresse = values[i][3];
genDoc(fond, adresse, template, targetFolder, rootFolder);
}
range.setBackground('#cfe2f3'); // TODO: only first 3 columns
}
//// CREATE PDF ////////////////// FUNCTION FOR GENERATING THE PDF /////////////////////////////////
function genDoc(fond, adresse, template, targetFolder, rootFolder) {
// Finds the template and duplicate it into a new file.
var conv = template.makeCopy();
var docId = conv.getId();
// Opens the newly created Document for editing
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
// Renames the newly generated document
var newName = doc.setName(fond);
// Replaces each with the parsed variables.
body.replaceText("%FOND%", fond);
body.replaceText("%ADRESSE%", adresse);
doc.saveAndClose();
//Adds the PDF ID to the invoice_input sheet
var pdf = conv.getAs("application/pdf");
var fileId = DriveApp.createFile(pdf).getId();
// Gets the PDF file by ID
var thisPDF = DriveApp.getFileById(fileId);
// Adds the PDF to the Folder
targetFolder.addFile(thisPDF);
// Removes the PDF from the root.
rootFolder.removeFile(thisPDF);
// Deletes the duplicated document
conv.setTrashed(true);
}