Google表格自定义公式有时候工作有时候不会

时间:2017-09-15 21:38:10

标签: google-apps-script google-sheets

我有一个spreadsheet,我在其中开发了一个名为RawVal的自定义函数:

function RawVal(BlockName) {
  try {
    var rawVal = 1;
    var thiSheet = SpreadsheetApp.getActiveSheet();
    var BlockRow = thiSheet.getRange("C:C").getValues().map(function(row) {return row[0];}).indexOf(BlockName);
    if (BlockRow > -1) {
      var baseVal = thiSheet.getRange("B" + (BlockRow+1)).getValue();
      var ingVal = thiSheet.getRange("D" + (BlockRow+1)).getValue();
      rawVal = Math.max(baseVal, ingVal);
      Logger.log(BlockName+": base="+baseVal+"; ing="+ingVal+"; max="+rawVal);
    }
    return rawVal;
  }
  catch (e) {
   Logger.log('RawVal yielded an error for " + Blockname + ": ' + e); 
  }
}

虽然函数很长,但目的是将每个行中输入一个中等大小的函数替换为:

=if(sumif(C:C,"Emerald Block",D:D)=0,sumif(C:C,"Emerald Block",B:B),sumif(C:C,"Emerald Block",D:D))

问题有时候会起作用,有时它也不会。它似乎与内容无关。之前工作的单元格可能会显示#NUM并出现错误"结果不是数字"。但是,如果我删除它并重新键入它(但奇怪的是不粘贴公式),大多数时候它会正确计算。注意:它没有停留在"正在加载",它实际上是在抛出错误。

调试日志没有用 - 而且不一致让我发疯。我做错了什么?

编辑:我用Logger.log替换了console.log的实例 - 单元格正确计算了6个小时,现在再次出现#NUM错误。

1 个答案:

答案 0 :(得分:0)

您的自定义函数似乎在许多地方使用(在工作表的每一行)。这一点以及他们在一段时间后停止工作的事实表明Google最终拒绝提供过多的计算时间。尝试遵循他们的optimization suggestion并用一个处理数组并返回数组的函数替换多个自定义函数。以下是它的工作原理:

function RawVal(array) {
  var thiSheet = SpreadsheetApp.getActiveSheet();
  var valuesC = thiSheet.getRange("C:C").getValues().map(function(row) {return row[0];});
  var valuesBD = thiSheet.getRange("B:D").getValues();
  var output = array.map(function(row) { 
    var rawVal = 1;
    var blockRow = valuesC.indexOf(row[0]);
    if (blockRow > -1) {
      var baseVal = valuesBD[blockRow][0];
      var ingVal = valuesBD[blockRow][2];
      rawVal = Math.max(baseVal, ingVal);
    }
    return [rawVal];
  }
  return output;
}

例如,您可以将此功能用作=RawVal(E2:E100)。参数作为双数组值传递,输出也是双数组。

此外,在使用" C:C"这样的范围时,请考虑该工作表在数据下是否有很多空行:看到一张包含20000个空行的工作表并不罕见毫无意义地通过类似的功能进行搜索。

替代方案:使用内置函数

您的自定义功能似乎主要是现有=vlookup的重新实现。例如,

=arrayformula(iferror(vlookup(H:H, {C:C, B:B}, 2, false), 1))

在C列中查找H中的所有条目,并返回B列中的相应值;一个公式为所有行执行此操作(并且在没有匹配时返回1)。你可以为D列添加另一个这样的数组,然后使用另一个arrayformula来获取这两列的最大元数(对于后者,请参见Take element-wise maximum of two columns with an array formula)。可以从视图中隐藏中间列。