"The coordinates or dimensions of the range are invalid" - json

I am working on a Google Apps Script that links with a REST API and puts the data into a Google Sheet.
I have successfully done this once, but upon accessing some different data I get the error message
"The coordinates or dimensions of the range are invalid"
when they work perfectly fine on my other script. All data accessed is JSON so I am bit confused and is from the same source. The code I am using is:
function stats () {
var logIn = {
"Authorization" : "Basic " + Utilities.base64Encode("XXXX" + ':' + "XXXX")
};
var url = "XXXXX";
var params = {
"method":"GET",
"headers":logIn, };
var response = UrlFetchApp.fetch(url, params);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("XXXX");
var dataAll = JSON.parse(response.getContentText()); //
var dataSet = dataAll;
var rows = [],
data;
for (i = 0; i < dataSet.length; i++) {
data = dataSet[i];
rows.push([XXXX]); //your JSON entities here
}
dataRange = sheet.getRange(1, 1, rows.length, 1);
dataRange.setValues(rows);
}
I have combined pieces of code from around the web and this works on my other script. The error appears on this line:
dataRange = sheet.getRange(1, 1, rows.length, 1);
I believe the issue is with the data I am accessing but I do not know how to alter the script for it to work.
The JSON data that works is shown like:
{
id: XXX,
group: XX,
text: "XXXX?",
creation_date: XXXX,
created_by: "XXXXX",
tags: [
"XXXX"
]
}
And the data that is causing the error is shown as:
{
2016-02-29: {
XXX: 0,
XXX: 0
},
I have had to 'XXXX' out a lot of the private information - apologies. Any help would be appreciated.

Javascript's length property is for indexed arrays and does not apply to Objects so dataSet.length returns undefined and the loop never executes.
To get the length of the object you can use Object.keys(dataSet).length as outlined here.

Related

Writing a request JSON for fetchURL in Google Scripts: Script runs twice?

sorry in advance for the long question. I am trying to create a Google Sheet that tells me how many hours each of my contractors has logged on Clockify each the month. (Full code at the bottom)
In short my problem is creating a JSON file for the UrlFetchApp.fetch() request to the Clockify API using input from the google sheet.
I want the JSON to look like this:
var newJSON = {
"dateRangeStart": "2022-01-01T00:00:00.000",
"dateRangeEnd": "2022-01-31T23:59:59.000",
"summaryFilter": {
"groups": ["USER"],
"sortColumn": "GROUP"
}
}
var payload = JSON.stringify (newJSON);
And when I use this code, it works perfectly. However, the start and end dates are variables that I compute in the google sheet, as I need these dates to change each month. I wrote a function that gives me the correct outputs ("2022-01-01T00:00:00.000", "2022-01-31T23:59:59.000"), but when I reference the cells in google sheets, I get a 400 error saying that the API was not able to parse the JSON.
Function in Script:
function GetHours(userName, startDate, endDate) {
var newJSON = {
"dateRangeStart": startDate,
"dateRangeEnd": endDate,
"summaryFilter": {
"groups": ["USER"],
"sortColumn": "GROUP"
}
}
var payload = JSON.stringify (newJSON);
...}
Calling the function in sheets:
=GetHours(C3,$D$45,$D$46)
Output error message:
Exception: Request failed for https://reports.api.clockify.me returned code 400. Truncated server response: {"code":400,"message":"generateSummaryReport.arg1.dateRangeEnd: Field dateRangeEnd is required, generateSummaryReport.arg1.dateRangeStart: Field da... (use muteHttpExceptions option to examine full response)
A weird thing is happening when I use Logger.log(payload), which may be the root of the problem. It appears that the code runs twice, and the first time the payload JSON is correct, but the second it is incorrect.
First time:
{"dateRangeStart":"2022-01-01T00:00:00.000","dateRangeEnd":"2022-01-31T23:59:59.000","summaryFilter":{"groups":["USER"],"sortColumn":"GROUP"}}
Second time:
{"summaryFilter":{"groups":["USER"],"sortColumn":"GROUP"}}
I have tried a bunch of solutions, but really it boils down to referencing the Google sheet in the JSON. When I copy and paste the output of my date calculation into the JSON, it works. When I create a variable in Scripts with the date calculation output, it works. When I return startDate, it gives me "2022-01-01T00:00:00.000", which is correct. I just don't understand what is going wrong. Thanks for your help!
Full code:
const APIbase = "https://api.clockify.me/api/v1"
const APIreportsbase = "https://reports.api.clockify.me/v1"
const myAPIkey = "[HIDDEN FOR PRIVACY]"
const myWorkspaceID = "[HIDDEN FOR PRIVACY]"
function GetHours(userName, startDate, endDate) {
var newJSON = {
"dateRangeStart": startDate,
"dateRangeEnd": endDate,
"summaryFilter": {
"groups": [
"USER"
],
"sortColumn": "GROUP"
}
}
var payload = JSON.stringify (newJSON);
var headers = {"X-Api-Key" : myAPIkey, "content-type" : "application/json"};
var url = APIreportsbase + '/workspaces/' + myWorkspaceID + '/reports/summary'
var options = {
"method": "post",
"contentType": "application/json",
"headers": headers,
"payload": payload,
"muteHttpExceptions" : false
};
var response = UrlFetchApp.fetch(url, options)
var json = response.getContentText();
var data = JSON.parse(json);
var people = data.groupOne;
for (let i = 0; i < people.length; i++) {
if (people[i].name == userName) {
if (people[i].duration == 0) {
return 0;
} else {
return people[i].duration/3600;
}
}
}
}
GetHours();
I got the program working by adding filter so that the second time the program ran, it didn't affect the return value.
if (startDate != null) {
var response = UrlFetchApp.fetch(url, options)
var json = response.getContentText();
.....
}

Google Apps Script. JSON to Spreadsheet - Result too long (API to Sheet) Work only with 100 reg

Good morning, I have made a Script that connects with an APi, it returns a JSON, I serialize it and complete an array with it .. then I paste it in a Google Spreadsheet, but it only works with 100 records. However if in the same Script, under the JSON my Google Drive makes it complete.
When I check the Logger it tells me the result is too long ...
My code.
function getOT() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('OT');
var url ='https://app.XXXXX.com/api/work_orders';
var authorization=XXXXXXApi(XXX,'app.XXXXXX.com','/api/work_orders','GET','443');
var Options ={
"url": "https://app.XXXXXX.com/api/work_orders",
"method": "GET",
"timeout": 0,
"headers": { "Authorization": "Hawk id=\""+authorization.cID+"\", ts=\""+ authorization.cTS+"\", nonce=\""+authorization.cNONCE+"\", mac=\""+authorization.cHMAC+"\"",
},
};
var response = UrlFetchApp.fetch('https://app.XXXX.com/api/work_orders', Options);
var array = [];
var CC = response.getContentText();
var datos = JSON.parse(CC);
Logger.log (CC)
for (var i = 0; i < datos.data.length ;i++) {
array.push([datos.data[i]['wo_folio']],[datos.data[i]['description']],[datos.data[i]['personnel_description']],[datos.data[i]['items_log_description']])
};
for (var i = 0; i < datos.data.length ;i++){
var startrow=2 + +i;
sheet.getRange(startrow, 1).setValue(datos.data[i]['wo_folio']);
sheet.getRange(startrow, 2).setValue(datos.data[i]['description']);
sheet.getRange(startrow, 3).setValue(datos.data[i]['personnel_description']);
sheet.getRange(startrow, 4).setValue(datos.data[i]['items_log_description']);
}
DriveApp.createFile('XX.csv', CC); //copio el JSON a mi drive
}
The Logging output too large. Truncating output. message is not an error, it's just a notice. It simply doesn't show the entire data, only a subset. This means that the data is actually there but is not shown to you when using a single call. Try logging the output inside a loop and print all the elements.
As for the TypeError: Cannot read property 'wo_folio' of undefined, it seems that this happens because you are modifying increasing the length property of datos.data:
const array = ['a', 'b']
array.length = 3
console.log(array) // outputs ['a', 'b', empty]
Notice that if I try to get the third element of array 2, you'll get undefined. In a similar way, datos.data[i]['wo_folio'] will become undefined['wo_folio'] if iterated outside the original length, and thus the error is thrown. And just so you know, changing an array length via its length property is rarely used.
I have put the size of the data, and I figure 100
var CC = response.getContentText();
var datos = JSON.parse(CC);
var registros=datos.data;
Logger.log(registros.length);
[21-01-03 00:19:21:398 ART] 100.0 .. but i have too many more...
If I run the query from postman, it has more than 300 records .. it only happens when I query it from GAS

Google Apps Script API iterate/ loop through ID individually

i have an endpoint that i need to go through X number of times (dependent on how many IDs), Each call will need to assign its individual LineItem ID and bring back a JSON response.
I have tried the following code, and it seems I can call the API but can't seem to figure out how to translate the response back to my sheet, so in the case below i may have upto 10 LI ids that will need to be called up individually > results brought back> copied to last row of a particular range and then the next API call with the next LI id, etc...
function ListLI360API_Agetest(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('MySheet');
var adID = 1558211;
var LIs =sheet.getRange(2, 3, sheet.getLastRow(), 1).getValues().filter(String);
var LIArrayLength = LIs.length;
for (var i = 0; i <= LIArrayLength; i++) {
if(LIs[i]!== undefined){
var url = 'https://displayvideo.googleapis.com/v1/advertisers/'+adID+'/lineItems/'+LIs[i]+'/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions'
//Logger.log(url);
var response = callApi5 (url, 'GET');
//Logger.log(response);
var content = response.getContentText();
//Logger.log(content);
var json = JSON.parse(content);
//Logger.log(json);
var ageData = json["assignedTargetingOptions"];
//Logger.log(ageData);
var rows = [],
data;
for (i = 0; i <= ageData.length; i++) {
data = ageData[i];
rows.push([data.name]);
}
//save results to spreadsheet in the next blank column and then API for next LI ID
Logger.log(rows);
}
}//endfor
}
I seem to be getting stuck on reading the results, i have tried with the following added into the script above but i get an error
"TypeError: Cannot read property "name" from undefined", im guessing there are some nulls/ blanks being returned in the JSON and hence it cant read the length
JSON looks like...
[20-06-24 21:34:57:159 BST] {
"assignedTargetingOptions": [
{
"name": "advertisers/1558211/lineItems/36917016/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions/503004",
"assignedTargetingOptionId": "503004",
"targetingType": "TARGETING_TYPE_AGE_RANGE",
"inheritance": "NOT_INHERITED",
"ageRangeDetails": {
"ageRange": "AGE_RANGE_45_54",
"targetingOptionId": "503004"
}
},
{
"name": "advertisers/1558211/lineItems/36917016/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions/503005",
"assignedTargetingOptionId": "503005",
"targetingType": "TARGETING_TYPE_AGE_RANGE",
"inheritance": "NOT_INHERITED",
"ageRangeDetails": {
"ageRange": "AGE_RANGE_55_64",
"targetingOptionId": "503005"
}
},
{
"name": "advertisers/1558211/lineItems/36917016/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions/503006",
"assignedTargetingOptionId": "503006",
"targetingType": "TARGETING_TYPE_AGE_RANGE",
"inheritance": "NOT_INHERITED",
"ageRangeDetails": {
"ageRange": "AGE_RANGE_65_PLUS",
"targetingOptionId": "503006"
}
}
]
}
[20-06-24 21:34:57:694 BST] {
"assignedTargetingOptions": [
{
"name": "advertisers/1558211/lineItems/36917017/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions/503004",
"assignedTargetingOptionId": "503004",
"targetingType": "TARGETING_TYPE_AGE_RANGE",
"inheritance": "NOT_INHERITED",
"ageRangeDetails": {
"ageRange": "AGE_RANGE_45_54",
"targetingOptionId": "503004"
}
},
{
"name": "advertisers/1558211/lineItems/36917017/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions/503005",
"assignedTargetingOptionId": "503005",
"targetingType": "TARGETING_TYPE_AGE_RANGE",
"inheritance": "NOT_INHERITED",
"ageRangeDetails": {
"ageRange": "AGE_RANGE_55_64",
"targetingOptionId": "503005"
}
},
{
"name": "advertisers/1558211/lineItems/36917017/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions/503006",
"assignedTargetingOptionId": "503006",
"targetingType": "TARGETING_TYPE_AGE_RANGE",
"inheritance": "NOT_INHERITED",
"ageRangeDetails": {
"ageRange": "AGE_RANGE_65_PLUS",
"targetingOptionId": "503006"
}
}
]
}
From this Example there are 2 LI Ids so 2 separate outputs, i need to take parts of these outputs and print them into the spreadsheet
API function looks like...
function callApi5(url, methodType, requestBody) {
var service = getService();
if (service.hasAccess()) {
var headers = {
'Content-Type': 'application/json',
'Accept' :'application/json',
'Authorization': 'Bearer ' + getService().getAccessToken()
};
var options = {
method: methodType,
headers : headers,
muteHttpExceptions: true
};
if (requestBody) {
options.payload = requestBody;
}
return UrlFetchApp.fetch(url, options);
} else {
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s',
authorizationUrl);
}
}
function getService() {
// Create a new service with the given name. The name will be used when
// persisting the authorized token, so ensure it is unique within the
// scope of the property store.
return OAuth2.createService('MyService')
// Set the endpoint URLs, which are the same for all Google services.
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
// Set the client ID and secret, from the Google Developers Console.
.setClientId("xxxxx.apps.googleusercontent.com")
.setClientSecret("xxxxxx")
// Set the name of the callback function in the script referenced
// above that should be invoked to complete the OAuth flow.
.setCallbackFunction('authCallback')
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getUserProperties())
// Set the scopes to request (space-separated for Google services).
// this is blogger read only scope for write access is:
.setScope('https://www.googleapis.com/auth/display-video')
// Below are Google-specific OAuth2 parameters.
// Sets the login hint, which will prevent the account chooser screen
// from being shown to users logged in with multiple accounts.
.setParam('login_hint', 'xxxx#xxxs.com')
// Requests offline access.
.setParam('access_type', 'offline')
// Forces the approval prompt every time. This is useful for testing,
// but not desirable in a production application.
.setParam('approval_prompt', 'force');
}
I believe your goal as follows.
You want to retrieve the values from all requests, which used the URLs created by 'https://displayvideo.googleapis.com/v1/advertisers/'+adID+'/lineItems/'+LIs[i]+'/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions', and put them to the Spreadsheet.
For this, how about this answer? From your question, I thought that your script of callApi5() works and json of var json = JSON.parse(content); is the value you showed in your question. So I would like to propose to modify the function of ListLI360API_Agetest.
Modification points:
When the array is used in the for loop, please loop from 0 to array.length - 1. Because the 1st index of array is 0. So, when for (var i = 0; i <= LIArrayLength; i++) is used, an error occurs at the last loop of LIArrayLength. In this case, please modify to for (var i = 0; i < LIArrayLength; i++). Also, this can be said for for (i = 0; i <= ageData.length; i++) {.
In your script, 1 for loop is included in the for loop. And, each loop uses the variable i. In this case, the variables of i of each loop are affected. By this, the loop cannot be correctly worked.
I think that your error of TypeError: Cannot read property "name" from undefined might be due to above 2 points.
LIs of var LIs =sheet.getRange(2, 3, sheet.getLastRow(), 1).getValues().filter(String); is 2 dimensional array. So in this case, I think that LIs[i][0] is suitable instead of LIs[i].
When above points are reflected to your script, it becomes as follows.
Modified script:
Please copy and paste the following script, and set the destination sheet name to the last line of ss.getSheetByName("###").getRange(1, 10, result.length, 1).setValues(result);.
function ListLI360API_Agetest(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('MySheet'); // Modified
var adID = 1558211;
var LIs = sheet.getRange(2, 3, sheet.getLastRow(), 1).getValues().filter(String);
var LIArrayLength = LIs.length;
var result = []; // Added
for (var i = 0; i < LIArrayLength; i++) { // Modified
if (LIs[i][0] !== undefined) { // Modified
var url = 'https://displayvideo.googleapis.com/v1/advertisers/'+adID+'/lineItems/'+LIs[i][0]+'/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions' // Modified
var response = callApi5 (url, 'GET');
var content = response.getContentText();
var json = JSON.parse(content);
var ageData = json["assignedTargetingOptions"];
for (var j = 0; j < ageData.length; j++) { // Modified
var data = ageData[j];
result.push([data.name]); // Modified
}
}
}
// Please set the destination sheet name.
ss.getSheetByName("###").getRange(1, 1, result.length, 1).setValues(result); // Added
}
If data.name is not existing, you don't want to put the values, please modify result.push([data.name]); to if (data.name) result.push([data.name]);.
Note:
In this modified script, it supposes that the structure of JSON object retrieved from each URL is the same. If the structure is different for each URL created by LIs[i][0], it is required to modify the script. Please be careful this.
I couldn't understand the result situation that the values are put to the Spreadsheet from your question. So in this modified script, the values are put to the destination sheet. If this is different from your actual situation, please modify the script.
References:
Array
getValues()
I have tested the answer provided by Tanike and modified the last part to be able to print to the spreadsheet. I have added a few more fields from JSON to test this, and finally added:
dataRange = sheet.getRange(lr+1, 17, result.length,result[0].length).setValues(result);
to print onto the spreadhseet.
function ListLI360API_Agetest(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('MySheet'); // Modified
var adID = 1558211;
var LIs = sheet.getRange(2, 3, sheet.getLastRow(), 1).getValues().filter(String);
var LIArrayLength = LIs.length;
var result = []; // Added
var lr = sheet.getRange('Q1').getDataRegion().getLastRow(); //Added
for (var i = 0; i < LIArrayLength; i++) { // Modified
if (LIs[i][0] !== undefined) { // Modified
var url = 'https://displayvideo.googleapis.com/v1/advertisers/'+adID+'/lineItems/'+LIs[i][0]+'/targetingTypes/TARGETING_TYPE_AGE_RANGE/assignedTargetingOptions' // Modified
var response = callApi5 (url, 'GET');
var content = response.getContentText();
var json = JSON.parse(content);
var ageData = json["assignedTargetingOptions"];
for (var j = 0; j < ageData.length; j++) { // Modified
var data = ageData[j];
result.push([
data.name,
data.assignedTargetingOptionId,
data.ageRangeDetails.ageRange]); // Modified
}
}
}
// Each Set of results is pushed one after another
dataRange = sheet.getRange(lr+1, 17, result.length,result[0].length).setValues(result);//Modified
}

Poloniex APi to Google Sheet CSV via Json

I've got the following script that pulls keys from the Poloniex JSON output, but doesn't put the actual data that corresponds to the keys into the actual sheet...it only puts the keys as titles at the top of the sheet.
I'm new to API's, and GAS, and coding in general, so I'm sure I'm missing something incredibly obvious, I'd really appreciate it if you could point out what.
Thanks in advance
function Bitcoin_fromPolo_toCSV() {
//Link the script with a spreasdsheet using the identifier found in the spreadsheet url
var ss = SpreadsheetApp.openById('1cubxxxxxxxxxxxxjDqM');
var APIPullSheet = ss.getSheetByName("APIPull");
// Clear Columns A,B,C,D
APIPullSheet.getRange('A2:D19999').clearContent();
var url = "https://poloniex.com/public?command=returnChartData&currencyPair=BTC_ETH&start=1502344800&end=9999999999&period=14400";
//Fetch pulls data from URL
var responseAPI = UrlFetchApp.fetch(url);
//Parse that JSON
var parcedData = JSON.parse(responseAPI.getContentText());
//Break that Parsed data into fields
//Define the 'stats' array, and populate it from the parced data pulled
// for loop iterates over each 'key' in 'parcedData' pushing that data to 'stats'
var stats = [];
stats.push(['date','high', 'low', 'open', 'close', 'volume', 'quoteVolume', 'weightedAverage']);
for(var key in parcedData.stats)
{
stats.push(parcedData.stats[key]);
}
statsRange = APIPullSheet.getRange(1, 1, stats.length, 8);
statsRange.setValues(stats);
}
How about the following modification?
Modification points :
JSON data from URL is as follows.
[
{
"date": 1502352000,
"high": 0.0899,
"low": 0.08754124,
"open": 0.08795499,
"close": 0.08988724,
"volume": 1390.47552953,
"quoteVolume": 15727.49124739,
"weightedAverage": 0.08841051
},
.
.
]
parcedData doesn't have stats as a key.
Flow for creating data :
Outer forEach() retrieves an element from parcedData.
Inner forEach() retrieves each key from stats[0], and retrieves data from the element of parcedData using the key.
Retrieved data is imported to temp which is 1 dimensional array.
The temp is imported to stats which is 2 dimensional array. After this, temp is initialized.
The script reflected this is as follows.
Modified script :
function Bitcoin_fromPolo_toCSV() {
var ss = SpreadsheetApp.openById('1cubxxxxxxxxxxxxjDqM');
var APIPullSheet = ss.getSheetByName("APIPull");
APIPullSheet.getRange('A2:D19999').clearContent();
var url = "https://poloniex.com/public?command=returnChartData&currencyPair=BTC_ETH&start=1502344800&end=9999999999&period=14400";
var responseAPI = UrlFetchApp.fetch(url);
var parcedData = JSON.parse(responseAPI.getContentText());
var stats = [];
stats.push(['date','high', 'low', 'open', 'close', 'volume', 'quoteVolume', 'weightedAverage']);
parcedData.forEach(function(e1){
var temp = [];
stats[0].forEach(function(e2){
temp.push(e1[e2])
});
stats.push(temp);
});
statsRange = APIPullSheet.getRange(1, 1, stats.length, 8);
statsRange.setValues(stats);
}
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")