3

我再次回到 SO 来解决 GAS 问题,因为我还不太熟悉 Javascript/GAS。基于以有效方式处理函数调用的方法,我对脚本运行速度有多慢感到有些麻烦。

我在几个地方读过(啊,就是在这里),为获取解析设置值(至少在电子表格中)执行“全部读取”然后“全部写入”执行“获取-一,写一个”方法(出于显而易见的原因,这是有道理的)。

我知道如何获取 Range 中的所有值,但我不确定如何通过(多维)数组、处理数据并相应地设置新 Range。

问题:该函数启动大约需要 2 秒,运行 50 行大约需要 5 秒。问题是,我可能会在此电子表格中有数千行,并且运行此函数以确保正确地对数据进行后处理,以便 Boomerang Calendar 正确获取时间数据在我看来有点荒谬。对于需要处理的每一列数据,该脚本需要两倍的时间,这太可怕了。我担心在下一个学期我会经常超过我的“GAS 处理时间限制”。

这是起始代码(不好,我承认):

function fixApostrophes() {
  // Get the active spreadsheet to run the script on
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  // Get the active sheet within the document to run the script on
  var sheet = spreadsheet.getActiveSheet();

  // Get max number of rows needed to process
  var maxRows = sheet.getLastRow();

  // Get the range for the startTime column and endTime column
  var apostropheRange = sheet.getRange(1, 10, maxRows, 2);

  // Get the value in each cell, remove apostrophes from the start,
  // and replace the value in that cell
  for (var i = 1; i < apostropheRange.getNumRows(); ++i) {

    // Get the cells for startTime and endTime to speed things up a bit
    var startCell = apostropheRange.getCell(i, 1);
    var endCell = apostropheRange.getCell(i, 2);

    // Get the values for startTime and endTime
    var startTime = startCell.getValue();
    var endTime = endCell.getValue();

    // Remove apostrophes from start of startTime
    while(startTime.charAt(0) == "'") {
      startTime = startTime.substring(1);
    }

    // Remove apostrophes from start of startTime
    while(endTime.charAt(0) == "'") {
      endTime = endTime.substring(1);
    }

    // Set the values for startTime and endTime
    startCell.setValue(startTime);
    endCell.setValue(endTime);
  }
}

这与我之前关于修复时间格式撇号问题的问题高度相关,该问题破坏了用于安排事件的 Boomerang 日历功能。

解决方案:使用函数将 Range 中的值拉入二维数组Range.getValues()。处理二维数组中的每个值(逐行可能是最合乎逻辑的方法),然后用新值更新已编辑值的索引(参见代码中的 Srik-answer 注释)。之后,使用 . 将 2D 数组中的元素放回原始 Range 中Range.setValues(2Darray)。如果你遇到它,我希望这对你有帮助!这也比在我的原始代码中看到的多次调用 API 快得多

function myNewLibraryFunction(startCol, numColumns) {

  // Get the active spreadsheet to run the script on
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  // Get the active sheet within the document to run the script on
  var sheet = spreadsheet.getActiveSheet();

  // Get max number of rows needed to process
  var maxRows = sheet.getLastRow();

  // Get the range for the startTime column and endTime column
  var dataRange = sheet.getRange(1, startCol, maxRows, numColumns);
  var values = dataRange.getValues();

  // Get the value in each cell, remove apostrophes from the start,
  // and replace the value in that cell
  for (var i = 1; i < maxRows; ++i) {

// Get the values for startTime and endTime
var startTime = values[i][0];
var endTime = values[i][1];

    // Remove apostrophes from start of startTime
    while(startTime.charAt(0) == "'") {
      startTime = startTime.substring(1);
    }

    // Remove apostrophes from start of startTime
    while(endTime.charAt(0) == "'") {
      endTime = endTime.substring(1);
    }

    values[i][0] = startTime; // New stuff from Srik's answer
    values[i][1] = endTime; // New stuff from Srik's answer
  }
  dataRange.setValues(values);
  SpreadsheetApp.flush(); // New stuff from Srik's answer
}
4

1 回答 1

3

基本上,您对 GAS 中列出的 API 进行的大多数函数调用都需要比常规 JavaScript 更多的时间。在您的情况下,减少对 Range 和 Sheet 类的调用次数

function fixApostrophes() {
  // Get the active spreadsheet to run the script on
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  // Get the active sheet within the document to run the script on
  var sheet = spreadsheet.getActiveSheet();

  // 1. Replace two calls and many other calls later with one. 
  var dataRange = sheet.getDataRange(); 
  var values = dataRange.getValues();// a 2D array

  // Get the value in each cell, remove apostrophes from the start,
  // and replace the value in that cell
  for (var i = 1; i < values .length ; ++i) {

    // Get the values for startTime and endTime
    var startTime = values [i][0];
    var endTime = values [i][1];

    // Remove apostrophes from start of startTime
    // These are okay. Regular Javascript - not time consuming
    while(startTime.charAt(0) == "'") {
      startTime = startTime.substring(1);
    }

    // Remove apostrophes from start of startTime
    while(endTime.charAt(0) == "'") {
      endTime = endTime.substring(1);
    }

  }

  dataRange.setValues(values);
}

提示:您可以在执行记录中查看每个调用花费了多少时间

于 2013-05-22T17:47:01.673 回答