加速Google脚本值访问和元数据?

时间:2019-11-21 09:20:38

标签: google-apps-script google-sheets

我编写了许多函数,这些函数可以查看单元格值并使用它们来设置其他单元格值或开发人员元数据,还可以查看元数据来决定要做什么。当我在对电子表格的功能进行压力测试时,为大范围的单元格运行脚本会超出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]

关于使这些通话变慢的任何想法?有没有一种方法可以优化代码,使其尽可能快地运行?

1 个答案:

答案 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

配额

  • 简单触发器的执行限制为30秒。
  • “安装” onEdit触发器时,该执行限制增加到“正常”脚本运行时的级别,即,对于Consumer,G Suite Free和G Suite Basic / Gov为6分钟,对于Early Access和G为30分钟套件企业/企业/教育。
  • 每个Consumer帐户每天允许的总触发运行时间为90分钟,G Suite免费版帐户为3小时,高级帐户为6小时。

参考文献