Google Script - 加速一个简单的循环
GoogleScript - Speeding up a simple loop
我刚刚开始涉足 VBA for Google Sheets 并编写了一个脚本,但是,它非常慢,这是由于下面的错误还是有加速的方法起来了吗?
这个脚本的重点是每天有 3 个 work 选项卡和一个主表来保存数据。一旦设置了所有 VLookUp,我将复制并粘贴它们作为值,但到目前为止,循环太慢了,甚至无法考虑使用它。
function autoJ7(){
var masterSheet= SpreadsheetApp.getActive().getSheetByName('New Accounts Q4');
var masterLength = masterSheet.getLastRow();
for(var row = 1; row < masterLength; row++){
var rowPath=masterSheet.getRange(row,8).getValue();
if(rowPath<6) {}
else if(rowPath<13) {
masterSheet.getRange(row,16,1,1).activate().setFormula("=vlookup(A"+row+",\'J+7\'!A:M,13,0)");
Logger.log("Path A");
}
else if(rowPath<20) {
masterSheet.getRange(row,17,1,1).activate().setFormula("=vlookup(A"+row+",\'J+14\'!A:M,13,0)");
Logger.log("Path B");
}
else if(rowPath<42) {
masterSheet.getRange(row,18,1,2).activate().setFormula("=vlookup($A"+row+",\'J+21\'!$A:$M,13,0)");
Logger.log("Path C");
}
};
一些加快速度的方法:
减少对 sheet 的调用:
一种。尽可能在一次调用中从 sheet 获取所有数据(就像这里的情况一样)
b. post 数据或公式到 sheet 在一次调用中。
如果你有很多 if-else 条件,switch-case 可能会更快。在这种情况下,也许不是。但我觉得它更优雅。 :-D
以下是我编写脚本的方式:
function autoJ7() {
var masterSheet= SpreadsheetApp.getActiveSpreadsheet().getSheetByName('New Accounts Q4');
var data = masterSheet.getDataRange().getValues(); // Get all the sheet data in one call
var rowPath, sheetRow; // This avoids defining variables repeatedly inside the loop
var formulas = []; // Array to hold formulas to be posted back to the Sheet
for (var row = 0; row < data.length; row++) {
sheetRow = row + 1; //To adjust for the array being zero-based
rowPath = data[row][7];
switch (rowPath) {
case (rowPath < 6):
formulas.push(["", "", ""]);
break;
case (rowPath < 13):
formulas.push(["=vlookup(A"+sheetRow+",\'J+7\'!A:M,13,0)", "", ""]);
break;
case (rowPath < 20):
formulas.push(["", "=vlookup(A"+sheetRow+",\'J+14\'!A:M,13,0)", ""]);
break;
case (rowPath < 42):
formulas.push(["", "", "=vlookup($A"+sheetRow+",\'J+21\'!$A:$M,13,0)"]);
}
}
masterSheet.getRange(1, 16, formulas.length, 3).setFormulas(formulas); // Post to sheet in one call
}
有时使用直接写入更简单,因为您不想过度编写实际上不属于流程一部分的公式。但是这个函数删除了每个 rowPath 变量的单独读取,也删除了宏中经常使用的 activates()。
function autoJ7() {
var ss=SpreadsheetApp.getActive();
var msh=ss.getSheetByName('New Accoounts Q4');
var mrg=msh.getRange(1,8,msh.getLastRow(),1);
var mvA=mrg.getValues();
mvA.forEach(function(r,i){
var row=i+1;
if(r[0]<13) {
msh.getRange(row,16,1,1).setFormula("=vlookup(A"+row+",\'J+7\'!A:M,13,0)");
Logger.log("Path A");
}else if(r[0]<20){
msh.getRange(row,17,1,1).setFormula("=vlookup(A"+row+",\'J+14\'!A:M,13,0)");
Logger.log("Path B");
}else if(r[0]<42){
msh.getRange(row,18,1,2).setFormula("=vlookup($A"+row+",\'J+21\'!$A:$M,13,0)");
Logger.log("Path C");
}
});
}
我刚刚开始涉足 VBA for Google Sheets 并编写了一个脚本,但是,它非常慢,这是由于下面的错误还是有加速的方法起来了吗?
这个脚本的重点是每天有 3 个 work 选项卡和一个主表来保存数据。一旦设置了所有 VLookUp,我将复制并粘贴它们作为值,但到目前为止,循环太慢了,甚至无法考虑使用它。
function autoJ7(){
var masterSheet= SpreadsheetApp.getActive().getSheetByName('New Accounts Q4');
var masterLength = masterSheet.getLastRow();
for(var row = 1; row < masterLength; row++){
var rowPath=masterSheet.getRange(row,8).getValue();
if(rowPath<6) {}
else if(rowPath<13) {
masterSheet.getRange(row,16,1,1).activate().setFormula("=vlookup(A"+row+",\'J+7\'!A:M,13,0)");
Logger.log("Path A");
}
else if(rowPath<20) {
masterSheet.getRange(row,17,1,1).activate().setFormula("=vlookup(A"+row+",\'J+14\'!A:M,13,0)");
Logger.log("Path B");
}
else if(rowPath<42) {
masterSheet.getRange(row,18,1,2).activate().setFormula("=vlookup($A"+row+",\'J+21\'!$A:$M,13,0)");
Logger.log("Path C");
}
};
一些加快速度的方法:
减少对 sheet 的调用: 一种。尽可能在一次调用中从 sheet 获取所有数据(就像这里的情况一样) b. post 数据或公式到 sheet 在一次调用中。
如果你有很多 if-else 条件,switch-case 可能会更快。在这种情况下,也许不是。但我觉得它更优雅。 :-D
以下是我编写脚本的方式:
function autoJ7() {
var masterSheet= SpreadsheetApp.getActiveSpreadsheet().getSheetByName('New Accounts Q4');
var data = masterSheet.getDataRange().getValues(); // Get all the sheet data in one call
var rowPath, sheetRow; // This avoids defining variables repeatedly inside the loop
var formulas = []; // Array to hold formulas to be posted back to the Sheet
for (var row = 0; row < data.length; row++) {
sheetRow = row + 1; //To adjust for the array being zero-based
rowPath = data[row][7];
switch (rowPath) {
case (rowPath < 6):
formulas.push(["", "", ""]);
break;
case (rowPath < 13):
formulas.push(["=vlookup(A"+sheetRow+",\'J+7\'!A:M,13,0)", "", ""]);
break;
case (rowPath < 20):
formulas.push(["", "=vlookup(A"+sheetRow+",\'J+14\'!A:M,13,0)", ""]);
break;
case (rowPath < 42):
formulas.push(["", "", "=vlookup($A"+sheetRow+",\'J+21\'!$A:$M,13,0)"]);
}
}
masterSheet.getRange(1, 16, formulas.length, 3).setFormulas(formulas); // Post to sheet in one call
}
有时使用直接写入更简单,因为您不想过度编写实际上不属于流程一部分的公式。但是这个函数删除了每个 rowPath 变量的单独读取,也删除了宏中经常使用的 activates()。
function autoJ7() {
var ss=SpreadsheetApp.getActive();
var msh=ss.getSheetByName('New Accoounts Q4');
var mrg=msh.getRange(1,8,msh.getLastRow(),1);
var mvA=mrg.getValues();
mvA.forEach(function(r,i){
var row=i+1;
if(r[0]<13) {
msh.getRange(row,16,1,1).setFormula("=vlookup(A"+row+",\'J+7\'!A:M,13,0)");
Logger.log("Path A");
}else if(r[0]<20){
msh.getRange(row,17,1,1).setFormula("=vlookup(A"+row+",\'J+14\'!A:M,13,0)");
Logger.log("Path B");
}else if(r[0]<42){
msh.getRange(row,18,1,2).setFormula("=vlookup($A"+row+",\'J+21\'!$A:$M,13,0)");
Logger.log("Path C");
}
});
}