我编写了许多函数,这些函数可以查看单元格值并使用它们来设置其他单元格值或开发人员元数据,还可以查看元数据来决定要做什么。当我在对电子表格的功能进行压力测试时,为大范围的单元格运行脚本会超出maximum runtime时遇到了问题。
研究它时,我注意到获取和设置预定义单元格的单元格值大约需要0.2秒,而查找和设置元数据则大约需要0.5-0.8秒。
我编写了一个示例脚本来演示此操作,但是由于某种原因,时间缩短了,我不知道这是否与单元格中的内容有关,或者电子表格较小还是....
但是,更改已经具有指定键元数据的工作表中的值并触发此脚本:
function onEdit(e){
timetest(e)
}
function timetest(e) {
var range = e.range;
var sheet = range.getSheet();
for (var r = 1; r <= range.getNumRows(); r++){
for (var c = 1; c <= range.getNumColumns(); c++){
var cell = range.getCell(r, c);
var value = cell.getValue();
var new_val = value + ' ' + r + c;
cell.setValue(new_val);
}
var metadata = sheet.createDeveloperMetadataFinder().withKey("Updated").find()
if (metadata.length > 0){
metadata[0].setValue(new_val)
} else {
sheet.addDeveloperMetadata("Updated", new_val, SpreadsheetApp.DeveloperMetadataVisibility.DOCUMENT);
}
}
}
为此
[19-11-21 01:05:44:105 PST] Starting execution
[19-11-21 01:05:44:252 PST] PropertiesService.getDocumentProperties() [0.14 seconds]
[19-11-21 01:05:44:253 PST] SpreadsheetApp.Range.getSheet() [0 seconds]
[19-11-21 01:05:44:254 PST] SpreadsheetApp.Range.getNumRows() [0 seconds]
[19-11-21 01:05:44:254 PST] SpreadsheetApp.Range.getNumColumns() [0 seconds]
[19-11-21 01:05:44:255 PST] SpreadsheetApp.Range.getCell([1, 1]) [0 seconds]
[19-11-21 01:05:44:357 PST] SpreadsheetApp.Range.getValue() [0.101 seconds]
[19-11-21 01:05:44:413 PST] SpreadsheetApp.Range.setValue([p 12 11]) [0.056 seconds]
[19-11-21 01:05:44:413 PST] SpreadsheetApp.Range.getNumColumns() [0 seconds]
[19-11-21 01:05:44:414 PST] SpreadsheetApp.Sheet.createDeveloperMetadataFinder() [0 seconds]
[19-11-21 01:05:44:414 PST] SpreadsheetApp.DeveloperMetadataFinder.withKey([Updated]) [0 seconds]
[19-11-21 01:05:44:682 PST] SpreadsheetApp.DeveloperMetadataFinder.find() [0.267 seconds]
[19-11-21 01:05:44:836 PST] SpreadsheetApp.DeveloperMetadata.setValue([p 12 11]) [0.153 seconds]
关于使这些通话变慢的任何想法?有没有一种方法可以优化代码,使其尽可能快地运行?
答案 0 :(得分:0)
在嵌套的for循环中,您正在向getCell()
,getValue()
和setValue()
发出请求。这会导致对Spreadsheets API的许多远程请求,这会降低脚本的速度。
为了大大提高脚本的性能,您可以通过一次调用(getValues()
)获得工作表中的所有数据,对其进行所需的操作,然后使用以下方法将其设置回工作表中还有一个电话(setValues()
)。
此外,我建议您将“元数据”操作带出循环,因为这似乎只对new_val
的最后一个值重要。这些修改后的最终代码如下:
function onEdit(e){
timetest(e)
}
function timetest(e) {
var range = e.range;
var sheet = range.getSheet();
var data = range.getValues();
var new_val;
for (var i=0; i<data.length; i++) {
var row = data[i];
for (var j=0; j<row.length; j++) {
var value = row[j];
new_val = value + ' ' + (i+1) + (j+1);
row[j] = new_val;
}
}
range.setValues(data);
if (data.length > 0 && data[0].length > 0) {
var metadata = sheet.createDeveloperMetadataFinder().withKey("Updated").find()
if (metadata.length > 0){
metadata[0].setValue(new_val)
} else {
sheet.addDeveloperMetadata("Updated", new_val, SpreadsheetApp.DeveloperMetadataVisibility.DOCUMENT);
}
}
}
最后,我建议您签出Best practices using Google Apps Script。