时间戳onEdit运行缓慢 - 如何优化?

时间:2018-02-24 17:55:20

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

我根据来自this帖子的大量Google搜索和灵感创建了以下代码。我是编码的新手,所以你必须原谅我的无知,因为我确信我的一些方法有点简陋。我希望你们能提供一些关于如何改进现有代码和/或实现我在下面列出的修改的技巧。

我的代码的目的是在修改某些工作表中的某些单元格时生成时间戳。

第1页:视频

触发时间戳的单元格:第1,2,3,4,5,22,23,24列,其中Row> 10

接收时间戳的单元格:如果为空白则为Y列,否则为Z列

表2:类别

触发时间戳的单元格:第13,16,17列,其中Row> 3

接收时间戳的单元格:如果为空白则为列T,否则为列U

我的代码

/*----------------------------Timestamps for Videos----------------------------*/

function onEditVideoTimestamps() {

//check to make sure on the right sheet
var s = SpreadsheetApp.getActiveSheet()
if (s.getName() == "Videos") {

//check to make sure edited row and column is within range
var cell = s.getActiveCell();
var rownbr = cell.getRow();
var colnbr = cell.getColumn();
var nbrcolumns = s.getMaxColumns();
var r = s.getRange(rownbr, 1, 1, nbrcolumns);
var rowArray = r.getValues();//now all your data for that row is in a two Dimensional array [[1,2,3,4,'My Data','etc']]  
if (rownbr > 10 && (colnbr == 1 || colnbr == 2 || colnbr == 3 || colnbr == 4 || colnbr == 5 || colnbr == 22 || colnbr == 23 || colnbr == 24)) {

  //is Y empty?
  var checkY = s.getRange('Y' + rownbr.toString()).getValue()
  if(checkY == '') {

    //Yes
    var time;
    time = new Date();
    time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
    //the column letter is where the timestamp will appear
    SpreadsheetApp.getActiveSheet().getRange('Y' + rownbr.toString()).setValue(time);

    } else {

    //No
    var time;
    time = new Date();
    time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
    //the column letter is where the timestamp will appear
    SpreadsheetApp.getActiveSheet().getRange('Z' + rownbr.toString()).setValue(time);
  }
}

/*----------------------------Timestamps for Categories/Albums----------------------------*/    
} else {

//check to make sure on the right sheet
var s = SpreadsheetApp.getActiveSheet()
if (s.getName() == "Categories") {

//check to make sure edited row and column is within range
var cell = s.getActiveCell();
var rownbr = cell.getRow();
var colnbr = cell.getColumn();
var nbrcolumns = s.getMaxColumns();
var r = s.getRange(rownbr, 1, 1, nbrcolumns);
var rowArray = r.getValues();//now all your data for that row is in a two Dimensional array [[1,2,3,4,'My Data','etc']]  
if (rownbr > 3 && (colnbr == 13 || colnbr == 16 || colnbr == 17)) {

  //is T empty?
  var checkT = s.getRange('T' + rownbr.toString()).getValue()
  if(checkT == '') {

    //Yes
    var time;
    time = new Date();
    time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
    //the column letter is where the timestamp will appear
    SpreadsheetApp.getActiveSheet().getRange('T' + rownbr.toString()).setValue(time);

    } else {

    //No
    var time;
    time = new Date();
    time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
    //the column letter is where the timestamp will appear
    SpreadsheetApp.getActiveSheet().getRange('U' + rownbr.toString()).setValue(time);
    }
   }
  }
 }
}

问题

  1. 此代码运行时间可能超过40秒。理想情况下,它不会超过10,如果可能的话甚至更少,因为它是在编辑时触发的。就目前而言,我很快就超过了我每日的GAS限制。

  2. 我想在我的脚本中添加以下逻辑:

    • 如果第1列更改为“已批准”,则即使已填充Y,也会在初始时间戳列(Y)中生成新的时间戳。第1列是一个状态字段,可以随时更改为“已批准”,“待定”,“已删除”或“已拒绝”。如果它被更改为“已批准”,我希望Y获取时间戳,而不管其内容如何。否则,我当前的逻辑适用:如果填充了Y,则时间戳以Z(最后修改时间戳)为单位。

    分类

    我真的只想对此工作表进行相同的更改,只需要不同的单元格引用。

    • 如果第13列更改为“已批准”,则无论是否已填充,都会在列T中生成新的时间戳。如果在该范围内进行了任何其他更改,并且已填充T,则时间戳将放置在U中。

    就像我说的,我是一个非常初学者,所以任何帮助都会受到赞赏。如果我需要澄清任何事情,请告诉我。感谢

1 个答案:

答案 0 :(得分:1)

您的代码中存在大量冗余。例如,在每个布尔测试中,您初始化time变量。您应该一次,然后在适当的情况下使用时间戳。

您可以实现的另一个即时更改是使用onEdit事件对象。这包含一个Range参数,您可以使用该参数查找活动的行和列,而无需对电子表格进行如此多的调用,这样可以加快脚本速度。

这是针对您当前需求的优化脚本。在测试中,它每次运行不到一秒钟。我还没有添加额外的功能。你只需要几个布尔测试,所以你应该能够做到这一点。

function onEdit(e) {

  var time = Utilities.formatDate(new Date(), "GMT-05:00", "MM/dd/yyyy HH:mm:ss");

  var vidColNbr = [1,2,3,4,5,22,23,24];
  var catColNbr = [13,16,17]

  var sheet = e.range.getSheet();

  //check to make sure on the right sheet
  if (sheet.getName() == "Videos") {
    //check to make sure edited row and column is within range
    if((e.range.getRow() >= 10) && (vidColNbr.indexOf(e.range.getColumn()) > -1)) {

      //is Y empty?
      var checkY = sheet.getRange('Y' + e.range.getRow()).getValue();
      if(checkY == '') {
        //Yes
        SpreadsheetApp.getActiveSheet().getRange('Y' + e.range.getRow()).setValue(time);
      } else {
        //No
        SpreadsheetApp.getActiveSheet().getRange('Z' + e.range.getRow()).setValue(time);
      }
    }

  /*----------------------------Timestamps for Categories/Albums----------------------------*/    
  } else {

    //check to make sure on the right sheet
    if (sheet.getName() == "Categories") {

    //check to make sure edited row and column is within range
      if ((e.range.getRow() >= 3) && (catColNbr.indexOf(e.range.getColumn()) > -1)) {

        //is T empty?
        var checkT = sheet.getRange('T' + e.range.getRow()).getValue()
          if(checkT == '') {
            SpreadsheetApp.getActiveSheet().getRange('T' + e.range.getRow()).setValue(time);
          } else {
            SpreadsheetApp.getActiveSheet().getRange('U' + e.range.getRow()).setValue(time);
        }
      }
    }
  }
}

The event Object reference非常有帮助。您可以通过onEdit事件访问大多数方法和类,这可以真正加快执行速度。