我在编码方面有点新手,尤其是Javascript / Google脚本语言。我已经创建了下面的代码,但它确实有效,但是现在我已经有了一个可用的代码,我想知道如何优化它。在我看来,所有getValue()调用都是主要的性能影响,而且我从未真正擅长优化循环。任何人都知道更好的方法来实现与此代码相同的方法吗?
它的作用:检查我的一个文件夹中的每个电子表格,看它是否需要运行其余的脚本。如果为true,则打开该表并计算具有数据的行数,使用该行来限制它在循环中检查的行数。然后,它会查找标记为推送的任何行,并将其复制到我的驱动器中的另一个电子表格。然后它继续到文件夹中的下一个文件并执行相同的操作。
这是我的代码:
function myVupdate() {
try {
var folder = DriveApp.getFolderById("123abc"),
files = folder.getFiles();
while (files.hasNext()) {
var file = files.next(),
sss = SpreadsheetApp.open(file);
SpreadsheetApp.setActiveSpreadsheet(sss);
//Work orders update
var ss = sss.getSheetByName("Sheet2"),
refresh = ss.getRange("W3").getValue();
if (refresh == 0) {continue};
var avals = ss.getRange("D5:D").getValues(),
count = avals.filter(String).length,
rows = count + 5
var val = ss.getDataRange().getValues();
for (var row=5; row < rows; row++) {
var cell = ss.getDataRange().getCell(row, 23).getValue();
if (cell == 0) {
var cells = [["v" + "WO-" + val[row-1][3] + "_" + val[row-1][2],val[row-1][13],val[row-1][14],val[row-1][15],new Date()]];
var tss = SpreadsheetApp.openById("target_spreadsheet"),
ts = tss.getSheetByName("Sheet5");
ts.insertRowBefore(2);
var last_hmy = ts.getRange(3,1).getValue();
ts.getRange(2,1).setValue(last_hmy+1);
ts.getRange(2,2,cells.length,cells[0].length).setValues(cells);
ts.getRange(2,7).setValue(sss.getName());
ss.getRange(row,17).setValue(last_hmy+1);
ss.getRange(row,18,cells.length,cells[0].length).setValues(cells);
//Turnover update
var ss = sss.getSheetByName("Sheet1"),
avals = ss.getRange("D5:D").getValues(),
count = avals.filter(String).length,
rows = count + 5
var val = ss.getDataRange().getValues();
}
}
for (var row=5; row < rows; row++) {
var cell = ss.getDataRange().getCell(row, 24).getValue();
if (cell == 0) {
var cells = [["v" + val[row-1][3] + "_" + val[row-1][2],val[row-1][12],val[row-1][15],val[row-1][16],new Date()]];
var tss = SpreadsheetApp.openById("target_spreadsheet"),
ts = tss.getSheetByName("Sheet5");
ts.insertRowBefore(2);
var last_hmy = ts.getRange(3,1).getValue();
ts.getRange(2,1).setValue(last_hmy+1);
ts.getRange(2,2,cells.length,cells[0].length).setValues(cells);
ts.getRange(2,7).setValue(sss.getName());
ss.getRange(row,18).setValue(last_hmy+1);
ss.getRange(row,19,cells.length,cells[0].length).setValues(cells);
}
}
}
}
catch(e) {
// Browser.msgBox("An error occured. A log has been sent for review.");
var errorSheet = SpreadsheetApp.openById ("target_sheet").getSheetByName("Error Log"),
source = sss.getName();
lastRow = errorSheet.getLastRow();
var cell = errorSheet.getRange('A1');
cell.offset(lastRow, 0).setValue(e.message);
cell.offset(lastRow, 1).setValue(e.fileName);
cell.offset(lastRow, 2).setValue(e.lineNumber);
cell.offset(lastRow, 3).setValue(source);
cell.offset(lastRow, 4).setValue(new Date());
MailApp.sendEmail("my@email.com", "Error report - " + new Date(),
"\r\nSource: " + source + "\r\n"
+ "\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName
+ "\r\nLine: " + e.lineNumber
);
}
}
答案 0 :(得分:2)
您好,欢迎来到Stack Overflow,
首先,你是对的。您执行的getValue()
或setValue()
次呼叫越多,性能越差,请阅读有关最佳做法的更多信息here。 Google建议您尽可能批量处理这些内容。立即引起注意的一件事是:
var val = ss.getDataRange().getValues();
所以现在您在二维数组中拥有工作表上的所有值。这意味着在下面的位
var ss = sss.getSheetByName("Sheet2"),
refresh = ss.getRange("W3").getValue();
if (refresh == 0) {continue};
var avals = ss.getRange("D5:D").getValues(),
count = avals.filter(String).length,
rows = count + 5
var val = ss.getDataRange().getValues();
for (var row=5; row < rows; row++) {
var cell = ss.getDataRange().getCell(row, 23).getValue();
不再需要每个getValue()
或getValues()
。相反,您知道refresh = val[2][22]
,因为您需要第3行和第23列,因为您已经拥有包含该表中数据的整个范围。
与avals
相同,因为D5:D
范围内的所有值都在vals[n][3]
,其中n
从4
开始。 请记住,数组索引从0开始(因此第一行和第一列为vals[0][0]
。
因此,无论您尝试使用getValues()
电子表格中的ss
,您都已拥有该数据。您还可以做的是操纵您拥有的数组,因此您始终只更改该数组中的值。完成后,使用ss.getDataRange().setValues(vals)
将整个阵列推回到相同的范围(您可以将范围存储在datRange = ss.getDataRange()
之类的变量中,然后执行datRange.setValues(vals)
。< / p>
您只需要为任何其他工作表使用单独的数据数组。我没有详细介绍其余的代码,因为相同的想法贯穿始终。由于您已使用getValues()
获取所有内容,因此不再有任何理由对该范围内的任何单元格使用getValue()
。