Google Sheets 脚本,自定义函数 运行 时间错误(30 秒)。如何使函数 运行 更快?

Google Sheets Script, Custom function runtime error (30seconds). How to make function run faster?

我正在尝试创建一个循环遍历“M”列并将每个单元格乘以一个常数(例如,10.5)的函数。我终于设法创建了一个执行此操作的函数,但它需要时间来执行并在完成之前遇到运行时错误,因为它需要超过 30 秒才能完全执行。你们认为有可能以某种方式加速我的代码吗?如果有人能指出我正确的方向,我将不胜感激。下面是我的代码。

function onEdit(e) {
  var ss = e.source;
  var cell = e.range;

  if(cell.getRow() == 1 && cell.getColumn() == 13 && e.value != null){

    if (cell.getDisplayValue() == 'Currency EURO') {
      var valuta = 10.5;
    }
    if (cell.getDisplayValue() == 'Currency Pund') {
      var valuta = 12.31;
    }


    var range = ss.getRange("M:M");
    var count = range.getDisplayValues();

    for(var i=2;i<count.length;i++){


      ss.getRange("M"+ i).setValue(Number(ss.getRange("M"+ i).getDisplayValue())*valuta);

      }


  }
}

我认为问题在于您过多地使用了电子表格函数 - 您基本上是在 for 循环的每次迭代中与电子表格进行交互。这有很大的开销。

我提出两个想法:

1.代码修复: 我建议尽可能少地使用电子表格功能。它们非常昂贵。这意味着只检索一次范围,并且只更新一次范围。

这是我的建议:

function onEdit(e) {
  var ss = e.source;
  var cell = e.range;

  if(cell.getRow() == 1 && cell.getColumn() == 13 && e.value != null){

    if (cell.getDisplayValue() == 'Currency EURO') {
      var valuta = 10.5;
    }
    if (cell.getDisplayValue() == 'Currency Pund') {
      var valuta = 12.31;
    }

    // This is a reference to the range
    var range = ss.getRange("M:M");
    // This actually reads the values - do it only once
    var count = range.getDisplayValues();

    // This updates the count variable - does not interact with the spreadsheet yet
    for(var i=2;i<count.length;i++){
       count[i][0] *= valuta;
    }

    // This updates the range - done only once.
    range.setValues(count);
  }
}

代码尚未经过测试,如果有任何错误需要修复,请告诉我。

2。可选 :看看 - 特别是模式 #3。 如果在获取范围时忽略空白值,则可以使其更快。

  function onEdit(e) {

    const range = e.range;

    if (range.getRow() === 1 && range.getColumn() === 13 && e.value) {

      let valuta;
      if (e.value === 'Currency EURO') { valuta = 10.5 }
      if (e.value === 'Currency Pund') { valuta = 12.31 }

      const sheet = e.source.getActiveSheet()
      const values = sheet.getRange(`M2:M`)
                          .getDisplayValues()
                          .filter(String)
                          .map(i => [Number(i) * valuta])

      sheet.getRange(2, 13, values.length, values[0].length).setValues(values)

    }

}

这是您的函数的优化版本。

  • 主要优化是所有数据更改都“一次性”处理 时间'.
  • 二次优化是只有一次调用values
  • 这也将处理任何空单元格,并避免第一行单元格。

这样试试:

function onEdit(e) {
  const sh = e.range.getSheet();
  if (sh.getName() == "Sheet Name" && e.range.rowStart == 1 && e.range.columnStart == 13 && e.value != null) {
    if (e.range.getDisplayValue() == 'Currency EURO') {
      var valuta = 10.5;
    }
    if (e.range.getDisplayValue() == 'Currency Pund') {
      var valuta = 12.31;
    }
    let vs = sh.getRange("M2:M" + sh.getLastRow()).getDisplayValues().flat().map((e,i) => [e * valuta] )
    sh.getRange("M2:M"+sh.getLastRow()).setValues(vs));
  }
}