如何在FILTER中使用自定义功能?

时间:2012-06-06 04:42:24

标签: google-apps-script google-sheets

我定义了一个自定义函数,用于从字符串中提取部分地址:

/*
 * Return the number preceding 'N' in an address
 *    '445 N 400 E' => '445'
 *    '1083 E 500 N' => '500'
 */
function NorthAddress(address) {
  if (!address) return null;
  else {
    var North = new RegExp('([0-9]+)[\\s]+N');
    var match = address.match(North);
    if (match && match.length >= 2) {
      return match[1];
    }
    return null;
  }
}

我想将此功能用作电子表格中FILTER(...)调用的条件之一,其中存储了这些地址:

=FILTER('Sheet 1'!A:A, NorthAddress('Sheet 1'!B:B) >= 450))

但是当我像这样调用NorthAddress时,它会获得B列中所有值的数组,而我在生命中找不到任何关于如何处理它的文档。最明显的方式(对我来说)似乎不起作用:迭代调用每个值的NorthAddress数组,并返回结果数组。

我的功能需要返回FILTER才能按预期工作?

3 个答案:

答案 0 :(得分:4)

当调用自定义函数传递多单元格范围时,它会接收一个值矩阵(2d数组),如果范围是单个列或单个行,则无关紧要,它始终是一个矩阵。你也应该返回一个矩阵。

无论如何,我不会使用自定义函数,因为已经存在本机电子表格公式:RegexMatchRegexExtractRegexReplace公式。要获得“if match”行为,只需将它们包装在IfError公式中。

答案 1 :(得分:0)

它不起作用因为地址是,如果你只传递一个单元格作为arg字符串,范围,字符串矩阵。

因此,您返回一个字符串,FILTER使用布尔数组来过滤数据,因此过滤条件为string< number

您只需在返回值时将字符串转换为数字

/*
 * Return the number preceding 'N' in an address
 *    '445 N 400 E' => '445'
 *    '1083 E 500 N' => '500'
 */
function NorthAddress(address) {
  if(typeof address == "string"){
    if (!address) return "#N/A";
    else {
      var North = new RegExp('([0-9]+)[\\s]+N');
      var match = address.match(North);
      if (match && match.length >= 2) {
        return parseInt(match[1]);
      }
      return "#N/A";
    }
  } else {
    var matrix = new Array();
    for(var i = 0; i<address.length; i++){
      matrix[i] = new Array();
      for(var j = 0; j<address[i].length; j++){
        var North = new RegExp('([0-9]+)[\\s]+N');
        var match = address[i][j].match(North);
        if (match && match.length >= 2) {
          matrix[i].push(parseInt(match[1]));
        }
      }
    }
    return matrix;
  }
}

希望这会有所帮助。

答案 2 :(得分:0)

我将添加此作为答案,因为我发现如果在未调用toString()时在引用的单元格或范围中传递数值,则自定义函数会返回错误:

function NorthAddress(address) {
  if (!address) return null;
  else {
    if (address.constructor == Array) {
      var result = address;
    }
    else {
      var result = [[address]];
    }
    var north = new RegExp('([0-9]+)[\\s]+N');
    var match;
    for (var i = 0; i < result.length; i++) {
      for (var j = 0; j < result[0].length; j++) {
        match = result[i][j].toString().match(north);
        if (match && match.length >= 2) {
          result[i][j] = parseInt(match[1]);
        }
        else {
          result[i][j] = null;
        }
      }
    }
    return result;
  }
}