优化代码 - getValue()和循环

时间:2017-03-14 01:31:02

标签: javascript google-apps-script google-sheets

我在编码方面有点新手,尤其是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
      );
  }
}

1 个答案:

答案 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],其中n4开始。 请记住,数组索引从0开始(因此第一行和第一列为vals[0][0]

因此,无论您尝试使用getValues()电子表格中的ss,您都已拥有该数据。您还可以做的是操纵您拥有的数组,因此您始终只更改该数组中的值。完成后,使用ss.getDataRange().setValues(vals)将整个阵列推回到相同的范围(您可以将范围存储在datRange = ss.getDataRange()之类的变量中,然后执行datRange.setValues(vals)。< / p>

您只需要为任何其他工作表使用单独的数据数组。我没有详细介绍其余的代码,因为相同的想法贯穿始终。由于您已使用getValues()获取所有内容,因此不再有任何理由对该范围内的任何单元格使用getValue()