考虑这种情况。
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("2:2");
var values = range.getValues();
values[0][0] = "updated value"; //updating retrieved data
sheet.insertRowAfter(1); //here the problem appears
range.setValues(values); //trying to save updated row data - FAIL!
更新后的行值将被写入第2行(根据范围选择器“ 2:2”),而不是在新位置“ 3:3”。 结果:它将覆盖第2行的数据,而不是更新先前选择/加载的行,该行现在位于“ 3:3”位置,而不再位于“ 2:2”。
我正在寻找一种方法,即使由于在工作表中其他位置添加/删除的行/单元格而移动了范围,该范围的“地址”也保持不变。
在此虚拟示例中,我可以跟踪范围更改。但是在并行处理/更新工作表中,我不能简单地跟踪来自许多不同地方的所有更改。
到目前为止,我想出了一个解决方案,仅在SS的末尾添加新行(这不会更改上面任何行的范围,但是我希望能够在不影响已选择的情况下在表格顶部添加新行范围。 删除行也是危险的情况-也会更改范围的位置。
LockService不能真正解决问题,因为我在同一张工作表上有很多脚本(由于插件的速度性能,不使用集中式库)。
单元格或行的元数据似乎太复杂了,无法完成如此简单的任务。
从我的角度来看,即使对象范围在其他地方移动/移动,它也应保持其位置。否则,我看不到将Range作为对象的原因-如果它仅保留有关从何处拾取的固定信息。 欢迎任何建议。谢谢你。
答案 0 :(得分:0)
"2:2"
(第2行)中检索值。如果我的理解正确,那么这个答案如何?请认为这只是几个答案之一。
在您的脚本中,range
中的var range = sheet.getRange("2:2");
是常数。这样,即使插入行,该值也不会改变。这就是您遇到问题的原因。
我认为使用命名范围的想法将根据您的情况解决。但是your comment如下。
I just found, that namedRange is not capable actualize its own address, if something had changed in the sheet after initialize of a range.
当将第2行作为命名范围安装时,将一行插入到第1行的正下方时,命名范围的范围也会更改。但是从您的评论来看,我认为该命名范围可能尚未重新加载。
为了确认这一点,我想提出一个示例脚本。
在运行脚本之前,请在第2行安装一个命名范围,名称为sampleNamedRange
。然后,运行此脚本。
var ss = SpreadsheetApp.getActiveSpreadsheet(); // Added
var sheet = ss.getActiveSheet(); // Modified
// Retrieve the range from the namedRange.
// namedRange of "sampleNamedRange" is installed for the range of "2:2" of the active sheet.
var range = ss.getRangeByName("sampleNamedRange"); // Modified
var values = range.getValues();
values[0][0] = "updated value"; //updating retrieved data
sheet.insertRowAfter(1);
// Retrieve the range from the updated namedRange.
var range = ss.getRangeByName("sampleNamedRange"); // Added
range.setValues(values);
如果我误解了您的问题,而这不是您想要的结果,我表示歉意