数组比在Google Scripts中访问Google表格单元格快多少?

BAM*_*BAM 3 javascript arrays google-sheets google-apps-script

在Google脚本中访问和操作数组与访问和操作Google工作表中的数据相比要快多少?

这是应用程序:

我正在制定一个为员工创建计划的计划.我的策略是创建每天可用员工的列表,随机化列表,然后根据特定参数逐个将随机员工插入每​​个开放时段.然后重复一周中的每一天,直到计划完成.

有时在给定随机列表的情况下不满足参数,我需要重新启动循环.平均而言,我将运行~1100次循环迭代,直到计划被填满.如果GoogleScript运行> 6分钟,则会导致该功能超时并自动停止.

我的功能是访问来自GoogleSheets的数据和直接从函数中的数组访问数据.一般来说,重写我的函数是否会有明显的差异,以便所有数据都直接在数组中存储和操作?

teh*_*wch 7

影响程度将取决于您正在做多少读写.如果当前使用了大量增量数据传输,那么改变您的方法可以带来巨大的好处.

调用Spreadsheet API通常需要0.01秒或更长时间才能完成.调用导入/导出数据,或致电子功能,将需要更长的时间(例如getDataRange,getValue(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);
}
Run Code Online (Sandbox Code Playgroud)

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