【问题标题】:Timestamps onEdit running slow - how to optimize?时间戳 onEdit 运行缓慢 - 如何优化?
【发布时间】:2018-02-24 17:55:19
【问题描述】:

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

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

表 1:视频

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

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

表 2:类别

触发时间戳的单元格:第 13、16、17 列,其中行 > 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 个,如果可能的话甚至更少,因为它是由 onEdit 触发的。就目前而言,我很快就超过了我的每日 GAS 限制。

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

视频

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

类别

我真的只想对这张表进行相同的更改,只是不同的单元格引用。

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

就像我说的那样,我是一个初学者,因此非常感谢任何帮助。如果我需要澄清任何事情,请告诉我。谢谢

【问题讨论】:

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


    【解决方案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 事件访问大多数方法和类,这确实可以加快执行速度。

    【讨论】:

    • 帮助很大。谢谢!它仍然运行有点慢,但我猜这是由于一个非常繁重的公式电子表格。有很多数组和条件公式正在计算。我将如何使用事件对象
    • 对不起,没有意识到点击返回会发表我的评论。我的问题:如何使用事件对象来识别特定单元格的值?我假设我可以定义“var newValue = e.Value”来从活动/编辑单元格中获取新值?但是,当活动单元格位于例如第 22 列并且我想知道第 1 列(在同一行中)的值时,我该怎么办。我真的很难理解这些东西,但是当我得到它时,我明白了。感谢您的帮助。
    • 函数运行时传递事件对象。所以,不,你不能使用活动单元格方法,除非你选择了那个单元格。如果它在同一行中,您可以使用定义该行的事件对象在该行中获取您想要的任何列。是的,由于所有计算值的公式,您的工作表很慢。 Apps 脚本比工作表本身的公式计算要快得多。所以,慢的不是脚本,而是发生的所有其他事情。
    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 2011-09-02
    • 1970-01-01
    • 2021-05-12
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多