ref和range哪个性能更好?
在处理大型电子表格时,尤其是用脚本自动化操作,比如用 Google Apps Script 或 VBA 写宏,经常会遇到选择使用 ref 还是 range 的问题。很多人以为这只是写法不同,其实背后对运行速度的影响差别不小。
先说结果:在大多数实际场景下,直接操作 range 比通过 ref 引用性能更好。原因在于 ref 通常是间接引用,多了一层解析过程,而 range 是直接定位单元格区域,执行更干脆。
一个真实例子:批量修改数据
假设你要更新 A1 到 A10000 这一列的值,把每个单元格的内容变成大写。如果用 ref 方式,可能会这样写:
const sheet = SpreadsheetApp.getActiveSheet();
const dataRange = sheet.getRange("A1:A10000");
const values = dataRange.getValues();
values.forEach((row, i) => {
values[i][0] = row[0].toString().toUpperCase();
});
// 通过 ref 设置回去
sheet.getRange("A1:A10000").setValues(values);这段代码没问题,但如果你反复调用 getRange("A1:A10000"),每次都会重新解析字符串,系统得去“翻译”这个地址。虽然一次看不出差别,但在循环或多个操作中,这种开销会叠加。
更高效的做法是,先把 range 存成变量,避免重复查找:
const sheet = SpreadsheetApp.getActiveSheet();
const targetRange = sheet.getRange("A1:A10000"); // 只解析一次
const values = targetRange.getValues();
values.forEach((row, i) => {
values[i][0] = row[0].toString().toUpperCase();
});
targetRange.setValues(values); // 复用同一个 range 对象这样做不仅减少了解析次数,还降低了内存中的对象创建频率,整体执行时间能缩短 20% 到 40%,尤其在老旧设备上更明显。
ref 的使用场景并不全坏
ref 在某些动态场景下仍有优势。比如你写一个通用模板,公式里用 INDIRECT("Sheet"&A1&"!B1") 这类 ref 引用,能灵活切换工作表。但这属于公式层面的动态需求,不适合高频操作。
再比如,你在写一个配置驱动的报表系统,某个单元格存的是数据区域名称(如“SalesQ1”),然后用 ref 去读取对应区域。这时候用 ref 是合理的,毕竟灵活性优先。
但一旦进入批量处理、循环更新这类性能敏感的环节,就该换成预定义的 range 操作。
小技巧:减少 getRange 调用次数
很多人习惯每次要用就写一次 getRange,其实可以提前缓存。比如你要同时改 A 列和 B 列:
const sheet = SpreadsheetApp.getActiveSheet();
const rangeA = sheet.getRange("A1:A10000");
const rangeB = sheet.getRange("B1:B10000");
const valuesA = rangeA.getValues();
const valuesB = rangeB.getValues();
// 处理逻辑...
rangeA.setValues(valuesA);
rangeB.setValues(valuesB);虽然写了两次 getRange,但只各一次,没有在循环里反复调用。比用 ref 字符串拼接再解析要快得多。
如果你发现脚本运行越来越慢,特别是数据量上来之后卡顿明显,不妨检查一下是不是到处都在用字符串形式的 ref 定位区域。换成直接 range 操作,往往会有意外之喜。