簡體   English   中英

停止自定義函數自動刷新/定期調用外部 API

[英]Stop custom function from auto refreshing/periodically calling external 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, 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 返回“無效電話號碼”代碼。 由於隱私,我不會在這里放任何真實的電話號碼。 如果我使用真實的電話號碼,第一個單元格將包含以國際號碼格式格式化的電話號碼。

示例自定義函數輸出

由於我使用的是免費計划,如果我已經知道結果是什么我不想每次都重新運行該函數,因為我不想遇到速率限制。 不幸的是,這似乎不起作用並且定期(它看起來像每天一次),它會刷新工作表中每一行的結果。

所以兩個問題:

  1. 我在檢查 API 結果然后退出函數時的邏輯有問題嗎? (代碼見下文)
  2. 如果邏輯是正確的,為什么 Google Sheets 似乎會定期忽略(或刷新?)第二列中的值並無論如何調用外部 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, 0, 1, 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 公式演示

您將看到,如果刪除原始單元格中的公式,溢出值也會消失。

因此,類似於以下代碼的內容幾乎總是會產生相同的值:

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() 演示

表格在重新計算公式之前所做的第一件事是清除由公式填充的先前值 由於條件語句取決於其先前執行的值,因此它始終會評估為相同的結果。 在您的情況下,它幾乎總是會進行 API 調用

令人困惑的是,這不是 100% 可靠的! 您會發現有時,它會按您的意願工作。 盡管在我的測試中,這僅發生了大約 10 次中的 1 次,而且最常見的是在將更改保存到腳本編輯器時更新公式。

理想情況下,雖然不可能,但您希望能夠編寫如下內容:

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")
  }
}

一旦它運行,這將清除公式,唉,對於公式setValue()禁用 如果您想使用setValue()您需要從菜單、觸發器或腳本編輯器運行您的腳本。 在這種情況下,它作為公式將不再有意義。z

參考

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM