I use the code below to retrieve a XML and write the data to Sheet2.
But when i run the function again it loads the entire xml again into the sheet.
What i want to achieve, but don't know how:
1.
Get de XML and compare it with the data already in Sheet2, based on 2 colums:
stationID & stationTypeID
2.
When the two columns match, update the entire row. When the columns don't match, insert the new row on top.
function loadOutposts(){
var outposts= new Array();
var url = "https://api.eveonline.com/eve/ConquerableStationList.xml.aspx";
var parameters = {method : "get", payload : ""};
var xmlFeed = UrlFetchApp.fetch(url, parameters).getContentText();
var xml = XmlService.parse(xmlFeed);
if(xml) {
var rows=xml.getRootElement().getChild("result").getChild("rowset").getChildren("row");
for(var i = 0; i < rows.length; i++) {
outpost=[rows[i].getAttribute("stationID").getValue(),
rows[i].getAttribute("stationName").getValue(),
rows[i].getAttribute("stationTypeID").getValue(),
rows[i].getAttribute("solarSystemID").getValue(),
rows[i].getAttribute("corporationID").getValue(),
rows[i].getAttribute("corporationName").getValue()
]
outposts.push(outpost);
}
}
//return outposts;
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet2').getRange(1,1,outposts.length,outposts[0].length).setValues(outposts);
};
Thx for the help!
How about this modification?
Flow :
Data retrieved by UrlFetchApp.fetch() is compared to the existing data on Spreadsheet.
When the columns 1 and 2 for them are same, the existing data is updated.
When the data retrieved from URL is not included in the existing data, the data is inserted to the top of existing data. This existing data becomes new data.
Then, the data on Spreadsheet is updated by new data.
Modified script :
function loadOutposts(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet2');
var outposts= new Array();
var url = "https://api.eveonline.com/eve/ConquerableStationList.xml.aspx";
var parameters = {method : "get", payload : ""};
var xmlFeed = UrlFetchApp.fetch(url, parameters).getContentText();
var xml = XmlService.parse(xmlFeed);
if (xml) {
var rows=xml.getRootElement().getChild("result").getChild("rowset").getChildren("row");
for(var i = 0; i < rows.length; i++) {
outpost = [
rows[i].getAttribute("stationID").getValue(),
rows[i].getAttribute("stationName").getValue(),
rows[i].getAttribute("stationTypeID").getValue(),
rows[i].getAttribute("solarSystemID").getValue(),
rows[i].getAttribute("corporationID").getValue(),
rows[i].getAttribute("corporationName").getValue()
]
outposts.push(outpost);
}
// ----- Added script
if (ss.getLastRow() > 0) {
var currentdata = ss.getRange(2, 1, ss.getLastRow(), ss.getLastColumn()).getValues(); // Updated
currentdata.forEach(function(e1, i1){
var temp = [];
outposts.forEach(function(e2, i2){
if (e1[0] == e2[0] && e1[1] == e2[1]) {
currentdata[i1] = e2;
temp.push(i2);
}
});
for (var i in temp) {
outposts.splice(temp[i], 1);
}
});
Array.prototype.push.apply(outposts, currentdata);
}
// -----
}
ss.getRange(2,1,outposts.length,outposts[0].length).setValues(outposts); // Updated
};
If I misunderstand your question, I'm sorry.
Related
I need to create a table from JSON, I'm getting output in a string and it should be printed in table format in HTML
function apicall(){
var id = document.getElementById('idval').value;
var url1 = '**********************';
var token = sessionStorage.getItem('MyUniqueUserToken');
var data1 = {"ip":id};
var success = {};
var dataType = {};
$.ajax({
url: url1,
data: data1,
type: "GET",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'token '+token);},
success: function(res) {
document.getElementById('output').innerHTML =JSON.stringify(res[0]);
}
});
}
enter image description here
Guessing that res is the response as a JSON so instead of
document.getElementById('output').innerHTML =JSON.stringify(res[0]);
you have to put your response into a loop (Given you have an empty table with cells=fields output0 to output4
var i=0;
response.data.forEach(function(field) {
//here you create the table cells if there are 5 fields
that would be 5 cells as I do not know the structure just
pseudo code
document.getElementById('output'+i).innerHTML = JSON.stringify(res[i]);
i = i+1;
}
if you want to semi dynamicly create table rows you have to have a table with header (footer) row fix and the tabelbody as an anchor to whichyou append the created rows could look like follows (partly pseudo code) -PLAIN vanilla javascript as I do not like jquery:
// We need a table definition for creating headers and interpreting JSON date
var tdataRow = [{
"output0" : field.output0,
"output1" : field.output1,
"output2" : field.output2,
"output3" : field.output3;
"output4" : field.output4
}];
// Then in jour ajax
response.data.forEach(function(field) {
var columnHeadings = Object.keys(tdataRow[0]);
var tableRef = document.getElementById("tbody" + "my_test_table");
var columnCount = 5; // Could be derived from number of headings
var tableLength = tableRef.getElementsByTagName("tr").length;// we get the number of the existing table rows
var trowID = tableLength + 1; // we append at the end of existing rows
var tableRow = tableRef.insertRow(tindex);
for (var j = 0; j < columnCount; j++) { /* Each column */
var cell = tableRow.insertCell(-1);
cell.setAttribute("id", columnHeadings[j] );
var obj = tdataRow[0];
cell.innerText = obj[columnHeadings[j]]; // we get the field names from the header
}
tableRow.setAttribute("id", "row" + "my_test_table" + j );
// examples how to style and use classes
tableRow.classList.add("table");
tableRow.classList.add("clickable-row");
tableRow.setAttribute("align","center");
// if you want to catch clicks on the row
tableRow.addEventListener("click", function(){
// do something with the row e.g. highlight/ get values etc
}
}
The second solution can be converted into a fully automated/dynamic solution where everything is created from the JSON - but small steps first.
So I have this code that is supposed to fetch a project_id from a google sheet and append it into URL. I have added the plus (+) but still unable to pick the project_id from the google sheet. Posting will not be possible without this parameter. It is not throwing any error but still unable to post to the project's system. Here is the code: What am I not doing right?
function sendBudget(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
// used getLastRow() function [1] to narrow the array to have only cells with data.
var range = sheet.getRange("AO2:AO"+sheet.getLastRow()).getValues();
var searchString = "3";
for (var i = 0; i<range.length; i++) {
if(range[i][0] == searchString) {
var lastRow = sheet.getRange(2+i,1,1,41).getValues();
var project_id = lastRow[0][40];
var data = {
'amount':lastRow[0][7]*10,
};
var payload = JSON.stringify(data);
var options = {
'method': 'POST',
'Content-Type': 'application/json',
'payload' : data,
};
var url = 'https://vnext.10000ft.com/api/v1/projects/'+ project_id +'/budget_items?item_type=TimeFeesDays&auth=token';
var response = UrlFetchApp.fetch(url , options);
if (response.getResponseCode() === 200) {
var json = JSON.parse(response);
var id = json["id"];
sheet.getRange(2+i, 41).setValue(4);
}
else {
sheet.getRange(2+i, 41).setValue(5);
}
}
}}
I realized that the project_id was picking the wrong cell, so all did change is the row number in the variable:
var project_id = lastRow[0][40];
I am new to javascript/google app script and I'm trying to find the best script to complete a task. I've got a google sheet where I need to check values in certain columns, and depending on a matching case it returns that row data that are to be posted through external API. Then the response (Ideally a project come to be set back to a different column of the same row.
I am not sure the most efficient way to search through the specific columns and grabbing not just that value but the entire row and pass them to external API.
Here is what I tried but failed miserably. Someone who can help me craft the code will please rescue me here.
function findTheLastRow(){
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("W2:W").getValues();
var searchString = "0";
if(searchString = "0")
{
var lastRow = lastRowData()
var data = {
'name':lastRow[2],
'client': lastRow[3],
'starts_at':lastRow[5],
'ends_at':lastRow[6],
'project_state':lastRow[4],
};
var payload = JSON.stringify(data);
var options = {
'method': 'POST',
'Content-Type': 'application/json',
'payload' : data,
};
var url = 'https:....';
var response = UrlFetchApp.fetch(url, options);
var json = JSON.parse(response);
var id = json ["id"];
}
You can use getLastRow() function [1] to narrow the array to have only cells with data. You have to take in account that getValues function [2] returns a 2D array every time. And you can use setValue function [3] to set the value on the cell with the match.
function findTheLastRow(){
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("W2:W"+sheet.getLastRow()).getValues();
var searchString = "0";
for (var i = 0; i<range.length; i++) {
if(range[i][0] == searchString) {
var lastRow = sheet.getRange(2+i,1,1,7).getValues(); //Assuming you only need 7 columns from each row
var data = {
'name':lastRow[0][2],
'client': lastRow[0][3],
'starts_at':lastRow[0][5],
'ends_at':lastRow[0][6],
'project_state':lastRow[0][4],
};
var payload = JSON.stringify(data);
var options = {
'method': 'POST',
'Content-Type': 'application/json',
'payload' : data,
};
var url = 'https:....';
var response = UrlFetchApp.fetch(url, options);
var json = JSON.parse(response);
var id = json["id"];
//Assuming you want id value in 8th column
sheet.getRange(2+i, 8).setValue(id);
}
}
}
[1] https://developers.google.com/apps-script/reference/spreadsheet/sheet#getlastrow
[2] https://developers.google.com/apps-script/reference/spreadsheet/range#getvalues
[3] https://developers.google.com/apps-script/reference/spreadsheet/range#setvaluevalue
So I'm trying to parse this https://www.quandl.com/api/v3/datasets/CHRIS/CME_GC1 and in my code, show nothing but the last price([4] in data). However, not exactly sure how to do it. So far I have this following code
And that's where I'm stuck.
let goldData = new XMLHttpRequest();
goldData.open('GET', 'https://www.quandl.com/api/v3/datasets/CHRIS/CME_GC1', true);
goldData.send();
goldData.onload = function (response) {
let goldResponse = JSON.parse(this.response);
}
Here you go!
let goldData = new XMLHttpRequest();
goldData.open('GET', 'https://www.quandl.com/api/v3/datasets/CHRIS/CME_GC1', true);
goldData.onload = function() {
var lastPrices = [];
var response = JSON.parse(this.responseText);
var data = response.dataset.data; // get data object from nested object.
// iterate through the data maps to retrieve all the prices.
var dataLength = data.length;
for (var i=0; i<dataLength; i++) {
var d = data[i];
lastPrices.push(d[4]);
}
console.log('lastPrices:', lastPrices);
// last prices from newest to oldest.
}
goldData.send();
I am working with a third-party API (from company called Simpli.fi) in Google Apps Script to pull some data into a spreadsheet. I am able to authenticate my API call just fine and can pull all of my required data with one URL. The issue is that the way the URL to call this API is formatted is as follows:
https://app.simpli.fi/api/organizations/{CLIENT_ID}/{SOME_ENDPOINT}
It works when I plug in one client id and one endpoint, however I do not want to pull the data individually for each client with each data endpoint.
I wish to pull data on all of my clients and also wish to access multiple endpoints, such as "/audiences" or "/campaigns". I am hoping there is a way (similar to Promises in JavaScript) that I can iterate through multiple URLs to fetch all of the data from the API.
For now, I am simply focusing on pulling all the data I want from the "/audiences" endpoint for all of my clients. I have set up an array accessing my Google Sheet that contains all the client codes and have plugged this into the URL with a for loop, which works just fine:
// iterate through all URL endpoints and client codes
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('formatting');
var range = sheet.getRange(['B2:B']).getValues();
var clients = range.filter(String);
var urlOneArray = [];
for (var i = 0; i < clients.length; i++) {
var urlOne = [baseURL + clients[i] + '/audiences'];
for (var j = 0; j < urlOne.length; j++) {
urlOneArray = urlOne[j];
Logger.log(urlOneArray);
}
}
The above logs a list of each built out URL as desired.
After pushing all of the built-out URLs into the urlOneArray, I tried calling with UrlFetchApp.fetchAll:
for (i=0; i < urlOneArray.length; i++) {
var response = UrlFetchApp.fetchAll(urlOneArray[i], params);
Utilities.sleep(500);
Logger.log(response);
}
When trying to use this method, I receive this error:
"Cannot find method fetchAll(string,object). (line 35, file "Code")"
If there is a way to iterate through multiple URLs to gather all of the data from the API in one pull, I would really appreciate some pointers.
Here is the full script:
// authenticate API call
var X_USER_KEY = 'XXXX';
var X_APP_KEY = 'XXXX';
function simplifiService() {
var baseURL = 'https://app.simpli.fi/api/organizations';
// iterate through all URL endpoints and client codes
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('formatting');
var range = sheet.getRange(['B2:B']).getValues();
var clients = range.filter(String);
var urlOneArray = [];
for (var i = 0; i < clients.length; i++) {
var urlOne = [baseURL + clients[i] + '/audiences'];
for (var j = 0; j < urlOne.length; j++) {
urlOneArray = urlOne[j];
Logger.log(urlOneArray);
}
}
var params = {
method: 'GET',
headers: {
"x-app-key": X_APP_KEY,
"x-user-key": X_USER_KEY
},
muteHttpExceptions: true
}
for (i=0; i < urlOneArray.length; i++) {
var response = UrlFetchApp.fetchAll(urlOneArray[i], params);
Utilities.sleep(500);
Logger.log(response);
}
if (response.getResponseCode() === 200) {
var data = JSON.parse(response);
Logger.log(data);
} else {
Logger.log('Error: ' + response.getResponseCode());
}
getData(data);
}
// parse out JSON data
function getData(data) {
var date = new Date();
var geoFenceId = data.audiences;
var geoFenceName = data.audiences[0].name;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Campaign Data');
//sheet.appendRow([date, geoFenceId, geoFenceName]);
}
Issue:
Invalid syntax: UrlFetchApp.fetchAll(requests Object[]) accepts object array, while you're providing a string and a object as argument.
Solution:
Valid Syntax: Create a object array for each endpoint/client and provide it as a argument to fetchAll()
Snippet:
function copyParams() {//shallow clone params object
for (var i in params) {
this[i] = params[i];
}
}
var endPoints = ['/audiences', '/campaigns'];
var requests = [];
var url, obj;
clients.forEach(function(client) {
endPoints.forEach(function(endPoint) {
obj = new copyParams();
url = baseUrl + '/' + client[0] + endPoint;
obj.url = url;
requests.push(obj);
});
});
console.log(requests);
var responseArray = UrlFetchApp.fetchAll(requests);
console.log(responseArray);
References:
UrlFetchApp.fetchAll
Array#forEach