google-apps-script - 加快从脚本到谷歌表格中分散单元格的更改
问题描述
我有一张表,显示基于其他支持表的计算结果。更改是手动进行的,但“摘要”表只是公式。这些变化出现在分散的细胞中,大部分是不连续的。
我想突出显示在手动更改支持表后摘要表中哪些单元格发生了更改。为此,我使用了第二张摘要表,它作为主要摘要表的副本。
最后一个成分是在编辑后运行的脚本。它遍历汇总范围并将值与第二个副本进行比较。任何差异都会在主摘要中突出显示并复制回第二个摘要。
这个过程确实有效,但速度很慢,我认为是由于更新。伪代码:
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');
}
}
}
我认为没有办法批量更新分散的范围,这似乎是一个简单的解决方案。
我正在寻找加快此过程的方法,无论是在脚本中还是通过使用其他策略。
解决方案
根据官方“最佳实践”,您应该批量读取关联的单元格数据,而不是重复读取和可能写入值。此语句确实假设设置值dst
不会影响未来读取的值。
因此,最简单的更改是使用Range#getDisplayValues
onsrc
和dst
:
...
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");
}
});
});
另一个优化是使用RangeList
类来批处理更改。要创建RangeList
,您需要一个单元格/范围符号数组,它可以使用 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");
}
...
其他参考
推荐阅读
- documentation - Raku 的内省可以列出不同文件/模块中的所有多候选吗?
- java - WADL2JAVA:Gradle 插件
- stripe-payments - 条纹卡支票返回 null
- c++ - 如何在 MacOS XCode 上以发布模式编译?
- javascript - 检测移动设备上的触摸移动事件
- android - React native 我的应用程序不会显示 API GET 调用的任何结果
- c# - 为不同的难度创造多个高分
- c# - 有没有办法在 JSON 文件的值中获取键名
- bash - 使用 sed 更改 URL 中的斜线方向
- struct - 错误:TSortedMap 以自定义结构为键,重载 operator<