I am trying to use Script editor(Apps script) to stream BigQuery results into google sheets. I'm following these [document][1] .
The issue I have, the data doesn't load fully, it hangs. I have a large number of rows(more than 12 rows). I think I need to optimise the "Append the results" section with some sort of batch update. Now it's a loop which i'm guessing is not very efficient. I cannot figure it out. I tried to use ".next()" but get an error, function didn't exist. I use these [document][2].
How can I optimise the append results section? Heres the whole code(later i've included just the part im looking to modify):
var ui = SpreadsheetApp.getUi();
ui.createMenu("Update")
.addItem('Update','update')
.addToUi();
}
function update() {
run1("\"Filter1\"","\"FilterA\"","Sheet1);
run1("\"Filter2\"","\"FilterB\"","Sheet2");
};
function run1(filter1,filter2,output) {
var projectId = 'xxx';
var request = {
useLegacySql: false,
useQueryCache: false,
query: 'select * from table ' +
'where a1.col1 = ' + filter1 + ' and a1.col2 in ( ' + filter2 + ' ); '
};
var queryResults = BigQuery.Jobs.query(request, projectId);
var jobId = queryResults.jobReference.jobId;
// Check on status of the Query Job.
var sleepTimeMs = 500;
while (!queryResults.jobComplete) {
Utilities.sleep(sleepTimeMs);
sleepTimeMs *= 2;
queryResults = BigQuery.Jobs.getQueryResults(projectId,jobId);
}
// Get all the rows of results.
var rows = queryResults.rows;
while (queryResults.pageToken) {
queryResults = BigQuery.Jobs.getQueryResults(projectId,jobId, {
pageToken: queryResults.pageToken
});
rows = rows.concat(queryResults.rows);
}
if (rows) {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName(output);
sheet.clearContents();
// Append the headers.
var headers = queryResults.schema.fields.map(function(field) {
return field.name;
});
sheet.appendRow(headers);
spreadsheet.getSheetByName(output).getRange("C1").setValue("Modified_col_name");
// Append the results.
var data = new Array(rows.length);
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
sheet.getRange(2, 1, rows.length, headers.length).setValues(data);
Logger.log("Results spreadsheet created: %s",
spreadsheet.getUrl());
} else {
Logger.log("No rows returned.");
}
};
Specifically this part of the code:
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
I believe your goal is as follows.
In this case, how about the following modification?
Before you use this script, please enable Sheets API at Advanced Google services.
if (rows) {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName(output);
sheet.clearContents();
// Append the headers.
var headers = queryResults.schema.fields.map(function(field) {
return field.name;
});
sheet.appendRow(headers);
spreadsheet.getSheetByName(output).getRange("C1").setValue("Modified_col_name");
// Append the results.
var data = new Array(rows.length);
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
sheet.getRange(2, 1, rows.length, headers.length).setValues(data);
Logger.log("Results spreadsheet created: %s",
spreadsheet.getUrl());
} else {
Logger.log("No rows returned.");
}
if (rows) {
var headers = queryResults.schema.fields.map(function (field) {
return field.name;
});
var data = [headers, ...rows.map(({ f }) => f.map(({ v }) => v || ""))];
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName(output);
sheet.clearContents();
SpreadsheetApp.flush();
Sheets.Spreadsheets.Values.update({ values: data }, spreadsheet.getId(), output, { valueInputOption: "USER_ENTERED" });
// spreadsheet.getSheetByName(output).getRange("C1").setValue("Modified_col_name"); // I'm not sure about this line.
Logger.log("Results spreadsheet created: %s", spreadsheet.getUrl());
} else {
Logger.log("No rows returned.");
}