【发布时间】:2022-08-18 15:11:24
【问题描述】:
假设我得到范围 A2:B2:
sheet.getRange(\"A2:B2\").getValues();
但是我在 A1:B1 下添加了一行,所以现在我的值在 A3:B3 中
Apps 脚本是否可以动态捕获我的值现在在另一个范围内?
如果没有,关于如何动态获取移动行范围的任何替代想法?
标签: google-apps-script google-sheets
假设我得到范围 A2:B2:
sheet.getRange(\"A2:B2\").getValues();
但是我在 A1:B1 下添加了一行,所以现在我的值在 A3:B3 中
Apps 脚本是否可以动态捕获我的值现在在另一个范围内?
如果没有,关于如何动态获取移动行范围的任何替代想法?
标签: google-apps-script google-sheets
我相信你的目标如下。
在这种情况下,如何使用命名范围、OnChange 触发器和 PropertiesService?我认为当使用这些时,您的目标可能会实现。准备好示例脚本后,如下所示。
作为示例,请将单元格“A2:B2”的命名范围创建为“sampleNamedRange1”。 Ref
请将以下脚本复制并粘贴到电子表格的脚本编辑器中。还有,please install OnChange trigger to the function installedOnChange。
function installedOnChange(e) {
var originalRange = "A2:B2";
var nameOfNamedRange = "sampleNamedRange1";
if (!["INSERT_ROW", "REMOVE_ROW"].includes(e.changeType)) return;
var p = PropertiesService.getScriptProperties();
var pv = p.getProperty("range");
if (!pv) pv = originalRange;
var range = e.source.getRangeByName(nameOfNamedRange);
var a1Notation = range.getA1Notation();
if (a1Notation != pv) {
p.setProperty("range", a1Notation);
Browser.msgBox(`Range was changed from ${pv} to "${a1Notation}". Original range is "${originalRange}".`);
}
// var values = range.getValues(); // The values are not changed because of the named range.
}
在这种情况下,请I added a row under A1:B1。这样,脚本将由 OnChange 触发器自动运行。而且,您可以看到对话框。您可以看到如下图所示的演示。
从讨论中,我了解到您想使用命名范围的名称来检索特定工作表的命名范围。在这种情况下,示例脚本如下。
const range = SpreadsheetApp.getActive().getSheetByName("sheetName").getRange("nameOfNamedRange");
或者
const range = SpreadsheetApp.getActive().getSheetByName("sheetName").getNamedRanges().find(n => n.getName() == "snameOfNamedRange").getRange();
const range = SpreadsheetApp.getActiveSheet().getRange("nameOfNamedRange");
或者
const range = SpreadsheetApp.getActiveSheet().getNamedRanges().find(n => n.getName() == "snameOfNamedRange").getRange();
【讨论】:
That's not my goal but thanks for your effort.,为了正确理解你的目标,能否提供一下细节?借此,我想确认一下。如果您能原谅我糟糕的英语水平,我将不胜感激。
I want to dynamically assign a value to getRange when the Values change.。可以问一下它的详细情况吗?当我能正确理解它时,我可以寻找解决方案或变通方法。
这可以通过DeveloperMetadata 实现。元数据可以设置为范围或工作表,每当移动此类数据(范围或工作表)时,相关的元数据也会随之移动。不幸的是,此元数据不能设置为任意范围,而只能设置为单列或单行。例如,使用A2:B2,我们必须将元数据设置为A 列、B 列和第2 行的整体。但是,一旦设置,就不再需要应用程序脚本。 Google 表格会自动跟踪此类数据的移动。
const setDevMetadata_ = (sheetName = 'Sheet1', rng = '2:2', key = 'a2b2') => {
SpreadsheetApp.getActive()
.getSheetByName(sheetName)
.getRange(rng)
.addDeveloperMetadata(key);
};
/**
* @description Set metadata to a specific range
* Unfortunately, this metadata cannot be set to arbitrary ranges, but only to single column or single row.
* For eg, with `A2:B2`, We have to set the metadata to the entirety of column A, column B and Row 2.
* @see https://stackoverflow.com/a/73376887
*/
const setDevMetadataToA2B2 = () => {
['2:2', 'A:A', 'B:B'].forEach((rng) => setDevMetadata_(undefined, rng));
};
/**
* @description Get a range with specific developer metadata key
*/
const getRangeWithKey = (sheetName = 'Sheet1', key = 'a2b2') => {
const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName),
devFinder = sheet.createDeveloperMetadataFinder(),
[rows, columns] = ['Row', 'Column'].map((rc) =>
devFinder
.withKey(key)
.withLocationType(
SpreadsheetApp.DeveloperMetadataLocationType[rc.toUpperCase()]
)
.find()
.map((devmetadata) =>
devmetadata.getLocation()[`get${rc}`]()[`get${rc}`]()
)
);
console.log({ rows, columns });
const rng = sheet.getRange(
rows[0],
columns[0],
rows[1] ? rows[1] - rows[0] + 1 : 1,
columns[1] ? columns[1] - columns[0] + 1 : 1
);
console.log(rng.getA1Notation());
return rng;
};
【讨论】:
.getRange() 并带有注释.getRange('a2:b2')。其他包括行列:如.getRange(2,1,1,2)。在我的示例中,我们使用 developermetadata 键调用:getRangeWithKey('Sheet1', 'a2b2')。为了正确返回范围,应该已经使用setDevMetadataToA2B2() 设置了元数据键。但是,代码中的那些字符串不会自动更改。您也许可以使用 @Tanaike 的代码和 google-apps-script-api 来达到相同的结果,但这很复杂