繁体   English   中英

复杂的转置超过了 Google Apps 脚本中的运行时间

[英]Complex transpose exceeding run time in Google Apps Script

我在单列中接收数据,必须将其转换为单独的记录。 一些记录的长度为 12 个字符,其他的为 10 个,其余为 9 个。此外,10 个和 9 个字符长的记录中的后 2 个值必须分别向右移动 1 个和 2 个字段。 给定记录中的第一个值始终是日期。 我创建了以下代码运行良好,除了它在大约 6 分钟和 77 条记录后超时。 我需要能够处理 15 倍甚至更多。

我在每个 if 语句的 else 部分嵌入了日期对象的计算,并嵌套了后续的 if 语句,以减少不必要的计算。 这让我从大约 48 条记录增加到 77 条。

非常感谢任何聪明的见解🙂


function transposeNew(){
  let ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  let lr = ss.getRange("A13").getDataRegion().getLastRow();
  let sr = 13

  // get the data column
  let data = ss.getRange(sr,1,lr-sr,1).getValues();

  // set up the rows loop
  let pasteRow = 2;
  let arrayField = 0;
  while (arrayField < data.length){
    //use the new Date() constructor to create a date object with the date value passed
    let isDate12 = new Date(data[arrayField+12]).getFullYear(); //processed; size input;record should include 12 rows & 13th should be a date to begin the next row
    if (isDate12 === 2020) {
      let record = data.slice(arrayField, arrayField+12);
      let recordTr = transposeSub(record);
      ss.getRange(pasteRow, 5, 1, 12).setValues(recordTr);
      arrayField = arrayField + 12;
    }
    else {
      let isDate10 = new Date(data[arrayField+10]).getFullYear(); //unprocessed;size input
      if (isDate10 === 2020) {
        let record = data.slice(arrayField, arrayField+10);
        let record1 = record.slice(0,8);
        let record1Tr = transposeSub(record1);
        let record2 = record.slice(8,10);
        let record2Tr = transposeSub(record2);
        ss.getRange(pasteRow, 5, 1, 8).setValues(record1Tr);
        ss.getRange(pasteRow, 14, 1, 2).setValues(record2Tr);
        arrayField = arrayField + 10;
      }
      else {
        let isDate9 = new Date(data[arrayField+9]).getFullYear(); //unprocessed;no size 
          input
        if (isDate9 === 2020) {
          let record = data.slice(arrayField, arrayField+10);
          let record1 = record.slice(0,7);
          let record1Tr = transposeSub(record1);
          let record2 = record.slice(7,9);
          let record2Tr = transposeSub(record2);
          ss.getRange(pasteRow, 5, 1, 7).setValues(record1Tr);
          ss.getRange(pasteRow, 14, 1, 2).setValues(record2Tr);
          arrayField = arrayField + 9;
        }
      }
    }
    pasteRow ++;
  }
}

function transposeSub(a)
{
  return Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
}

我看到您创建了一个循环,并在此while语句中多次调用 SpreadsheetApp 函数。 这会创建与电子表格的连接,读取/更改其数据并多次关闭连接,这就是您的代码运行时间过长的原因。 请查看GAS 最佳实践批处理操作部分

你应该考虑放逐任何get/setValue()while相反,调用getValues()之前保持在JavaScript数组的所有值while再使用setValues()while在一次写入所有输出。 答案探讨了所描述的概念。

所以事实证明问题是循环标准中的一个缺陷; 菜鸟错误。 存在数据异常,以至于一条记录不符合任何 if 语句中的标准,因此循环一直在继续。 我通过在工作表上的每条记录旁边插入 pasteRow 和 arrayField 的值来发现这一点,以便我可以看到它在哪里中断。 有趣的是,记录停止了,但 pasteRow 和 arrayField 值在应用程序退出之前持续到了 20,000 秒。

我确实注意到@Bruno Polo 和@Cooper 提供的反馈是正确的。 发布后不久,我对其进行了修改,将记录推送到一个新数组中,并在完成后粘贴该数组。 由于上述相同的原因,这失败了。 我想现在我明白了这个问题,我会回到那个版本。

谢谢你和我一起看这个。 这是一个非凡的专家社区,我从中学到了很多! 😁

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM