Google apps script 加快从脚本到google工作表中分散单元格的更改

Google apps script 加快从脚本到google工作表中分散单元格的更改,google-apps-script,google-sheets,Google Apps Script,Google Sheets,我有一张表,显示了基于其他背景表的计算结果。更改是手动进行的,但“摘要”表仅限于公式。这些变化出现在分散的单元中,大部分是不连续的 我想突出显示在手工更改背景纸后,汇总表中已更改的单元格。为此,我使用了第二个摘要表,它从主摘要表的副本开始 最后一个要素是编辑后运行的脚本。它遍历摘要范围并将值与第二个副本进行比较。任何差异都会在主摘要中突出显示,并复制回第二个摘要 这个过程确实有效,但速度相当慢,我认为是因为更新。伪代码: var src = summary.getRange(...) var d

我有一张表,显示了基于其他背景表的计算结果。更改是手动进行的,但“摘要”表仅限于公式。这些变化出现在分散的单元中,大部分是不连续的

我想突出显示在手工更改背景纸后,汇总表中已更改的单元格。为此,我使用了第二个摘要表,它从主摘要表的副本开始

最后一个要素是编辑后运行的脚本。它遍历摘要范围并将值与第二个副本进行比较。任何差异都会在主摘要中突出显示,并复制回第二个摘要

这个过程确实有效,但速度相当慢,我认为是因为更新。伪代码:

var src = summary.getRange(...)
var dst = copy.getRange(...)

var src_cell;
var dst_cell;

src.setBackground('white'); // Bulk reset of changes

for (row = 1; row < src.getNumRows(); row++) {
    for (col = 1; col < src.getNumColumns(); col++) {
        src_cell = src.getCell(row, col);
        dst_cell = src.getCell(row, col);

        if (src_cell.getDisplayValue() != dst_cell.getDisplayValue()) {
            dst_cell.setValue(src_cell.getDisplayValue());
            src_cell.setBackground('gray');
        }
    }
}
var src=summary.getRange(…)
var dst=copy.getRange(…)
var-src_细胞;
var-dst_细胞;
src.立根背景(“白色”);//批量重置更改
对于(行=1;行
我认为没有办法批量更新分散的范围,这似乎是一个简单的解决方案

我正在寻找加快这一过程的方法,无论是在脚本中还是通过使用其他策略。

对于每个官员,您应该批量读取相关的单元格数据,而不是重复读取或可能写入值。此语句假定
dst
中的设置值不会影响将来读取的值

因此,最简单的更改是在
src
dst
上使用
Range#getDisplayValues

...
src.setBackground("white");
var srcValues = src.getDisplayValues();
var dstValues = dst.getDisplayValues();

srcValues.forEach(function (srcRow, r) {
  var dstRow = dstValues[r];
  srcRow.forEach(function (value, c) {
    if (value !== dstRow[c]) {
      dst.getCell(r + 1, c + 1).setValue(value);
      src.getCell(r + 1, c + 1).setBackground("gray");
    }
  });
});
另一个优化是使用类来批处理更改。为此,您需要一个单元格/范围符号数组,可以使用R1C1或A1样式的寻址。R1C1是最容易计算的

...
var dstChanges = [];
var srcChanges = [];
...

    if (value !== dstRow[c]) {
      dstChanges.push({row: r + 1, col: c + 1, newValue: value});
      srcChanges.push({row: r + 1, col: c + 1});
    }
...

if (srcChanges.length > 0) {
  var srcRow = src.getRow();
  var dstRow = dst.getRow();
  var srcCol = src.getColumn();
  var dstCol = dst.getColumn();
  copy.getRangeList(dstChanges.map(function (obj) {
    return "R" + (obj.row + dstRow) + "C" + (obj.col + dstCol);
  }).getRanges().forEach(function (rg, i) {
    rg.setValue(dstChanges[i].newValue);
  });
  summary.getRangeList(srcChanges.map(function (obj) {
    return "R" + (obj.row + srcRow) + "C" + (obj.col + srcCol);
  }).setBackground("gray");
}
...
其他参考文献


太好了,我刚开始使用天然气,所以这种先进的技术正是我所需要的。有没有一个地方可以让你确定通话是否慢?例如,我认为getRange()很慢,但随后的range.getDisplayValue()会很快,因为已经检索到了该范围。但从您的回答中,我发现最好是一次批量获取所有值。@Álex不,这只是熟悉的结果。例如,获取一个
范围
引用并不是那么糟糕,即使该范围跨越了大量单元格计数。然而,仅仅因为大量的背景工作,获取该范围的值/显示值将是有成本的。对于较小的范围,调用可能需要相似的时间量,或者更少的时间来获取值。Google确实会对任何API调用执行一些缓存和优化,但通常最好是在纯JavaScript中尽可能多地执行工作。