【问题标题】:How much faster are arrays than accessing Google Sheets cells within Google Scripts?数组比访问 Google Scripts 中的 Google Sheets 单元格快多少?
【发布时间】:2018-08-07 18:37:56
【问题描述】:

在 google 脚本中访问和操作数组与从 google 表格中访问和操作数据相比要快多少?

这是应用程序:

我正在制定一个计划来为员工制定时间表。我的策略是为每天创建一个可用员工列表,将列表随机化,然后根据特定参数将随机员工一个一个插入每个空缺的位置。然后重复一周中的每一天,直到排满为止。

有时给定随机列表不满足参数,我需要重新启动循环。平均而言,我将运行约 1100 次循环迭代,直到计划被填满。如果 GoogleScript 运行时间超过 6 分钟,则会导致函数超时并自动停止。

我的函数混合了从 GoogleSheets 访问数据和直接从函数内的数组访问数据。一般来说,重写我的函数,以便将所有数据直接存储在数组中并进行操作,会有明显的不同吗?

【问题讨论】:

    标签: javascript arrays google-apps-script google-sheets


    【解决方案1】:

    影响程度取决于您的阅读和写作量。如果当前使用大量增量数据传输,那么改变您的方法可以产生巨大的好处。

    对电子表格 API 的调用通常需要 0.01 秒或更长时间才能完成。导入/导出数据或调用子函数的调用将花费更长的时间(例如getDataRangegetValue(s)setValue(s))。 Apps 脚本足够聪明,可以优化一些连续调用,但如果您是交替读取和写入,那么 Google 端将无法为您提供帮助。
    您可以在View -> Execution Transcript 菜单上查看此计时数据。

    我的建议是将任何现有的基于单元格的验证公式移动到脚本函数中,这些函数对传递的员工姓名、员工与他们已经“工作”的班次之间的对象映射以及提议的上班班次进行操作。然后,您可以使用 1 个调用来导入员工 - 日可用性列表,并且对于每一天,对于每个班次,验证随机选择的可用员工是否可以工作,因为他们在调度期间之前的班次。最后,您将对象写回工作表。


    定时脚本(由于连续读取而被谷歌内部优化)

    function writeRand_(rows, cols)
    {
      var datasheet = SpreadsheetApp.openById(ssid).getSheetByName('Sheet1');
      datasheet.getDataRange().clearContent();
      var rand = [];
      for(var row = 0; row < rows; ++row)
      {
        var data = [];
        for(var col = 0; col < cols; ++col)
          data.push(Math.random());
        rand.push(data);
      }
      datasheet.getRange(1, 1, rand.length, rand[0].length).setValues(rand);
      return datasheet;
    }
    
    function readAndTime()
    {
      var rows = 50, cols = 8;
      var datasheet = writeRand_(rows, cols);
      // sum one-by-one
      var sum1 = 0;
      var startRangeSum = new Date().getTime();
      for(var row = 1; row <= rows; ++row)
        for(var col = 1; col <= cols; ++col)
          sum1 += datasheet.getRange(row, col).getValue()-0;
      var endRangeSum = new Date().getTime();
      // Read all, then sum.
      var sum2 = 0;
      var startArraySum = new Date().getTime();
      var inputs = datasheet.getDataRange().getValues();
      for(var row = 0; row < inputs.length; ++row)
        for(var col = 0; col < inputs[0].length; ++col)
          sum2 += inputs[row][col]-0;
      var endArraySum = new Date().getTime();
      Logger.log("Value count: " + rows * cols);
      Logger.log("Range sum: " + (endRangeSum - startRangeSum)/1000 + " sec. " + sum1);
      Logger.log("Array sum: " + (endArraySum - startArraySum)/1000 + " sec. " + sum2);
    }
    

    上面给出了 ~.8s 的范围和 .2s 的数组 - 而 .2s 基本上都是由于调用 getDataRange() 以使 inputs 所需的时间

    【讨论】:

      【解决方案2】:

      tehhowch 说得对 =) 我就是这样做的。

      /* The first couple of nested loops use only reading methods as well as based on this 
          they pick up cells whose value must be changed in the array for next loop
      */
      
      for (var rowIndex = editedCell.getRow(); rowIndex <= wageGrid.getLastRow(); rowIndex++) {
        if (weBreak) break;
      
        for (var collIndex = (rowIndex == editedCell.getRow()) ? (editedCell.getColumn() + 1) : wageGrid.getColumn(); collIndex <= wageGrid.getLastColumn(); collIndex++) {
      
          var cell = aSheet.getRange(rowIndex, collIndex);
          var cellFontColor = cell.getFontColor();
          var cellYearAndMonth = aSheet.getRange(rowIndex, 1).getValue();
          var cellDay = aSheet.getRange(1, collIndex).getValue();
      
          if (cellFontColor == "#ff0000") {
      
            weBreak = true;
            break;
          }
          if (aSheet.getRange(rowIndex, 1).getValue().getMonth() == cellYearAndMonth.getMonth()) {
      
            cellsToSetValue.push(cell);
          }
        }
      }
      
      //the next loop has an array of cell and perform only "set" methods
      
      for (var cellIndex = 0; cellIndex <= cellsToSetValue.length; cellIndex++) {
      
        cellsToSetValue[cellIndex].setValue(evt.value);
      }
      

      因此,当 API 优化“get”和“set”方法的工作时只有两次延迟,并且它们之间的一切都发生得很快)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-19
        • 1970-01-01
        • 2017-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-23
        相关资源
        最近更新 更多