使用脚本检测Google表格中的公式错误

时间:2018-03-07 21:56:40

标签: google-apps-script

我的最终目标是here,但由于我没有得到回复,我开始从零开始学习东西(无论如何最好)。基本上,我想要一个可以识别错误并修复错误的脚本

那么,第一部分是能够识别错误。有没有办法使用Google Script识别单元格中是否有错误,并返回特定的消息?或者我只需要做一个if / else表示“如果单元格值为'#N / A',请执行此操作”,加上“如果单元格值为'#ERROR',请执行此操作”,继续执行各种错误?。基本上我想要ISERROR(),但是在剧本中

4 个答案:

答案 0 :(得分:2)

使用辅助函数抽象出恶意:

function isError_(cell) {
  // Cell is a value, e.g. came from `range.getValue()` or is an element of an array from `range.getValues()`
  const errorValues = ["#N/A", "#REF", .... ];
  for (var i = 0; i < errorValues.length; ++i)
    if (cell == errorValues[i])
      return true;

  return false;
}

function foo() {
  const vals = SpreadsheetApp.getActive().getSheets()[0].getDataRange().getValues();
  for (var row = 0; row < vals.length; ++row) {
    for (var col = 0; col < vals[0].length; ++col) {
      if (isError_(vals[row][col])) {
        Logger.log("Array element (" + row + ", " + col + ") is an error value.");
      }
    }
  }
}

在辅助函数中使用Array#indexOf

function isError_(cell) {
  // Cell is a value, e.g. came from `range.getValue()` or is an element of an array from `range.getValues()`
  // Note: indexOf uses strict equality when comparing cell to elements of errorValues, so make sure everything's a primitive...
  const errorValues = ["#N/A", "#REF", .... ];
  return (errorValues.indexOf(cell) !== -1);
}

如果/当使用Array#includes升级Google Apps脚本时,这将是比Array#indexOf更好的选择。

答案 1 :(得分:1)

更新:2020年3月25日

@tehhowch表示“如果/当Google Apps脚本使用Array#includes升级时,那将是比Array#indexOf更好的选择。”

Array.includes现在可以在Apps脚本中运行,并且与indexOf相比,可以预期提供了一种更加简单的方法。

此示例与先前的答案有所不同,它使用特定范围来表明不需要循环遍历每个单元格。实际上,此答案将适用于任何范围长度。

答案的两个关键方面是:

  • map:为每一列创建一个数组
  • includes:在IF语句中用于测试是非值。

function foo() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sourcename = "source_sheet";
  var source = ss.getSheetByName(sourcename);

  var sourcerange = source.getRange("A2:E500");
  var sourcevalues = sourcerange.getValues();

  // define the error values
  var errorValues = ["#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A","#ERROR!"];

  // loop though the columns
  for (var c = 0;c<5;c++){

    // create an array for the column
    var columnoutput = sourcevalues.map(function(e){return e[c];});

    // loop through errors
    for (var errorNum=0; errorNum<errorValues.length;errorNum++){

      // get the error
      var errorvalue = errorValues[errorNum]
      // Logger.log("DEBUG: column#:"+c+", error#:"+e+", error value = "+errorvalue+", does col include error = "+columnoutput.includes(errorvalue));

      // if the error exists in this column then resposnse = true, if the error doesn't exist then response = false
      if (columnoutput.includes(errorvalue) != true){
        Logger.log("DEBUG: Column#:"+c+", error#:"+errorNum+"-"+errorvalue+" - No ERROR");

      } else {
        Logger.log("DEBUG:  column#:"+c+", error#:"+errorNum+"-"+errorvalue+"- ERROR EXISTS");

      }
    }
  }

  return;
}

答案 2 :(得分:0)

我有一个类似的问题,并使用getDisplayValue()而不是getValue()来解决

尝试类似的东西:

function checkCells(inputRange) {
  var inputRangeCells = SpreadsheetApp.getActiveSheet().getRange(inputRange);
  var cellValue;
  for(var i=0;  i < inputRangeCells.length; i++) {
    cellValue = inputRangeCells[i].getDisplayValue();
    if (cellValue=error1.....) { ... }
  }
}

显示值应该给您显示给用户的内容,而不是#ERROR!

答案 3 :(得分:0)

更短的是,在 [vals] 数组上使用嵌套的 forEach(),然后检查单元格值是否与具有 indexOf 的 [errorValues] 数组的值匹配。这比 for 循环快...

function foo() {
  const errorValues = ["#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A","#ERROR!"];  
  const vals = SpreadsheetApp.getActive().getSheets()[0].getDataRange().getValues();
  
  vals.forEach((val,row) => { val.forEach((item, col) => {
    (errorValues.indexOf(item) !== -1) ? Logger.log("Array element (" + row + ", " + col + ") is an error value.") : false ;
    });
 });

}