Google Spreadsheet - return values to multiple columns - javascript

I'm trying to do something that is beyond my junior coding capabilities. I have created a function that will parse API data into Google Spreadsheet, but no matter what I've tried (and searched online for answers), the results are only being posted to a single column.
The code I am using currently is:
function getAPIdata (URL,key){
var apiurl = "https://example.com/Site/"+URL+"/students?&ID="+key
var rank_data = parse(apiurl)
var result = []
var data_dictionary = rank_data.Student
for (var i in data_dictionary){
result.push(data_dictionary[i].Name)
result.push(data_dictionary[i].Grade)
}
return result
}
The data in question that is being parsed is
Student": [
{
"Name": ​Adam,
"Grade": 75
},
{
"Name": ​Alan,
"Grade": 90
}
What is happening is that when I call the function in excel I am getting a single column with:
Adam
75
Alan
90
What I would like to do is have the following (spaces here delineate another column)
Adam 75
Alan 90
Basically, I have a 1x4 output and I would like a 2x2 output. Is there anyway I could do this? I realize I can call the function twice and push different data sets each time, but in this case I can only call the API once for all data. I thought about potentially pulling the data, caching it but before I delve down learning a path that will not bear fruit, I was hoping some of the experts here could weigh in.
Thanks for reading!

I think you can use [] and push a row at a time, like
function getAPIdata (URL,key){
var apiurl = "https://example.com/Site/"+URL+"/students?&ID="+key
var rank_data = parse(apiurl)
var result = []
var data_dictionary = rank_data.Student
for (var i in data_dictionary){
result.push([data_dictionary[i].Name, data_dictionary[i].Grade])
}
return result
}

Related

Can I use two parameter event for one function?

What I want to do is change the url.
Replace the Object word with an event parameter called e1.
Replace the word field with the event parameter e2.
I know this code is not working.
But I don't know how to do it.
The following is my code that I just wrote.
function getAllFieldValue(e1,e2) {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var url = 'test123.my.salesforce.com/services/data/v44.0/queryAll?q=SELECT Field FROM Object';
var url = url.replace('Object',e1);
var url = url.replace('Field',e2);
var response = UrlFetchApp.fetch(url,getUrlFetchOptions());
var json = response.getContentText();
var data = JSON.parse(json);
var fieldValues = data.records;
for(var i=0;i<fieldValues.length;i++){
var fieldValue = fieldValues[i].e;
ss.getRange(i+1,1).setValue(fieldValue);
}
}
I want to take the data from another database through this code and put it in the Google spreadsheet.
For e1, it means the object value selected in the dropbox.
For e2, it means the field of the object selected in the drop box.
Is there a way to use two event parameters for one function?
I look forward to hearing from you.
====================
Please understand that I am using a translator because I am not good at English.
Checking fieldValues[i] in Logger.log returns the following values:
[{
attributes={
type=Account,
url=/services/data/v44.0/sobjects/Account/0015i00000BS03VAAT
},
Name=University of Arizona
},
{
attributes={
type=Account,
url=/services/data/v44.0/sobjects/Account/0015i00000BS03TAAT
},
Name=United Oil & Gas Corp.
},
{
attributes={
type=Account,
url=/services/data/v44.0/sobjects/Account/0015i00000BS03ZAAT
},
Name=sForce
}]
The issues I am currently experiencing are as follows.
If I select 'Name' from the drop-down list, ec2 becomes 'Name'.
As far as I'm concerned,
var fieldName = fieldValues[i].e2 is
var fieldName = fieldValues[i].Name
It means that.
I think fieldValues[i].e2 should return the values of University of Arizona, United Oil & Gas Corp, sForce.
But in reality nothing is returned.
var fieldName = fieldValues[i].Name works properly.
I think there is a problem with fieldValues[i].e2
This is the problem I'm currently experiencing.
There was no problem with the parameters e1, e2, which I thought was a problem. The reason why the code did not work is because of the for loop var fieldValue = fieldValues[i].e; Because it didn't work properly.
var fieldName = fieldValues[i].e2
to
var fieldName = fieldValues[i][e2]
After modifying it like this, the code works properly.

Extract specific nested array in JSON Objects that match data with Javascript

I'm working with an NBA API where one of the features is finding players by their last name.
The issue I have; is that multiple players can have the same last name, of course.
An example of the response from the API when sorting with last names:
"players": [
0: {
"firstName":"Anthony"
"lastName":"Davis"
"teamId":"17"
"yearsPro":"9"
"collegeName":"Kentucky"
"country":"USA"
"playerId":"126"
"dateOfBirth":"1993-03-11"
"affiliation":"Kentucky/USA"
"startNba":"2012"
"heightInMeters":"2.08"
"weightInKilograms":"114.8"
1: {
"firstName":"Deyonta"
"lastName":"Davis"
"teamId":"14"
"yearsPro":"3"
"collegeName":"Michigan State"
"country":"USA"
"playerId":"127"
"dateOfBirth":"1996-12-02"
"affiliation":"Michigan State/USA"
"startNba":"2016"
"heightInMeters":"2.11"
"weightInKilograms":"107.5"
}
I limited the results here, but it goes on and on, etc.
So, I am looking to do two things:
First, extract/filter the correct player using their first name and last name.
In said extraction, I still need the complete array information when it is matched.
So essentially, I want 'Deyonta Davis', but when found - I also need the rest of said player's information (years pro, college, country, etc.)
I already have a command set up to retrieve the first result of the nested data in this API via last name - where the command takes the last name you input and sends the first result. The precise problem is that the first result is likely not to be the guy you are looking for.
The goal is to include first & last name to avoid pulling the wrong player.
A snippet of how I currently call the information via last name:
// Calling API
const splitmsg = message.content.split(' ')
var lastnameurl = "https://api-nba-v1.p.rapidapi.com/players/lastName/" + splitmsg[1];
axios.get(lastnameurl, {
headers: {
"x-rapidapi-key": apikey,
"x-rapidapi-host": apihost
}
// Extracting Player Information (first result)
var playerfirstname = response.data.api.players[0].firstName;
var playerlastname = response.data.api.players[0].lastName;
var collegename = response.data.api.players[0].collegeName;
var countryname = response.data.api.players[0].country;
var playerDOB = response.data.api.players[0].dateOfBirth;
var yrspro = response.data.api.players[0].yearsPro;
var startednba = response.data.api.players[0].startNba;
Any help would be appreciated, thank you.
If I understand the question correctly the task is:
Retrieve first matching object from an array where properties firstName and lastName equal to desired values.
To achieve this you could use build in find function.
const player = array.find(el => {
return el.firstName === "Deyonta" && el.lastName === "Davis"
});
Keep in mind if there is no such object in array the player will be undefined.

2D Arrays in Google Apps Script

I am self taught with Apps Script, so generally approach one problem at a time, as it comes up. Arrays are confusing!
I am using an API to get the number of social followers for Facebook, Twitter and Instagram accounts. Here is the code so far. Note I have removed the API call specifics for privacy, I have also used fake profile ID's in the above, for example 1111 = Facebook, 2222 = Twitter, etc...
var response = UrlFetchApp.fetch(endpointUrl, params);
var jsonss = JSON.parse(response.getContentText());
var dataset = jsonss.data;
Logger.log(dataset);
[{dimensions={customer_profile_id=1111, reporting_period.by(day)=2021-10-31}, metrics={lifetime_snapshot.followers_count=407919.0}}, {dimensions={reporting_period.by(day)=2021-10-31, customer_profile_id=2222}, metrics={lifetime_snapshot.followers_count=1037310.0}}, {dimensions={reporting_period.by(day)=2021-10-31, customer_profile_id=3333}, metrics={lifetime_snapshot.followers_count=806522.0}}]
then map the array -
var followers = dataset.map(function(ex){return [ex.dimensions,ex.metrics]});
Logger.log(followers);
[[{reporting_period.by(day)=2021-10-31, customer_profile_id=1111}, {lifetime_snapshot.followers_count=407919.0}], [{reporting_period.by(day)=2021-10-31, customer_profile_id=2222}, {lifetime_snapshot.followers_count=1037310.0}], [{customer_profile_id=3333, reporting_period.by(day)=2021-10-31}, {lifetime_snapshot.followers_count=806522.0}]]
Now I get stuck, I am not sure how to get 'followers_count' when 'profile_id=1111', can someone please help? I have tried using another map function ( var followers = dataset.map(function(ex){return [ex.dimensions.map(function(ex2){return [ex2.followers_count]}]}); ) however this doesn't work...
Any suggestions to push me in the right direction is very much appreciated!
If Logger.log(followers); is [[{reporting_period.by(day)=2021-10-31, customer_profile_id=1111}, {lifetime_snapshot.followers_count=407919.0}], [{reporting_period.by(day)=2021-10-31, customer_profile_id=2222}, {lifetime_snapshot.followers_count=1037310.0}], [{customer_profile_id=3333, reporting_period.by(day)=2021-10-31}, {lifetime_snapshot.followers_count=806522.0}]] and you want to retrieve the value of lifetime_snapshot.followers_count: 407919 by using customer_profile_id: 1111, how about the following sample script?
Sample script:
In this sample script, your values of followers is used.
const profile_id = 1111; // Please set customer_profile_id you want to use.
const res = followers.reduce((ar, [a, b]) => {
if (a["customer_profile_id"] == profile_id) {
ar.push(b["lifetime_snapshot.followers_count"]);
}
return ar;
}, []);
if (res.length == 0) return;
const followers_count = res[0];
console.log(followers_count);
When this script is used for your values of followers, I thought that 407919 is retrieved.
If the same IDs are existing, you can retrieve them using console.log(res).
Reference:
reduce()

Loop function on Apps Scripts & Google Natural Language API

I am learning how to code so sorry if this is too basic, but I am getting troubles here:
I've been trying to invoke the Google Natural Language API, to give me information about information on 210 rows of my Google Spreadsheet (the whole table has 211 rows). I would like to save the results on 1 Json File.
I am trying to run a loop with the code below, but I am getting the Json file only with the information corresponding to the 1st row. Tried as well to put the "Driveapp.createFile line of code" inside of the loop function, but then I have many Json files, each one with the information corresponding to one row. And what I would like is 1 Json file, with the corresponding information of the 210 rows.
I would appreciate your help, please.
function analyzeText() {
var client = "Spreadsheet_ID";
var query = SpreadsheetApp.openById(client).getSheetByName("1. Template");
var result = SpreadsheetApp.openById(client).getSheetByName("Teste - Natural Language API");
var lrow = query.getLastRow();
for(var i=2; i<=211;i++)
{
var text = query.getRange(i,211).getValue()
var requestUrl = [
'https://language.googleapis.com/v1beta2/documents:analyzeEntities?key=',
'API_KEY_XXXXXXXXXXXXXXXXXXX'
].join("");
var data = {
"document": {
"language": "en-us",
"type": "PLAIN_TEXT",
"content": text
},
"encodingType": "UTF8"
};
var options = {
method : "POST",
contentType: "application/json",
payload : JSON.stringify(data)
};
var response = UrlFetchApp.fetch(requestUrl, options);
var data = JSON.parse(response);
}
DriveApp.createFile('response3.json', response, MimeType.PLAIN_TEXT);
}
I would suggest you instead of the approach you are taking (using a for loop and the method getValue(), which it's a slow method to call in a loop), consider this one I am giving you with this code:
function analyzeText() {
var clientId = "your-sheet-id";
var ss = SpreadsheetApp.openById(clientId);
var templateSheet = ss.getSheetByName("1. Template");
// .getRange(row, column, numRows) -> From the first row and col, take the next 4 rows
// Modify these arguments depending in where you want to start and how many rows you want
var data = templateSheet.getRange(1, 1, 4).getValues();
// You will get an array 2D, using join you will able to get an string from
// all the elements in that array
var text = data.join();
var requestUrl = [
'https://language.googleapis.com/v1beta2/documents:analyzeEntities?key=',
'API_KEY_XXXXXXXXXXXXXXXXXXX'
].join("");
// Now text will have all your cell values and you only need to do one request
var data = {
"document": {
"language": "en-us",
"type": "PLAIN_TEXT",
"content": text
},
"encodingType": "UTF8"
};
var options = {
method : "POST",
contentType: "application/json",
payload : JSON.stringify(data)
};
var response = UrlFetchApp.fetch(requestUrl, options);
var data = JSON.parse(response);
DriveApp.createFile('response3.json', response, MimeType.PLAIN_TEXT);
}
In this way, you only need to make one request and it will be faster than running 211 times your loop. I would also recommend you to check:
Apps Script Quotas: Running your code as you have it, it would give you more chances of hitting these quotas.
Best Practices: You can check more about the best practices so you can have a better idea about why I was telling you to avoid the getValue() method in a loop.

Combining JSON Arrays with jQuery

I've spent all morning messing with this now and reading on here, but have found myself going round in circles!
I am trying to draw a chart using the excellent AmCharts Javascript Charts, to show me stock holding as a bar chart and stock turn as a line chart.
I cannot get both sets of data from one query to my database, and cannot use AmCharts StockChart as it is not time based data... therefore, I have two sets of data which need combining with Javascript.
The data is being pulled from a database and returned successfully as JSON arrays similar to this:
SALES DATA:
[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
{"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}]
STOCK DATA:
[{"brandName":"Gibson","stockValue":"1234"},
{"brandName":"Fender","stockValue":"975"},
{"brandName":"Epiphone","stockValue":"834"}]
Obviously the actual figures are made up in that example!
Now, what I need to do is to combine those to create this:
COMBINED DATA
[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55","stockValue":"975"},
{"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43","stockValue":"1234"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13","stockValue":"834"}]
What we have there is the Sales Dataset combined with Stock Dataset to add the additional data of stockValue added to the corresponding brandName record.
I have tried using $.extend but I can't figure out how to use it in this situation.
It is perhaps important to note that the data pairs might not necessarily be in the right order, and it is possible, though unlikely, that there might not be a match, so some kind of zeroing error catching must be implemented.
What you'll need to do first is transform the data into two objects, whose properties are the values you want to merge together:
{
"Fender" : {"gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
"Gibson" : {"gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
"Epiphone" : {"gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}
}
and
{
"Gibson": {"stockValue":"1234"},
"Fender": { "stockValue":"975"},
"Epiphone": { "stockValue":"834"}
}
Once the transformation is done, you'll have two objects that you can merge using $.extend or other functions.
Update
For large sets, this gives results in nearly linear time:
var salesa = {}, stocka = {};
$.each(sales, function(i, e) {
salesa[e.brandName] = e;
});
$.each(stock, function(i, e) {
stocka[e.brandName] = e;
});
var combine = {};
$.extend(true, combine, salesa, stocka)
More speed can be tweaked if the merging happened during the second transformation callback ($each(stock...) instead of a separate call to $.extend() but it loses some of its obviousness.
I think what's he's trying to do is join the two datasets as if they were tables, joining by the brandName. From what I've been testing jQuery's $.extend() function does not take care of that, but merges objects according to their index in the Object arrays that it receives.
I think the matching of the key would need to be done manually.
stock = [{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
{"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}];
value = [{"brandName":"Gibson","stockValue":"1234"},
{"brandName":"Fender","stockValue":"975"},
{"brandName":"Epiphone","stockValue":"834"}];
var results = [];
$(stock).each(function(){
datum1 = this;
$(value).each(function() {
datum2 = this;
if(datum1.brandName == datum2.brandName)
results.push($.extend({}, datum1, datum2));
});
});
Which would result in:
[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55","stockValue":"975"},
{"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43","stockValue":"1234"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13","stockValue":"834"}]
Instead of what the use of $.extend() returns:
[{"brandName":"Gibson","gearShiftedPerMonth":"35","retailSalesPerMonth":"55","stockValue":"1234"},
{"brandName":"Fender","gearShiftedPerMonth":"23","retailSalesPerMonth":"43","stockValue":"975"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13","stockValue":"834"}]
If your example code reflects reality, then jQuery's $.extend will be the wrong tool for this.
It blindly copies data from one object to another. Notice that the order of your data is not consistent. The SALES DATA has Fender first, while the STOCK DATA has gibson first.
So jQuery's $.extend is mixing the two results. The "gearShifted" and "retailSales" for Fender is ending up with the "brandName" and "stockValue" for Gibson.
What you'll need is to iterate one array, and look up the "brandName" in the other, and then copy over the data you want. You could use $.extend for that part of it if you like...
var sales_data =
[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
{"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}]
var stock_data =
[{"brandName":"Gibson","stockValue":"1234"},
{"brandName":"Fender","stockValue":"975"},
{"brandName":"Epiphone","stockValue":"834"}]
var combined = $.map(sales_data, function(obj, i) {
return $.extend({}, obj, $.grep(stock_data, function(stock_obj) {
return obj.brandName === stock_obj.brandName
})[0]);
});
Note that this is not terribly efficient, but unless the data set is enormous, it shouldn't be an issue.
DEMO: http://jsfiddle.net/sDyKx/
RESULT:
[
{
"brandName": "Fender",
"gearShiftedPerMonth": "35",
"retailSalesPerMonth": "55",
"stockValue": "975"
},
{
"brandName": "Gibson",
"gearShiftedPerMonth": "23",
"retailSalesPerMonth": "43",
"stockValue": "1234"
},
{
"brandName": "Epiphone",
"gearShiftedPerMonth": "10",
"retailSalesPerMonth": "13",
"stockValue": "834"
}
]
In vanilla javascript you can do:
var sales = [{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
{"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}];
var stock = [{"brandName":"Gibson","stockValue":"1234"},
{"brandName":"Fender","stockValue":"975"},
{"brandName":"Epiphone","stockValue":"834"}];
var combined = stock.slice(0);
for (var i = 0; i < stock.length; i++) {
for (var j = 0; j < sales.length; j++) {
if (stock[i].brandName === sales[j].brandName) {
for (var attrname in sales[j]) { combined[i][attrname] = sales[j][attrname]; }
}
}
}
JSON.stringify(combined)
produces
[
{"brandName":"Gibson","stockValue":"1234","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
{"brandName":"Fender","stockValue":"975","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
{"brandName":"Epiphone","stockValue":"834","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}
]

Categories