首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Google脚本运行速度太慢

Google脚本运行速度太慢
EN

Stack Overflow用户
提问于 2016-08-31 01:39:56
回答 3查看 3.3K关注 0票数 1

我目前正在写一个google脚本,不幸的是运行太慢了。(超过6分钟限制)。该脚本打开一个文档,替换两个字符串(在google工作表中设置),将其保存为PDF。没什么花哨的。

我大约有200个这样的文档要运行这个脚本,但在6分钟的限制内,它只能运行6个。谷歌脚本就是这么慢吗,还是我无意中写出了效率最低的谷歌脚本?

代码语言:javascript
复制
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;
}

任何关于如何优化的指点都将非常感谢。我是谷歌脚本和编程的新手,所以不用大惊小怪,哈哈。如果我没有正确地使用这块板子,我道歉。请告诉我,我会改正的。

EN

回答 3

Stack Overflow用户

发布于 2016-08-31 06:27:46

我立即注意到您有一个未定义的变量n。它在队列中:

var thisRange = sheet.getRange("A" + n + ":C" + n);

这应该会使代码完全不可用。将这些变量更改为i后,我能够成功地运行代码整整6分钟。在此期间,它能够循环大约41.5次。它创建了第9-53行的文件,但在能够将最后一个文件添加到正确的文件夹之前停止。

查看执行记录,您最长的操作是创建、移动和删除文件的几次调用。

您还定义了range,然后再也不使用这个变量,这样就没有必要使用它了。

我在我自己多次使用的结构和方法中重写了代码。我能够完全处理第9-59行。该方法能够将其扩展6行。我建议添加一个超时触发器,每隔5分55秒停止一次功能,然后在5秒后再次重新启动。关于javascript时间的指南可以在here上找到。我还使用了一种不同的匹配方法;使用RegEx。关于RegEx以及如何最小化处理时间,有大量的指南。我在这方面一点也不精通。

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2016-08-31 05:11:31

(注意:我还没有测试过这个,但应该可以让你开始)

一些想法:

  1. 将"getRange“命令移出for循环。
  2. 读取for循环外部的模板、targetFolder和rootFolder,并将它们作为参数传递给genDoc。重新使用“possible.
  3. Write”和“individually.
  4. Do”,用“

”和“

  1. ”代替individually.
  2. Do不返回任何内容。

所以就像这样:

代码语言:javascript
复制
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);
}
票数 0
EN

Stack Overflow用户

发布于 2021-09-15 07:09:13

如果您的代码已得到改进,请考虑使用触发器,但请记住,代码在完成后需要删除触发器,因为您可以创建的数量是有限制的。

初始代码应该在需要创建的文档工作表中设置一个列表,然后设置一个触发器来运行create document。

create document代码然后可以检查是否有更多的文档要从列表中创建,如果有,则创建文档并设置下一个触发器,删除旧触发器。

这样一来,一个文档就会成功运行,如果还有更多的事情要做,那么很快就会触发下一个文档。

记住,除了6分钟的限制之外,还有总的时间限制。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39233844

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档