Looping JSON response in google script - google-apps-script

We are trying to work out how to loop through a JSON response.
We have managed to call the API of our 3rd party database and pull the first line (the headers) but need to loop through all the rows and then copy them to a google sheets.
Any ideas?

Not too much information on what information is in the JSON you're receiving or how you're going to handle it, so here's my general answer:
Once you receive the full JSON data, you can turn it into an object by using JSON.parse( jsonString ) where jsonString is the data you received from the API. More on that here.
If your row values are stored in an array, you can easily loop through them using the forEach() method. More on that here. Below is example JSON data and a function to parse through it.
Example Data
{
"name": "Example Data",
"rows": [
{
"string": "I'm a string",
"number": 14
},
{
"string": "Chicago",
"number": 36
}
]
}
Example Parse Function
function handleJsonResponse(data) {
//Parse response and get sheet
var response = JSON.parse(data);
var spreadsheet= SpreadsheetApp.getActive().getSheetByName(response.name);
if (spreadsheet === null) {
//Error here
}
//Loop through data and add it to spreadsheet
response.rows.forEach(function( row, index ) {
//This function will be executed for every row in the rows array
//Set the index of the row to the first column in the sheet
//2 is added to the index for the row number because index starts at 0 and we want to start adding data at row 2
spreadsheet.getRange(index + 2, 1).setValue(index);
//Set the value of string to the second column
spreadsheet.getRange(index + 2, 2).setValue(row.string);
//Set the value of number to the third column
spreadsheet.getRange(index + 2, 3).setValue(row.number);
});
}
If you have any questions feel free to ask.

Related

Can I list all the times I saved a file?

My company uses Google Drive and we are still mainly using Microsoft Office documents.
Is it possible to see my activity or each time I saved a document in the Shared Drive even though it is not Google Documents I want to see the activity of?
I found this link https://developers.google.com/apps-script/advanced/drive-activity , but the code only returns Google Docs activity. Not non-Google documents like Word and Excel.
You might want to check if using Revisions.list will fit your needs.
Revisions.list
Lists the current file's revisions.
Path parameters:
fileId - The ID of the file.
Optional query parameters:
fields - The paths of the fields you want included in the response. If not specified, the response includes a default set of fields specific to this method. For development you can use the special value * to return all fields, but you'll achieve greater performance by only selecting the fields you need. For more information, see Return specific fields for a file.
pageSize - The maximum number of revisions to return per page. Acceptable values are 1 to 1000, inclusive. (Default: 200)
pageToken - The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.
Response Body:
{
"kind": "drive#revisionList",
"nextPageToken": string,
"revisions": [
revisions Resource
]
}
Revisions Resource Representation:
You can obtain useful information related to the revision done to the file such as the modified time and last modifying user.
{
"kind": "drive#revision",
"id": string,
"mimeType": string,
"modifiedTime": datetime,
"keepForever": boolean,
"published": boolean,
"publishedLink": string,
"publishAuto": boolean,
"publishedOutsideDomain": boolean,
"lastModifyingUser": {
"kind": "drive#user",
"displayName": string,
"photoLink": string,
"me": boolean,
"permissionId": string,
"emailAddress": string
},
"originalFilename": string,
"md5Checksum": string,
"size": long,
"exportLinks": {
(key): string
}
}
You can specify specific fields in your request under fields parameter so that only necessary information can be shown in the response body:
Sample Fields Parameter:
nextPageToken, revisions/id, revisions/modifiedTime, revisions/lastModifyingUser/displayName, revisions/lastModifyingUser/emailAddress
Sample Response Body:
{
"revisions": [
{
"id": "1898",
"modifiedTime": "2020-12-16T22:29:02.971Z",
"lastModifyingUser": {
"displayName": "User1 Test",
"emailAddress": "user1#example.com"
}
}
]
}
Play with DriveApps file.getLastUpdated(). This is not the same as ALL the times you've updated it but it should get the last time the file was changed. https://developers.google.com/apps-script/reference/drive/file#getLastUpdated()
Or do you really need a list of all the edit times not just the most recent one? In that case you could run a script once a day that records the lastUpdated for all the files you care about or all the files in a folder and record if they've changed. What is the use case?
Thanks for that Ron. Revisions did the trick.
It took me a while to wrap my head around it, but these are the 2 functions I used. I will try to put them together at some point when I have Drive API v3.
function listFilesInFolder() {
// get the id's of files in a folder
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow(["Name", "File-Id"]);
var folder = DriveApp.getFolderById(" ID STRING ");
var contents = folder.getFiles();
var counter = 0;
var file;
while (contents.hasNext()) {
var file = contents.next();
counter++;
data = [
file.getName(),
file.getId(),
];
sheet.getRange("C2").setValue = counter
sheet.appendRow(data);
};
};
function fileactivity() {
var revs = Drive.Revisions.list(" FileID String ");
var savedList = [];
for(var i=0; i<revs.items.length; i++) {
var revision = revs.items[i];
// modifiedByMeTime requires Drive API v3
savedList.push([revision.kind, revision.modifiedDate]);
};
var sheet = SpreadsheetApp.getActiveSheet();
Logger.log(savedList);
}

Google Apps Scripting Issue

1) I am trying to create a complete script that will take input data from a google form/google sheet and use the top row as as field names for a Freshdesk ticket while taking the last row (most current) as the data to input as the ticket data ..
2) I have coded onFormSubmit portion so it creates the general ticket however i would the data from the backend to be used as the certain field data
function onFormSubmit(e) {
if ((typeof GasFreshdesk)==='undefined') {
eval(UrlFetchApp.fetch('https://raw.githubusercontent.com/zixia/gas-freshdesk/master/src/gas-freshdesk-lib.js').getContentText())
}
var MyFreshdesk = new GasFreshdesk('https://***.freshdesk.com', 'API KEY'); // REPLACE redacted with real key
// Custom fields passed in. Use this for now - to test (then replace later with other valid values).
var customFields = {"email": "firstnamelastname#org.org",
"room": "IT",
"building": "**",
"devicesystem": "Device",
"problem": "problem"
};
var ticket = new MyFreshdesk.Ticket({description: "We have provided you with a loaner",
subject: "** - Device - Problem- " + "FullName", email: "firstnamelastname#org.org",
type: "Support Request", custom_fields: customFields});
}
What i'm looking for is a way to grab the values in the last row of data since that data is what will need to be inputted into the ticket.
function LastRow() {
var ss= SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 1");
var lr = getLastRow();
Logger.log(lr);
}

Spreadsheet display JSON data into columns and rows

I'd like to handle a bunch of data in Google Spreadsheets so I can easily create charts and all that stuff. The data come in Json format from an URL. I can successfully get those data in a Spreadsheet but I cannot figure out an easy way to distribute those data into columns of the sheet.
This is a sample of the JSON structure:
Is there any easy way to achieve my goal?
Thanks a lot.
How about this sample script? This sample script retrieves all elements in JSON data using the recursive call, and import them to Spreadsheet.
In order to use this script, please set as follows.
1. Use this script as a bound script for Spreadsheet.
1. Define json data in main() or as a global variable.
Sample JSON :
var json = {
keyA: {
ArrayA1: ["ArrayA1_val1", "ArrayA1_val2", "ArrayA1_val3"],
keyA1: "keyA1_val",
keyA2: "keyA2_val",
},
keyB: {
ArrayB1: ["ArrayB1_val1", "ArrayB1_val2", "ArrayB1_val3"],
keyB1: "keyA1_val",
keyB2: "keyA2_val",
keyB3: {
ArrayB31: ["ArrayB31_val1", "ArrayB31_val2", "ArrayB31_val3"],
ArrayB32: ["ArrayB32_val1", "ArrayB32_val2", "ArrayB32_val3"],
}
}
};
Sample Script :
function getElements(v, callback) {
for (var k in v) {
callback(
k,
Object.prototype.toString.call(v[k]).slice(8, -1).toLowerCase() === "object"
? JSON.stringify(v[k], null, "\t") : v[k],
Object.prototype.toString.call(v[k]).slice(8, -1).toLowerCase()
);
if (typeof v[k] === "object") {
getElements(v[k], callback);
}
}
}
function main() {
var ar = [];
getElements(json, function(key, value, type) {ar.push([key, value, type])});
var ss = SpreadsheetApp.getActiveSheet();
ss.getRange(ss.getLastRow() + 1, 1, ar.length, ar[0].length).setValues(ar);
}
Result :
If I misunderstand your question, I'm sorry.

Can I append data to an existing BigQuery table from a CSV file using the API?

I'm trying to use Google Apps Script to append data into a BigQuery table using the BigQuery API. The data to append is currently CSV format. So far I've found that you can stream data into BigQuery using tabledata().insertAll() but it looks like that requires json format and I'm not even convinced that it would do what I need to. Is there a straightforward solution to this that I'm missing? Because I know BigQuery supports appending, and yet everything I'm finding is really focused on loading data into new tables.
EDIT:
Sounds like tabledata().insertAll() is indeed the right method to use (hopefully). So I converted my file to json instead, but now I'm stuck on how to actually use it. I'm trying to base what I'm doing off of the reference page for it but it's still really confusing for me. Currently I am getting a 404 error when I run my code and it hits the fetch call. I'm trying to do a URL fetch, maybe that's not how I'm supposed to be doing things? I'm really new to APIs and I'm still figuring out how they work. Here's the code I currently have that's causing this:
var tableId = 'users';
var file = DriveApp.getFileById(jsonId);
//I don't know if a blob is the type that I want or not, but I'm trying it
var data = file.getBlob();
var url = 'https://www.googleapis.com/bigquery/v2/projects/PROJECT_ID/datasets/DATASET_ID/tables/tableId/insertAll'
.replace("PROJECT_ID", params.PROJECT_ID)
.replace("DATASET_ID", params.DATASET_ID)
.replace("tableId", tableId);
var response = UrlFetchApp.fetch(url, {
"kind": "bigquery#tableDataInsertAllRequest",
"skipInvalidRows": 0,
"ignoreUnknownValues": 0,
"rows": [
{
"json": data
}
],
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
This is not the most direct from csv to BQ JSON but it's some code that I'm using that should help you on the BigQuery side.
var PROJECT_ID = "xxx";
var DATASET_ID = "yyy";
function convertValuesToRows(data) {
var rows = [];
var headers = data[0];
for (var i = 1, numColumns = data.length; i < numColumns; i++) {
var row = BigQuery.newTableDataInsertAllRequestRows();
row.json = data[i].reduce(function(obj, value, index) {
obj[headers[index]] = value;
return obj
}, {});
rows.push(row);
};
return rows;
}
function bigqueryInsertData(data, tableName) {
var insertAllRequest = BigQuery.newTableDataInsertAllRequest();
insertAllRequest.rows = convertValuesToRows(data);
var response = BigQuery.Tabledata.insertAll(insertAllRequest, PROJECT_ID, DATASET_ID, tableName);
if (response.insertErrors) {
Logger.log(response.insertErrors);
}
}
This allows you to supply any GAS style value matrix (from getValues or indeed Utilities.parseCsv)
convertValuesToRows will take a 2d array of strings (with headers) and encode it in the format BigQuery needs, e.g.
[["H1", "H2", "H3"],
[1 , 2 , 3 ],
[4 , 5 , 6 ]];
will be added to the insertRows request int he form of key value pairs i.e.
[{H1: 1, H2: 2, H3: 3},
{H1: 4, H2: 5, H3: 6}]
You only need to worry about the first representation as that is what you pass into bigQueryInsertData together with the table name you want to feed the data in to (The schema of the table needs to match what you are sending) and the converter function is called from within.
Utilities.parseCsv already returns a 2d array of strings so you can basically call bigQueryInsertData(Utilities.parseCsv(data.getDataAsString()), "myTable")

Fill multiple rows in google spreadsheet via google script

I am currently working on a semester project for my university in which we want to log data from an Arduino to a Google Sheet.
I was following the numerous tutorials and examples that I could find on Google and it worked so far really, really well. My Arduino is able to upload data to said spreadsheet.
Unfortunately all those examples always only deal with one row to be filled. For our project we would like to fill 2 or 3 lines simultaneously.
I will shortly show what I have done so far and maybe you can help me solve my (probably easy) problem.
I created a google spreadsheet in which I want to log my data
I used the script from a tutorial that should fill one row.
By typing the following line in my browserhttps://script.google.com/macros/s/<gscript id>/exec?tempData=datahereI am now able to fill row one with my data in enter in the end of the url.
But how do I progress now, when I want to fill two or three rows of the table? I say that the author of the code already implemented an option to fill the third row, yet I can't find out what to input in my url then to fill it with data.
All my attempts to write something like
https://script.google.com/macros/s/<gscript id>/exec?tempData=datahere&tempData1=value2
just ended in writing
datahere&tempData1=value2
in my first row, not filling datahere into the first and value2 in to the second row.
How can I provide and write multiple rows of data?
The code in this script is:
/*
GET request query:
https://script.google.com/macros/s/<gscript id>/exec?tempData=data_here
*/
/* Using spreadsheet API */
function doGet(e) {
Logger.log( JSON.stringify(e) ); // view parameters
var result = 'Ok'; // assume success
if (e.parameter == undefined) {
result = 'No Parameters';
}
else {
var id = '<ssheet id>'; // Spreadsheet ID
var sheet = SpreadsheetApp.openById(id).getActiveSheet();
var newRow = sheet.getLastRow() + 1;
var rowData = [];
//var waktu = new Date();
rowData[0] = new Date(); // Timestamp in column A
for (var param in e.parameter) {
Logger.log('In for loop, param='+param);
var value = stripQuotes(e.parameter[param]);
//Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'tempData': //Parameter
rowData[1] = value; //Value in column B
break;
case 'tempData1':
rowData[2] = value; //Value in column C
break;
default:
result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));
// Write new row below
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
// Return result of operation
return ContentService.createTextOutput(result);
}
/**
* Remove leading and trailing single or double quotes
*/
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}
I would suggest the following:
Create a 2d array of your data you wish to write to the spreadsheet. If your client on Arduino were using JavaScript this might look like :
var data = [
["row1value1", "row1value2"],
["row2value1", "row2value2"]
];
Convert this to JSON, again in JavaScript this might look like:
var json = JSON.stringify(data);
This gives you a string representation of your array.
Now make your request using this data. I would suggest you should look at using doPost instead of doGet, as you are sending data to the spreadsheet that updates state. However, for the purposes of getting something working, your URL would look like:
https://script.google.com/<.....>/exec?myarray=<stringified JSON>
In Apps Script, in your doGet (again, consider using doPost instead), you could then use:
// Get the JSON representation of the array:
var json = e.parameter.myarray;
// Convert back to 2d array
var data = JSON.parse(json);
Now you can write this to a Range in Sheets using setValues, e.g. assuming a rectangular 2d array:
sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
Hope this helps