停止自定义函数自动刷新/定期调用外部API 您的目标:简短答案:说明:参考文献

问题描述

我正在使用Google Apps脚本和自定义函数来调用外部API来验证电话号码。

下面是我的函数的代码。

/**
 * This CUSTOM FUNCTION uses the numVerify API to validate 
 * a phone number based on the input from JotForm and a 
 * country code which is derived from the JotForm country
 *
 * Numverify website: https://numverify.com/dashboard (account via LastPass)
 * Numverify docs: https://numverify.com/documentation
 */
function PHONE_CHECK(number,country){
  
  if(country == "")
    return [["","country_not_set"]]
  
  // check the API result has already been retrieved
  var range = SpreadsheetApp.getActiveSheet().getActiveRange()
  var apires = range.offset(0,1).getValue()
  if(apires.length > 0)
    return range.offset(0,1,2).getValues()
    
    
  var url = 'http://apilayer.net/api/validate'
  + '?access_key=' + NUMVERIFY_KEY
  + '&number=' + encodeURIComponent(number)
  + '&country_code=' + encodeURIComponent(country)
  + '&format=1';

  var response = UrlFetchApp.fetch(url,{'muteHttpExceptions': true});
  var json = response.getContentText();
  var data = JSON.parse(json);
  
  if(data.valid !== undefined){
    if(data.valid){
      return [[data.international_format,"OK"]]
    }else{
      return [["","invalid_number"]] // overflows data to the next column (API Error) while keeping the phone field clear for import into TL
    }
  }else if(data.success !== undefined){
    if(data.error.type.length > 0){
      return [[number,data.error.type]]
    }else{
      return [[number,"no_error_type"]]
    }
  }else{
    return [[number,"unexpected_error"]] // this generally shouldn't happen...
  }
}

鉴于此公式(包含电话号码和国家/地区代码),它将根据numverify API检查电话号码,并将结果返回到单元格中并溢出到其右侧的单元格中。溢出用于指示是否已成功调用API,并检查结果是否已检索

示例: =PHONE_CHECK("+32123456789","BE")

请注意,第一个单元格为空,因为API返回了“无效的电话号码”代码。由于隐私原因,我不会在此处输入任何真实的电话号码。如果我要使用真实的电话号码,则第一个单元格将包含以国际号码格式设置的电话号码。

example custom function output

由于我使用的是免费计划,因此如果我已经知道结果是什么,我不想每次都重新运行该功能,因为我不想遇到速率限制。 不幸的是,这似乎不起作用,并且定期(每天一次),它将刷新工作表中每一行的结果。

有两个问题:

  1. 检查API结果然后退出函数时,我的逻辑有问题吗? (请参见下面的代码)
  2. 如果逻辑正确,为什么Google表格似乎会定期忽略(或刷新?)第二列中的值并以任何方式调用外部API?
  var range = SpreadsheetApp.getActiveSheet().getActiveRange() // get the cell from which the function is called
  var apires = range.offset(0,1).getValue() // get the values directly to the right of the cell
  if(apires.length > 0) // check if there's anything there...
    return range.offset(0,2).getValues() // return an array that basically just resets the same values,effectively stopping the script from running

解决方法

您的目标:

您想要一个自定义函数,也就是公式,只能运行一次,或运行一次以生成特定结果所需的次数。 您希望同一公式将值写入另一个单元格(例如相邻的单元格),以便将来告诉该公式是否应该再次运行。

简短答案:

恐怕从自定义函数AKA公式计算出的值是瞬态的,用它们无法实现您想要的操作。

说明:

您可以使用此自定义功能进行快速测试:

function arrayTest() {
  return [[1,2,3,4,5]]
}

如果将其放在如下所示的单元格中:

arrayTest Formula demo

您将看到,如果删除原始单元格中的公式,则溢出值也会消失。

因此,类似以下代码的内容将几乎始终产生相同的值:

function checkTest() {
  var cell = SpreadsheetApp.getActiveRange()
  var status = cell.offset(0,1).getValue();
  
  if (status != "") {
    return "already executed" // in your case without calling API
  } else {
    return [["OK","executed"]] // in your case making API call - will happen ~90% of the time.
  }
}

// OUTPUT [["OK","executed"]]

在这里,我要插入一行并将其删除以强制重新计算公式。

checkTest() Demo

在重新计算公式之前,Sheets要做的第一件事是清除公式填充的先前值。由于条件语句取决于其先前执行的值,因此它将始终评估为相同的结果。对于您而言,它几乎总是会进行API调用

令人困惑的是,这不是100%可靠的!您会发现有时,它会按预期工作。尽管在我的测试中,这种情况只发生了十分之一,大约是10次,最常见的情况是在将更改保存到脚本编辑器时更新了公式。

理想情况下,尽管不可能,但您希望能够编写如下内容:

function checkTest() {
  var cell = SpreadsheetApp.getActiveRange();
  var cellValue = cell.getValue();
  var adjacentCell = cell.offset(0,1);
  var status = adjacentCell.getValue();
  
  if (status == "") {
    cell.setValue(cellValue)
    adjacentCell.setValue("executed")
  }
}

运行公式后会清除,clear setValue()禁用了公式!如果要使用setValue(),则需要从菜单,触发器或脚本编辑器中运行脚本。在这种情况下,将其作为公式不再有意义。z

参考文献

https://developers.google.com/apps-script/guides/sheets/functions

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...