【问题标题】:How to reduce time of script execution with FormApp...getResponses()?如何使用 FormApp...getResponses() 减少脚本执行时间?
【发布时间】:2020-10-14 13:06:32
【问题描述】:

表单中内置的电子邮件收集功能为文本格式。我们有很多员工填写此表格,因此从下拉列表中选择比手动输入每个员工的电子邮件更方便。收集邮件的内置功能不允许使用下拉列表问题类型,所以我不得不禁用它并使用脚本将回复发送到电子邮件。

此外,当您在表单中选择其中一个选项(转移)时,您需要插入一个额外的带有数据的更正行。这也是由脚本完成的。

脚本运行良好,但不幸的是,它的执行时间达到了 45 秒。我认为这是异常大的。

更新代码:

var FORM_ID = '#####';
var SHEET_NAME = 'Operations';

function sendFormToEmail() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  console.time('section10'); // 25579ms
  var sheet = ss.getSheetByName(SHEET_NAME);
  console.timeEnd('section10');
  
  // Open a form by ID and log the responses to each question.
  var form = FormApp.openById(FORM_ID);
  
  var formResponses = form.getResponses();
  var i = formResponses.length - 1;
  var formResponse = formResponses[i]; // Last item
  var itemResponses = formResponse.getItemResponses();
  
  var length = itemResponses.length;
  Logger.log("length = " + length);

  var emailTo = itemResponses[0].getResponse();  // Returns the email if given
  var cp = itemResponses[1].getResponse();  // Counterparty
  var subject = "Input form: "+ cp;
  var datePay = itemResponses[2].getResponse();  // Date of the operation
  var dateAccept = itemResponses[3].getResponse();  // Date of acceptance
  var sum = itemResponses[4].getResponse() ;  // Amount
  var what = itemResponses[5].getResponse();  // Operation type

  var comm =  "Correction " + itemResponses[length - 1].getResponse(); // Last response
  var sum_1 = parseFloat(sum.replace(/,/, '.')) * (-1);  // Amount * (-1)
  var timestamp = new Date();
  var textBody = "Operation: " + timestamp + ";\n";

  for (var j = 0; j < itemResponses.length; j++) {
    var itemResponse = itemResponses[j];
    var resp = itemResponse.getResponse();
    textBody += itemResponse.getItem().getTitle() + "=" + resp + ";\n";
  }

  if (what == 'Transfer') { // If the transfer between your accounts
    var lr = sheet.getLastRow();
    sheet.insertRowBefore(lr);
    var values = [datePay, dateAccept, "", sum_1, "", "", "", "", comm, "", "", "", what, timestamp, "", "", ""];
    Logger.log(values);
    console.time('section12'); // 19449ms
    sheet.getRange(lr, 2, 1, 17).setValues([values]);
    console.timeEnd('section12')
  }
  
  if(emailTo !== undefined){
    GmailApp.sendEmail(emailTo, subject, textBody);
  }
}

起初我以为是验收单的大尺寸(约13000行)。我创建了一个表的副本,将其减少到几十行,但速度并没有增加多少。 然后我从表单中删除了答案(其中不到 9000 个)——同样的事情,我没有获得太多的性能提升。

有人知道如何更改脚本算法以提高其性能吗?

===

结论

感谢@TheMaster 对console.time() 的帮助。多亏了这个工具,我发现了代码中的瓶颈。更准确地说,代码运行良好,但它与代码交互的电子表格系统的结构有关。结构需要优化。 还有一个想法可能是针对 Google 开发人员的。如果有一种工具可以直观地(以图形方式)显示构成单个系统的电子表格和工作表之间的关系,那就太好了。也许具有某种反映其块之间交互时间的数值特征。这样可以快速消除系统中的此类瓶颈并进行改进。

【问题讨论】:

  • 您能否通过editing 将您的脚本更新添加到您的帖子中?
  • 尝试在代码的各个部分添加console.time('section1')console.timeEnd('section1') 以确定哪个部分花费的时间最多...如果您找出代码部分,请尝试找出确切的行通过在该部分中添加小节
  • Edit 添加此信息。你的床单可能膨胀了。删除工作表,删除每张工作表底部和右侧的空单元格
  • 是的,底部没有空行,右侧没有空列,我一直在跟踪。原因可能是电子表格超载。它有 30 张表格,所有表格都有一堆公式,其中大部分都与其他电子表格相关。系统的结构可能必须改变。
  • 考虑添加您的调试方式和您的发现作为答案。正如你所说,这可能是由于 import* 公式

标签: performance google-apps-script google-forms


【解决方案1】:

调查:

  • 使用每个代码段的console.time()console.timeEnd() 并计算到达每个代码段所花费的时间来确定问题。

问题:

正如the question comment chain 中所讨论的,这是由于包含许多工作表和导入公式的臃肿电子表格。这导致有更多时间来获取确切的工作表并使用 setValues:

console.time('section10'); // 25579ms 
var sheet = ss.getSheetByName(SHEET_NAME); 
console.timeEnd('section10');
//....
console.time('section12'); // 19449ms 
sheet.getRange(lr, 2, 1, 17).setValues([values]);
console.timeEnd('section12')

可能的解决方案:

  • 减少张数
  • 减少相互关联的电子表格(=import* 公式)
  • 删除每张工作表底部的空行和右侧的空列。

【讨论】:

    猜你喜欢
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    相关资源
    最近更新 更多