Is there anyway to speed up this batch update code using google script? - api

I am currently attempting to update 1600-2000 rows of data in google sheets. I am parsing data from an API Fetch but it keeps timing out because the update is taking way too long. I don't really know how to post reusable code without giving out the API which I can't do. Does anyone know how I can speed up this process?
function logDataInEveryCell3() {
const ss = SpreadsheetApp.getActive();
const vs = ss.getRange("A2:A1669").getValues().flat();
const osh = ss.getSheetByName("Sheet1");
let row = 2;
vs.forEach(e => {
let res = UrlFetchApp.fetch("https://api” + e +token");
let obj = JSON.parse(res.getContentText());
let items = obj["dispatches"]["items"];
let vo = items.map(itm => [itm.vehicle.driver.contact.name])
vo2 = vo.slice(-1);//good idea
osh.getRange(row,3).setValues(vo2);
row += vo2.length;
});
}

Try something like this:
function logDataInEveryCell() {
const ss = SpreadsheetApp.getActive();
const vs = ss.getRange("A2:A51").getValues().flat();
const osh = ss.getSheetByName("Sheet1");
osh.clearContents();
let l = 1;
let a = [];
vs.forEach(e => {
let res = UrlFetchApp.fetch("API" + e + "Token");
let obj = JSON.parse(res.getContentText());
let items = obj["dispatches"]["items"];
let vo = items.map(itm => [itm.vehicle.driver.contact.name])
a.push(vo.slice(-1));
});
a.flat(1);
osh.getRange(l,1,a.length,a[0].length).setValues(a);
}
Reference:
Use batch operations

Related

how to add conditional where parameters to sql query in node js

I have the below method that aims to filter records from a table. But sometimes, the user might only select one filter or two. I want to add where conditions only for parameters that the user sends. At the moment, it filters with all conditions. One possibility I know is to use some conditions to concatenate the string if true but I do not think this is the best way.
Any better way of doing this?
// Retrieve hotels by filter
app.get('/filter', (request, response) => {
var name = request.query.name;
var country = request.query.country;
var freeWifi = request.query.freeWifi;
var freeParking = request.query.freeParking;
var restaurant = request.query.restaurant;
var pool = request.query.pool;
var gym = request.query.gym;
var airconditioning = request.query.airconditioning;
let query = `select * from hotels h inner join hotelFilters hf on h.id = hf.hotelId where h.title like "%${isNullOrUndefined(name) ? '' : name}%"
and hf.freeWifi = ${freeWifi} and hf.freeParking = ${freeParking} and hf.restaurant = ${restaurant} and hf.outdoorPool = ${pool}
and hf.airConditioning = ${airconditioning}
and hf.gym = ${gym}`;
connection.query(query, (error, result) => {
if (error) {
console.log(error, 'Error occurred with hotels/filter API...');
}
if (result.length > 0) {
response.send({
result
})
}
})
});

SheetJS Change Header names to dynamic

I am trying to change the header names in sheetJS to something I recieve from the form. Here is my form submit function:
onFormSubmit() {
const fileReader = new FileReader();
const solution = 'testsolution'; // normally i get this from a form input
fileReader.onload = (e) => {
this.arrayBuffer = fileReader.result;
const data = new Uint8Array(this.arrayBuffer);
const arr = [];
for (let i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
const bstr = arr.join('');
const workbook = XLSX.read(bstr, {type: 'binary'});
const first_sheet_name = workbook.SheetNames[0];
const worksheet = workbook.Sheets[first_sheet_name];
// change the column names to match entity
const records = XLSX.utils.sheet_to_json(worksheet, {raw: true});
console.log('records - ', records);
};
fileReader.readAsArrayBuffer(this.file);
}
currently for example my headers come in like this:
AltId, FirstName, LastName
And I want them to end up like this with 'testsolution' apended with underscore and lowercase
testsolution_altid, testsolution_firstname, testsolution_lastname
NOTE: Header names may change depending on what sheet is uploaded. For example the next sheet uploaded may contain headers:
AltId, Address1, Address2, City, State
And should end up like
testsolution_altid, testsolution_address1, testsolution_address2, testsolution_city, testsolution_state
Any help would be appriciated!
I ended up doing it like this if it helps anyone else:
// change the column names to match entity
const newHeaders = [];
const columnCount = XLSX.utils.decode_range(ws['!ref']).e.c +1;
console.log(columnCount);
for (let i = 0; i < columnCount; ++i) {
newHeaders[i] = solution+'_'+ ws[`${XLSX.utils.encode_col(i)}1`].v.toLowerCase();
// console.log(header[i]);
}
// console.log(newHeaders);

Making a value dynamic in Spark AR via Script

Coming from this Question Tweening Colors on Spark AR via Script i now try to make start and end color dynamically bounded. I propably havn't swallowed the whole concept of reactive programming yet, but i tried to make a factory so the value is a function... yet its not working, or only with the initial values. Using the set function and restarting animation doesnt change a thing. What am i missing? Thank you and best regards!
const pink = [.99, .682, .721, 1];
const blue = [.0094, .0092, .501, 1];
const yellow = [0.9372, .7725, 0, 1];
function ColorFactory() {
this.sourceCol = pink;
this.targetCol = blue;
this.set = function (_col1, _col2) {
this.sourceCol = _col1;
this.targetCol = _col2;
}
this.get = function (id) {
switch (id) {
case 'source': return this.sourceCol;
default: return this.targetCol;
}
}
}
var colfac = new ColorFactory();
const timeDriver = Animation.timeDriver(timeDriverParameters);
const rotSampler = Animation.samplers.easeInQuad(0, 35);
const alphaSampler = Animation.samplers.linear(1, 0);
const colSampler = Animation.samplers.linear(colfac.get('source'), colfac.get('target'));
const colorAnimation = Animation.animate(timeDriver, colSampler);
timedriver.start();
//doesnt make change anything, same colors as before:
colfac.set(blue, yellow);
timedriver.reset();
timedriver.start();
So how could i make the set of colors dynamic? Anyone?
The only "good" option for you is to do something like this:
const colors = [];
const driver = A.timeDriver({ durationMilliseconds : 1000 });
// On NativeUI monitor selected index event
ui.selectedIndex.monitor.subscribe(
(val) => {
const sampler = A.samplers.linear(colors[val.oldValue, colors[val.newValue]);
const colorAnimation = A.animate(driver, sampler);
// bind here to shader
})

arcGIS javascript no lat long after doing Feature Layer query

I have done a query on my feature layer and got a result. the only problem is that the resulting object doesn't contain a LAT and LNG attribute. Here is the problem:
centerAndZoomOnAsset(assetId: string) {
let query = this.pipeFL.createQuery();
query.where = `AssetId = '${assetId}'`;
query.outFields = ['*'];
this.pipeFL.queryFeatures(query).then((result: esri.FeatureSet) => {
debugger;
const foundFeatureGraphic: esri.Graphic = result.features[0];
if (foundFeatureGraphic) {
const center = foundFeatureGraphic.geometry.extent.center.clone();
At this point I have a value for center, and it has it's x,y coords, however, I do not have: center.latitude or center.longitude...
I don't see why it will not have it. When I do a hit test on a click, it contains both lat and lng, but when i query from outside of the hit test, it doesn't contain my lat and lng.
Any ideas as to why this is happening?
You need to set the returnGeometry parameter to true in order to get spatial data from the query. See the API here
Try using this:
centerAndZoomOnAsset(assetId: string) {
let query = this.pipeFL.createQuery();
query.where = `AssetId = '${assetId}'`;
query.returnGeometry = true;
query.outFields = ['*'];
this.pipeFL.queryFeatures(query).then((result: esri.FeatureSet) => {
debugger;
const foundFeatureGraphic: esri.Graphic = result.features[0];
if (foundFeatureGraphic) {
const center = foundFeatureGraphic.geometry.extent.center.clone();

How to send the index of a for loop into the promise of a function in a Vue Resource call?

I am looping through an object however in the asynchronous part the i variable is always five.
How can I maintain that value, or pass it into the function
getProductData: function() {
var vm = this;
for (var i = 0; i < vm.recommendationResponse['recommendedItems'].length; i++) {
var sku = vm.recommendationResponse['recommendedItems'][i]['items'][0]['id'];
vm.$http.get('http://127.0.0.1:8000/models/api/productimage/' + sku).then(response => {
// get body data
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = response.body['product_image_url'];
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = response.body['price'];
}, response => {
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = '';
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = '';
});
}
}
I I do something like this:
vm.$http.get('http://127.0.0.1:8000/models/api/productimage/' + sku).then((response, i) => ...
then i is undefined
Who do I keep the index of the loop or should I go about it a different way?
Always use let to initialize variables in for loop when dealing with async operations. Similar things goes to having for loops in intervals. By using let you make sure you always have a unique variable assigned to i.
for (let i = 0, recommendationlength = vm.recommendationResponse['recommendedItems'].length; i < recommendationlength; i++)
Little bonus, if you cache array length in the beginning you get a small performance boost :-)
You could use Array.prototype.forEach instead:
var vm = this;
vm.recommendataionResponse['recommendedItems'].forEach((item, i) => {
var sku = vm.recommendationResponse['recommendedItems'][i]['items'][0]['id'];
vm.$http.get('http://127.0.0.1:8000/models/api/productimage/' + sku).then(response => {
// get body data
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = response.body['product_image_url'];
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = response.body['price'];
}, response => {
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = '';
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = '';
});
})
This way, since there is a unique scope for each i value, each .then callback will be able to reference the correct value.