Выполнение запросов от API к сценарию Google Spreadsheet / G Apps и получение отфильтрованных результатов - PullRequest
0 голосов
/ 15 февраля 2020

Я пытаюсь создать электронную таблицу, основанную на превосходном API DataDT для 1-минутных данных Форекс. Я пытаюсь создать функцию, которая 1) Считывает значение («Дата и время») из ячейки 2) Выполняет поиск этого значения в указанном URL из вышеупомянутого API 3) Печатает 2 других свойства (цена открытия и закрытия) для в ту же дату.

Current spreadsheet status

Другими словами, он будет принимать входные данные из строк N и O и выводить соответствующие значения (OPEN и CLOSE из API) в строках H и I.

(ссылка на текущую GSpreadsheet )

Эта электронная таблица будет связывать макроэкономические c новости и исторические c цены и, возможно, раскрывать полезные советы для пользователей Forex.

Мне уже удалось эффективно запрашивать данные из API, но я не могу найти способ фильтровать только те даты, которые я запрашиваю. Гораздо меньше повторений для разных дат! С помощью пользователя @Cooper я получил следующий код, который может запрашивать целые страницы из API, но пока не может эффективно фильтровать. Буду признателен за любую помощь, которую вы можете оказать.

Это текущий статус кода в Appscript:

(Code.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();
}

1 Ответ

1 голос
/ 15 февраля 2020

Поиск onEdit

Вам необходимо добавить столбец флажков в столбец 17, а также создать устанавливаемый триггер onEdit. Вы можете использовать предоставленный код или сделать это вручную через меню Edit / Project Triggers. При использовании кода создания триггера убедитесь, что создан только один триггер, так как несколько триггеров могут вызвать проблемы.

Кроме того, не делайте ошибку, называя свой устанавливаемый триггер 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 файл, который можно просмотреть с помощью View / Show Manifest File. Вот ссылка , которая просто показывает, как они выглядят. Но основная идея c заключается в том, чтобы ставить запятую после последней записи перед закрывающей скобкой и добавлять необходимые строки.

После того, как вы создали триггер, лучше go включить триггеры Просмотр / Текущий проект и установить для уведомлений Немедленное. Если вы получите ошибки определения объема, вам сообщат, какие из них добавить. Вы добавляете их, а затем запускаете функцию, и вы можете повторно авторизовать доступ с помощью дополнительных областей. Вы даже можете запустить нулевую функцию, например 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;
}

Это функция создания триггера. Старайтесь не запускать это более одного раза и всегда проверяйте go, чтобы видеть, что есть только один, и устанавливайте уведомления как немедленные при первом включении, чтобы вы очень быстро получали электронные письма после возникновения ошибок.

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

Анимация:

enter image description here

Это копия вашей электронной таблицы с флажками.

enter image description here

Если у вас возникнут какие-либо трудности, не стесняйтесь возвращаться и получать помощь. Я знаю, что некоторые из этих вещей звучат немного устрашающе, но это похоже на метри c. Как только вы измерили и взвесили несколько вещей, это начинает звучать и чувствовать себя естественно.

Вот мой код в точности, как он есть в моем скрипте, который выполняется прямо сейчас. Возможно, у меня есть опечатка из-за редактирования в комментариях. Здесь есть несколько строк отладки, в которых запускается Logger и отображаются тосты, которые вы, вероятно, должны закомментировать.

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();
}
...