【问题标题】:How to Apply custom formula across all columns using Array Formula如何使用数组公式在所有列中应用自定义公式
【发布时间】:2021-06-14 17:01:01
【问题描述】:

我无法使用数组公式在所有列中应用我的自定义公式。我的自定义公式名为 getCountry,它可以根据地址获取国家/地区。地址组件,例如街道或城市也每列分开。当我将公式应用于单元格时,它会显示正确的国家/地区。当我将它包含在 ArrayFormula 中时,它只显示第一行的国家/地区。

我想应用 ArrayFormula 函数,因为如果有新行我想自动应用公式。如果 ArrayFormula 不起作用,是否有解决方法?

这是示例电子表格。

https://docs.google.com/spreadsheets/d/1W3s1a8mG2fkmFlrez9mQLqwtyIcl-gNym1xtvLPFN1Q/edit?usp=sharing

这是我的自定义函数的代码:

function getCountry(address) {
  var response = Maps.newGeocoder().geocode(address);
  for (var i = 0; i < response.results.length; i++) {
    var result = response.results[i];
    country = []
    for (var comp of result.address_components) {
      if (comp.types.indexOf("country") > -1) country.push(comp.long_name)
    }
    if(country.length > 1) return country.join()
    return country[0]
  }
}

编辑:我设法使它在较小的数据集上工作。但是当我将它应用到更大的数据集时,它会提示错误“超过最大执行时间”。如何使它更好,以便在应用于更大的数据集时不会返回该错误?我使用的公式是:

=transpose(split(getCountryList(transpose(query(transpose(filter(A2:D,not(isblank(A2:A)))),,rows(filter(A2:A,not(isblank(A2:A))))))),","))

而我现在使用的自定义函数是:

function getCountry(address){
  var response = Maps.newGeocoder().geocode(address);
    country = []
    for (var i = 0; i < response.results.length; i++) {
      var result = response.results[i];
      for (var comp of result.address_components) {
        if (comp.types.indexOf("country") > -1) country.push(comp.long_name)
      }
    }
    return (country.length > 1)?country.join(): country[0];
}

function getCountryList(address_array) {
  country_list = []
  for (i in address_array){
    var country = getCountry(address_array[i]);
    country_list.push(country);
  }
  return country_list.join();
}

【问题讨论】:

  • 您需要修改脚本以使其 ArrayFormula 与您的自定义函数一起使用。基本上,arrayformula 将一组值传递给您的函数,因此您需要您的函数将其作为数组接收并逐个处理。

标签: google-apps-script google-sheets google-sheets-formula


【解决方案1】:

您可以修改getCountryList() 函数使其接受范围参数,并添加在线函数帮助,如下所示:

/**
* Guesses the country of a number of addresses listed in rows.
* Each address can consist of several consecutive cells in the same row.
*
* @param {A2:D} addresses A range that contains street addresses, one address per row.
* @return {String[][]} The countries that match the addresses.
* @customfunction
*/
function GetCountry(addresses) {
  if (!Array.isArray(addresses)) {
    addresses = [[addresses]];
  }
  return addresses.map(row => [getCountry_(row.join(' '))]);
}

function getCountry_(address) {
  if (!address || !address.trim()) {
    return null;
  }
  const country = [];
  const responses = Maps.newGeocoder().geocode(address);
  responses.results.forEach(result => {
    for (let comp of result.address_components) {
      if (comp.types.indexOf('country') !== -1) {
        country.push(comp.long_name);
      }
    }
  });
  return country.join();
}

您可以像这样使用自定义函数:

=GetCountry(A2:D)

这些更改应该会导致对Maps 服务的调用次数减少,但每个地址仍然是单独检索的,这是一个性能瓶颈。我没有检查Maps 中是否有批处理调用方法可以让您一次发送多个请求。如果您没有找到批处理调用方法,请尝试使用多个 GetCountry() 公式,每个公式处理 100 行。

见custom function optimization tips。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多