【问题标题】:Querying from an API to a Google Spreadsheet / G Apps Script and obtaining filtered results从 API 查询到 Google 电子表格/G Apps 脚本并获得过滤结果
【发布时间】:2020-02-16 02:38:30
【问题描述】:

我正在尝试基于DataDT's 为 1 分钟外汇数据构建一个出色的 API 的电子表格。我正在尝试构建一个函数,它 1)从单元格中读取一个值(“日期时间”) 2)从上述 API 的给定 URL 中搜索该值 3)打印 2 个其他属性(开盘价和收盘价)同一天。

换句话说,它将从 N 行和 O 行获取输入,并在 H 和 I 行输出相关值(来自 API 的 OPEN 和 CLOSE)。

(链接到当前GSpreadsheet

此电子表格将宏观经济新闻和历史价格联系起来,并可能为外汇用户提供有用的见解。

我已经设法有效地从 API 查询数据,但我找不到仅针对我所询问的日期时间进行过滤的方法。不同日期的迭代要少得多!在用户@Cooper 的帮助下,我得到了以下代码,它可以从 API 查询整个页面,但还不能有效地过滤。如果您能提供任何帮助,我将不胜感激。

这是 Appscript 中代码的当前状态:

(代码.gs)

function searchOnEdit(e) {
  //e.source.toast('Entry');// I use these lines for debugging
  var sh=e.range.getSheet();
  if(sh.getName()!='API') return;
  var checkedValue='TRUE';//these are the defaults if you install the checkboxes from the Insert Menu
  var uncheckedValue='FALSE';
  if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
    e.range.setValue(uncheckedValue);//this was commented out it should not have been sorry for that Cooper
    //e.source.toast('flag1');
    var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
    var obj={datetime:r[14],url:r[13],event:e};
    var dObj=getDataDT1(obj);
    //Logger.log(dObj);
    sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);//loading OPEN on your spreadsheet
    sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);//loadding CLOSE on your spreadsheet
  }
}

//{datetime:'',url:'',event:e}
function getDataDT1(obj) {
  Logger.log(JSON.stringify(obj));//I need to see this
  var r=UrlFetchApp.fetch(obj.url);
  var data=JSON.parse(r.getContentText("UTF-8"));
  //Logger.log(data);
  var pair='USDJPY';
  var dat=new Date(obj.datetime);
  var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
  for(var i=0;i<data.length;i++) {
    var dt=data[i].DATE_TIME.split(' ');
    var sd=new Date(data[i].DATE_TIME);
    var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
    if(sdv==dtv) {
      var d=dt[0].split('-');
      var t=dt[1].split(':');
      var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
      var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
      var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
      break;
    }
  }
  //Logger.log(rObj);
  return rObj;
}

(Appscript.json)

{
  "timeZone": "America/Caracas",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes":  ["https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/script.scriptapp","https://www.googleapis.com/auth/spreadsheets"]
}

(触发器.js)

function createSearchOnEditTrigger() {
  var ss=SpreadsheetApp.getActive();
  ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}

【问题讨论】:

  • 好的,因为我已经知道您要做什么,问题是我从哪里获取日期时间以及它将采用什么格式。您能否提供电子表格的图像。显示需要放置结果的位置。
  • 当然!我上传了一张图片并稍微完善了解释。日期时间的格式为 YYYY-MM-DD HH:MM:SS 目前在 O 列中,输出在 H 列中,我尝试修改以前的代码,但无法使其工作...
  • 你能解释一下Reads a value ("Date time") from a cell 2吗?
  • 当然!该过程将(简化)如下: 1) 用户在 O 列中写入 date_time 值列表,从第 2 行开始 2) 对于这些 date_times 中的每一个,代码在 API 中搜索与每个 date_time 匹配的对象值(没有重复) 3) 代码输出与每个 date_time 值对应的 OPEN 和 CLOSE 值 API 由以下对象组成:{ "DATE_TIME": "2019-04-03 00:00:00", "OPEN": 0.94261, "HIGH": 0.94262, "LOW": 0.94247, "CLOSE": 0.94247, "VOLUME": 6 } date_time 值从不重复
  • 这个想法基本上是回答问题:这个日期和时间的开盘价是多少?那个日期的收盘价是多少?依此类推,还有一个 date_times 列表。 N列的值也是动态变化的,所以不同的天从不同的url获取

标签: javascript google-apps-script google-sheets forex


【解决方案1】:

onEdit 搜索

您需要在第 17 列添加一列复选框,并创建一个可安装的 onEdit 触发器。您可以使用提供的代码或通过“编辑/项目触发器”菜单手动执行。使用触发器创建代码时,请检查以确保只创建了一个触发器,因为多个触发器可能会导致问题。

另外,不要错误地将可安装触发器命名为 onEdit(e),因为它会响应简单触发器和导致问题的可安装触发器。

我在下面有一个动画向您展示它是如何运作的,您也可以看到电子表格的布局。请注意隐藏的列。我必须这样做以使动画尽可能小。但我没有删除你的任何专栏。

最好等待复选框重置为关闭,然后再选中另一个复选框。检查它们的速度可能会如此之快,以至于脚本跟不上,并且可能会错过一些搜索。

我还必须手动添加这些范围:

"oauthScopes":["https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/spreadsheets"]

您可以将它们放入您的 appsscript.json 文件中,该文件可使用查看/显示清单文件查看。这是一个reference,几乎没有向您展示它们的样子。但基本思想是在右括号之前的最后一个条目之后放置一个逗号并添加所需的行。

创建触发器后,最好进入查看/当前项目触发器并将通知设置为立即。如果您遇到范围界定错误,它会告诉您要添加哪些错误。您添加它们,然后运行一个函数,您可以使用其他范围重新授权访问。你甚至可以运行像function dummy(){}; 这样的空函数。

这是 onEdit 函数:

function searchOnEdit(e) {
  //e.source.toast('Entry');// I use these lines for debugging
  var sh=e.range.getSheet();
  if(sh.getName()!='API') return;
  var checkedValue='TRUE';//these are the defaults if you install the checkboxes from the Insert Menu
  var uncheckedValue='FALSE';
  if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
    e.range.setValue(uncheckedValue);
    //e.source.toast('flag1');
    var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
    var obj={datetime:r[14],url:r[13],event:e};//you dont really need e here
    var dObj=getDataDT1(obj);
    //Logger.log(dObj);
    sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);//loading OPEN on your spreadsheet
    sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);//loadding CLOSE on your spreadsheet
  }
}

这是搜索功能。我尝试缓存数据,但它太大了。因此,如果您可以显着减小大小,这将有助于加快连续搜索的速度。

//{datetime:'',url:'',event:e}
function getDataDT1(obj) {
  var r=UrlFetchApp.fetch(obj.url);
  var data=JSON.parse(r.getContentText("UTF-8"));
  //Logger.log(data);
  var pair='USDJPY';
  var dat=new Date(obj.datetime);
  var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
  for(var i=0;i<data.length;i++) {
    var dt=data[i].DATE_TIME.split(' ');
    var sd=new Date(data[i].DATE_TIME);
    var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
    if(sdv==dtv) {
      var d=dt[0].split('-');
      var t=dt[1].split(':');
      var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
      var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
      var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
      break;
    }
  }
  //Logger.log(rObj);
  return rObj;
}

这是创建触发器函数。请注意不要多次运行此程序,并始终检查是否只有一个,并在您第一次打开它时将通知设置为立即通知,以便在发生错误后很快收到电子邮件。

function createSearchOnEditTrigger() {
  var ss=SpreadsheetApp.getActive();
  ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}

动画:

这是带有复选框的电子表格副本。

如果您有任何困难,请随时回来寻求帮助。我知道其中一些东西听起来有点令人生畏,但它有点像公制。一旦您测量并称量了一些东西,它就会开始听起来和感觉自然。

这是我的代码,与我现在正在运行的脚本中的代码完全相同。由于在 cmets 中进行编辑,也许我有一个错字。这有一些调试行,其中运行 Logger 并显示您可能应该注释掉的 toast。

function searchOnEdit(e) {
  e.source.toast('Entry');
  var sh=e.range.getSheet();
  if(sh.getName()!='API') return;
  var checkedValue='TRUE';
  var uncheckedValue='FALSE';
  if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
    e.range.setValue(uncheckedValue);
    e.source.toast('flag1');
    var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
    var obj={datetime:r[14],url:r[13],event:e};
    var dObj=getDataDT1(obj);
    Logger.log(dObj);
    sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);
    sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);
  }
}

//{datetime:'',url:''}
function getDataDT1(obj) {
  var r=UrlFetchApp.fetch(obj.url);
  var data=JSON.parse(r.getContentText("UTF-8"));
  //Logger.log(data);
  var pair='USDJPY';
  var dat=new Date(obj.datetime);
  var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
  for(var i=0;i<data.length;i++) {
    var dt=data[i].DATE_TIME.split(' ');
    var sd=new Date(data[i].DATE_TIME);
    var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
    if(sdv==dtv) {
      var d=dt[0].split('-');
      var t=dt[1].split(':');
      var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
      var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
      var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
      break;
    }
  }
  //Logger.log(rObj);
  return rObj;
}

function createSearchOnEditTrigger() {
  var ss=SpreadsheetApp.getActive();
  ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多