Mon*_*yDo 1 javascript optimization multidimensional-array google-sheets google-apps-script
我刚刚编写了第一个从VBA移植的Google Apps脚本,该脚本可格式化一列客户订单信息(感谢您的全力指导)。
描述:
该代码使用-前缀标识状态代码,然后将以下名字和姓氏(如果存在)组合在一起。然后,它会写上“姓氏已完成”的位置。最后,如果订单之间没有间隙,它将插入一个必要的空白单元格(请参见下图)。
问题:
问题是处理时间。它不能处理更长的数据列。我被警告
脚本大量使用方法Range.getValue。
现有优化:
根据对这个问题的回答,我尝试将尽可能多的变量保留在循环之外,并且还改进了if语句。@MuhammadGelbana建议只调用一次Range.getValue方法并移动其值...但是我不知道这将如何/将如何工作。
码:
function format() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var lastRow = s.getRange("A:A").getLastRow();
var row, range1, cellValue, dash, offset1, offset2, offset3;
//loop through all cells in column A
for (row = 0; row < lastRow; row++) {
range1 = s.getRange(row + 1, 1);
//if cell substring is number, skip it
//because substring cannot process numbers
cellValue = range1.getValue();
if (typeof cellValue === 'number') {continue;};
dash = cellValue.substring(0, 1);
offset1 = range1.offset(1, 0).getValue();
offset2 = range1.offset(2, 0).getValue();
offset3 = range1.offset(3, 0).getValue();
//if -, then merge offset cells 1 and 2
//and enter "Order complete" in offset cell 2.
if (dash === "-") {
range1.offset(1, 0).setValue(offset1 + " " + offset2);
//Translate
range1.offset(2, 0).setValue("Order complete");
};
//The real slow part...
//if - and offset 3 is not blank, then INSERT CELL
if (dash === "-" && offset3) {
//select from three rows down to last
//move selection one more row down (down 4 rows total)
s.getRange(row + 1, 1, lastRow).offset(3, 0).moveTo(range1.offset(4, 0));
};
};
}
Run Code Online (Sandbox Code Playgroud)
格式更新:
有关使用字体或背景色格式化输出的指导,请在此处检查此后续问题。希望您能从这些专业人士给我的建议中受益:)
使用.getValue()
和这样的方法.moveTo()
在执行时间上可能会非常昂贵。一种替代方法是使用批处理操作,在该操作中,您可以获取所有列值,并在一次调用中写入工作表之前根据需要遍历数据重塑。运行脚本时,您可能已经注意到以下警告:
该脚本使用一种被认为很昂贵的方法。每次调用都会生成对远程服务器的耗时调用。这可能会对脚本的执行时间(尤其是大数据)产生严重影响。如果脚本性能不佳,则应考虑使用其他方法,例如Range.getValues()。
使用.getValues()和.setValues()可以将脚本重写为:
function format() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var lastRow = s.getLastRow(); // more efficient way to get last row
var row;
var data = s.getRange("A:A").getValues(); // gets a [][] of all values in the column
var output = []; // we are going to build a [][] to output result
//loop through all cells in column A
for (row = 0; row < lastRow; row++) {
var cellValue = data[row][0];
var dash = false;
if (typeof cellValue === 'string') {
dash = cellValue.substring(0, 1);
} else { // if a number copy to our output array
output.push([cellValue]);
}
// if a dash
if (dash === "-") {
var name = (data[(row+1)][0]+" "+data[(row+2)][0]).trim(); // build name
output.push([cellValue]); // add row -state
output.push([name]); // add row name
output.push(["Order complete"]); // row order complete
output.push([""]); // add blank row
row++; // jump an extra row to speed things up
}
}
s.clear(); // clear all existing data on sheet
// if you need other data in sheet then could
// s.deleteColumn(1);
// s.insertColumns(1);
// set the values we've made in our output [][] array
s.getRange(1, 1, output.length).setValues(output);
}
Run Code Online (Sandbox Code Playgroud)
用20行数据测试脚本,发现执行了4.415秒,以上代码在0.019秒内完成
.getValue()
和 会.setValue()
导致处理时间增加。尽量减少对服务的调用:
您可以在 Google Apps Script 本身中完成的任何事情都比调用需要从 Google 的服务器或外部服务器获取数据的调用快得多,例如对电子表格、文档、站点、翻译、UrlFetch 等的请求。
提前缓存:
Google Apps Script 已经有一些内置优化,例如使用前瞻缓存来检索脚本可能获得的内容,并编写缓存来保存可能设置的内容。
您可以编写脚本以最大限度地利用内置缓存,通过最大限度地减少读取和写入次数。
交替读写命令很慢
为了加速脚本,用一个命令将所有数据读入一个数组,对数组中的数据执行任何操作,然后用一个命令将数据写出。
/**
* Really Slow script example
* Get values from A1:D2
* Set values to A3:D4
*/
function slowScriptLikeVBA(){
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
//get A1:D2 and set it 2 rows down
for(var row = 1; row <= 2; row++){
for(var col = 1; col <= 4; col++){
var sourceCellRange = sh.getRange(row, col, 1, 1);
var targetCellRange = sh.getRange(row + 2, col, 1, 1);
var sourceCellValue = sourceCellRange.getValue();//1 read call per loop
targetCellRange.setValue(sourceCellValue);//1 write call per loop
}
}
}
Run Code Online (Sandbox Code Playgroud)
/**
* Fast script example
* Get values from A1:D2
* Set values to A3:D4
*/
function fastScript(){
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
//get A1:D2 and set it 2 rows down
var sourceRange = sh.getRange("A1:D2");
var targetRange = sh.getRange("A3:D4");
var sourceValues = sourceRange.getValues();//1 read call in total
//modify `sourceValues` if needed
//sourceValues looks like this two dimensional array:
//[//outer array containing rows array
// ["A1","B1","C1",D1], //row1(inner) array containing column element values
// ["A2","B2","C2",D2],
//]
targetRange.setValues(sourceValues);//1 write call in total
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2851 次 |
最近记录: |