Google Apps脚本 - 如何使用参数为函数创建触发器?

时间:2017-12-30 02:57:05

标签: google-apps-script

我正在研究加密货币的跟踪器。在以下函数中,我从API获取数据并放入单元格中。例如,当我想以美元获得比特币的价值时,我将公式= getCryptodata(“比特币”,“price_usd”)放在一个单元格中,并返回当前价格。

  function getCryptoData(coin, api) {

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];

  var url = 'https://api.coinmarketcap.com/v1/ticker/' + coin + '/';
  var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
  var json = response.getContentText();
  var data = JSON.parse(json);

  return parseFloat(data[0][api]);

  }

我希望价格每分钟更新一次,所以我设置了该功能的触发器。突然间,现在似乎出现了问题。每次触发该功能时,都会显示此错误(在我的邮箱中)。

  

TypeError:无法从undefined中读取属性“(class)@ 35c554a5”。

当我从脚本编辑器运行脚本时,我遇到了同样的问题。然后我想出了检查函数中的参数是否定义的想法,如果没有定义,给它们一个通用值。 Google似乎对未定义的参数存在问题(尽管它们在工作表中定义)。所以我在我的函数中已经有的行之前添加了这些行。

  if (typeof coin == 'undefined') {
    var coin = "bitcoin";
  }
  if (typeof api == 'undefined') {
    var api = "price_usd";
  } 
  else {

现在错误已经消失,但触发该功能时不会更新这些值。

我错过了什么?

3 个答案:

答案 0 :(得分:0)

所以这里有一些事情发生了:

  • 您正在尝试加载活动电子表格,但是当您触发脚本时,没有活动的电子表格。 (你为什么要加载这个电子表格?你似乎没有用它做任何事情)
  • 您的脚本返回一个值但是如果您的脚本是从计划触发的(因此不是从另一个函数触发),则返回的值将不返回任何值。你需要把这个值放在有用的地方。

此问题的解决方案可能是直接将API中的值放入工作表中。为此,脚本需要进行少量更改。

示例:

function getCryptoData(coin, api, target) {

  var ss = SpreadsheetApp.openById("YOUR-ID-HERE"); // The script has no active spreadsheet so make sure to acquire the spreadsheet by providing the ID
  var sheet = ss.getSheets()[0];

  var url = 'https://api.coinmarketcap.com/v1/ticker/' + coin + '/';
  var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
  var json = response.getContentText();
  var data = JSON.parse(json);

  SpreadsheetApp.getRange(target).setValue(parseFloat(data[0][api])); // Write the returned value directly to the range (e.g. A1) that was specified as an argument

}

因此,使用这样的函数,您可以创建另一个函数,您可以偶尔触发每个函数来更新您的值:

function updateCryptoData() {
  getCryptodata("bitcoin", "price_usd", "B2");
  getCryptodata("bitcoin", "price_usd", "C2");
}

如果您选择使用此类解决方案,则不需要在工作表中添加公式。

注意:从性能的角度来看,此解决方案并非最佳。但是,我尝试对您自己的代码进行少量代码更改以使其正常工作。理想情况下,您只需按照每种硬币类型调用一次API。

答案 1 :(得分:0)

使用fetch时,您应该知道每次调用可以返回多少数据。因为您每分钟都在呼叫数据,所以您将超出daily limit.

的可能性范围内

答案 2 :(得分:0)

这不需要重新加载电子表格。首先,您必须为特定硬币和定价创建触发器。

function teste()
{
 trigger_("bitcoin","price_usd","B2");
 trigger_("litecoin","price_usd","B3");
 trigger_("bitcoin","price_usd","B4");
}

参考trigger_id存储与触发器对应的数据。

function trigger_(coin,api,target)
{
 var new_trigger = ScriptApp.newTrigger(getCryptoData).timeBased().everyMinutes(1).create();
 var trigger_id = new_trigger.getUniqueId();
 PropertiesService.getUserProperties().setProperty(trigger_id, coin+","+api+","+target);
}

当触发器被触发时,它获取相应的数据(硬币,价格,目标),用于调用api并更新目标单元格。

function getCryptoData(event) 
{

  var trig = ScriptApp.getProjectTriggers();
  for(var i =0; i<trig.length; i++)
  {
   if(trig[i].getUniqueId()== event.triggerUid )
   {
    var cryptoData = PropertiesService.getUserProperties().getProperty(event.triggerUid);
    cryptoData = cryptoData.split(",");
    var coin = cryptoData[0];
    var api = cryptoData[1];
    var target = cryptoData[2];
    var ss = SpreadsheetApp.openById("YOUR_SPEADSHEET_ID").getSheets(); // change accordingly
    var sheet = ss[0];  // change accordingly
    var url = 'https://api.coinmarketcap.com/v1/ticker/' + coin + '/';
    var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
    var json = response.getContentText();
    var data = JSON.parse(json);
    Logger.log(parseFloat(data[0][api]));
    ss[0].getRange(target).setValue(parseFloat(data[0][api]));
   }
  }
}

注意:普通用户运行触发器的每日限制为90分钟/天 app script quota