Reputation: 89
I've created a for loop that pulls sales data in columns from an array (salesLog) and places them into a sheet (targetSheet). The sales data is kept in multiple columns. The columns between columnStart and columnEnd are added (unit), matched with the correct row in the source sheet, and placed in the correct row in the targetSheet. This loop works fine except it's too slow, and a fear unscalable with more data. I'm looking for a way to run this loop faster. Any help?
var length = POlistTarget.length;
for (var i=0; i <= length; i++){
//find Row
var row = POlistSource.indexOf(POlistTarget[i]);
//findColumns
var columnStart = periodArr[0]+1
var columnEnd = periodArr.length
var unitArr =
salesLog.getRange(row+3,columnStart,1,columnEnd).getValues().flat().filter(row=>row!="");
//add units in an array
var unit = unitArr.reduce(function(a,b){return a+b;},0);
//execute
targetSheet.getRange(i+4,7,1,1).setValue(unit);
}
Upvotes: 1
Views: 952
Reputation: 27350
As also Tanaike mentioned in his comment, the main improvement is to use setValues
once outside of the for loop instead of using setValue
inside the for loop iteratively. In this way you will make one call to set the data instead of POlistTarget.length
calls. See more details in best practices.
Another improvement both in terms of performance but also code formatting is to use forEach
instead of for loop. The idea is to get rid of unnecessary code.
const units = [];
POlistTarget.forEach((pt,i)=>{
let row = POlistSource.indexOf(pt);
let columnStart = periodArr[0]+1;
let columnEnd = periodArr.length;
let unit = salesLog.getRange(row+3,columnStart,1,columnEnd).
getValues().
flat().
filter(r=>r!='').
reduce((a,b)=>a+b);
units.push([unit]);
});
targetSheet.getRange(4,7,units.length,1).setValues(units);
More improvements:
If your code was complete, we could see whether it could be feasible to use getRange
for the full array on salesLog
so you can get rid of getRange
inside the for loop. In this way, you could skip the for loop altogether.
Upvotes: 1