【问题标题】:Google App Script: Speed up script - Conditional copy to another tabGoogle App Script:加速脚本 - 有条件地复制到另一个选项卡
【发布时间】:2021-12-14 13:00:10
【问题描述】:

有 2 个标签:

  • 警报
  • 大师

脚本:

  • 在警报选项卡中,如果 A 为空且 H >= 45,则将值从 G 复制到 A,在 MASTER 中的下一个空行中
  • 在 MASTER 选项卡中最近添加的行上的某些列中添加特定值。所有新行都将具有相同的值。

脚本偶尔会检索一些超时,我尝试添加一些

SpreadsheetApp.flush();

由于我们与这些添加无关,脚本开始运行得更好,但我相信随着列表的增长,它会返回更多超时。

可以加快速度吗?

function CopyPendingPayment(){
  var sheet = SpreadsheetApp.getActive();
  var sourceSheet = sheet.getSheetByName("Alerts");
  var destination = sheet.getSheetByName("MASTER");
  var lastRow = sourceSheet.getDataRange().getLastRow();
  var column = destination.getRange('A' + destination.getMaxRows())
  SpreadsheetApp.flush();

  for(var row=3; row<=lastRow; row++){
  if(sourceSheet.getRange(row,1).getValue() == "" & sourceSheet.getRange(row,8).getValue() >= "45"){
      var rangeToCopy = "G"+row+":G"+row;
      var lastFilledRow = parseInt(column.getNextDataCell(SpreadsheetApp.Direction.UP).getA1Notation().slice(1))
      SpreadsheetApp.flush();
      
      sourceSheet.getRange(rangeToCopy).copyTo(destination.getRange(lastFilledRow+1,1)),{contentsOnly:true};
      destination.getRange(lastFilledRow+1, 9).setValue("No Payment Received");
      destination.getRange(lastFilledRow+1, 10).setValue(new Date());
      destination.getRange(lastFilledRow+1, 12).setValue("PENDING");
      destination.getRange(lastFilledRow+1, 13).setValue("- Reminder sent");
      destination.getRange(lastFilledRow+1, 14).setValue(new Date());
    }
    }
  }

我猜至少在不同列上广告值的部分可以更快地完成,对吧?

谁能帮帮我? 提前谢谢你

Sample

【问题讨论】:

标签: google-apps-script google-sheets


【解决方案1】:

我相信你的目标如下。

  • 您希望降低脚本的处理成本。

这样的话,下面的修改怎么样?

修改脚本:

function CopyPendingPayment() {
  var sheet = SpreadsheetApp.getActive();
  var sourceSheet = sheet.getSheetByName("Alerts");
  var destination = sheet.getSheetByName("MASTER");
  
  // I modified below script.
  var srcValues = sourceSheet.getRange("A3:H" + sourceSheet.getLastRow()).getValues();
  var lastRow = destination.getLastRow();
  var obj = srcValues.reduce((o, [a,,,,,,g,h], i) => {
    if (a == "" && h >= 45) {
      o.values.push([g]);
      o["No Payment Received"].push(`I${lastRow + i + 1}`);
      o["date"].push(`J${lastRow + i + 1}`, `N${lastRow + i + 1}`);
      o["PENDING"].push(`L${lastRow + i + 1}`);
      o["- Reminder sent"].push(`M${lastRow + i + 1}`);
    }
    return o;
  }, {values: [], "No Payment Received": [], "date": [], "PENDING": [], "- Reminder sent": []});
  destination.getRange(lastRow + 1, 1, obj.values.length).setValues(obj.values);
  ["No Payment Received", "date", "PENDING", "- Reminder sent"].forEach(e => destination.getRangeList(obj[e]).setValue(e == "date" ? new Date() : e));
}
  • 在此修改中,将“A”列的值与 Class Range 的setValues 放在一起。并且,列“I”、“J”、“L”、“M”和“N”的值被放入类 RangeList 的setValue。因为我认为您可能想保留其他列。

  • 作为另一种方法,我认为您的目标也可以通过覆盖目标工作表的单元格来实现。那么,下面的脚本呢?

      function CopyPendingPayment() {
        var sheet = SpreadsheetApp.getActive();
        var sourceSheet = sheet.getSheetByName("Alerts");
        var destination = sheet.getSheetByName("MASTER");
        var srcValues = sourceSheet.getRange("A3:H" + sourceSheet.getLastRow()).getValues();
        var lastRow = destination.getLastRow();
        var values = srcValues.reduce((ar, [a,,,,,,g,h], i) => {
          if (a == "" && h >= 45) {
            var date = new Date();
            ar.push([g,,,,,,,,"No Payment Received", date,,"PENDING","- Reminder sent",date]);
          }
          return ar;
        }, []);
        destination.getRange(lastRow + 1, 1, values.length, values[0].length).setValues(values);
      }
    

参考资料:

补充:

根据您的以下回复,

确实,它看起来要快得多。我已经测试了你的版本和我的版本。唯一的问题是,如果在任何其他目标工作表列中有一个数组,则值将粘贴在下面。原始版本考虑到这一点,并将值粘贴到 A 列的第一个空白单元格中。

下面的示例脚本怎么样?

示例脚本:

function CopyPendingPayment_C() {
  // This is from https://stackoverflow.com/a/44563639
  Object.prototype.get1stEmptyRowFromTop = function (columnNumber, offsetRow = 1) {
    const range = this.getRange(offsetRow, columnNumber, 2);
    const values = range.getDisplayValues();
    if (values[0][0] && values[1][0]) {
      return range.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() + 1;
    } else if (values[0][0] && !values[1][0]) {
      return offsetRow + 1;
    }
    return offsetRow;
  };

  var sheet = SpreadsheetApp.getActive();
  var sourceSheet = sheet.getSheetByName("Alerts");
  var destination = sheet.getSheetByName("MASTER");
  
  // I modified below script.
  var srcValues = sourceSheet.getRange("A3:H" + sourceSheet.getLastRow()).getValues();
  var lastRow = destination.get1stEmptyRowFromTop(1) - 1;

  // I modified below part.
  var obj = srcValues.reduce((o, [a,,,,,,g,h]) => {
    if (a == "" && h >= 45) {
      o.offset++;
      o.values.push([g]);
      o["No Payment Received"].push(`I${o.offset}`);
      o["date"].push(`J${o.offset}`, `N${o.offset}`);
      o["PENDING"].push(`L${o.offset}`);
      o["- Reminder sent"].push(`M${o.offset}`);
    }
    return o;
  }, {values: [], "No Payment Received": [], "date": [], "PENDING": [], "- Reminder sent": [], offset: lastRow});

  destination.getRange(lastRow + 1, 1, obj.values.length).setValues(obj.values);
  ["No Payment Received", "date", "PENDING", "- Reminder sent"].forEach(e => destination.getRangeList(obj[e]).setValue(e == "date" ? new Date() : e));
}

【讨论】:

  • 感谢您的帮助,对于迟到的回复深表歉意。确实,这似乎快了很多。我已经测试了你的版本和我的版本。唯一的问题是,如果在任何其他目标工作表列中有一个数组,则值将粘贴在下面。原始版本考虑到这一点并将值粘贴到 A 列的第一个空白单元格中。
  • @user1128912 感谢您的回复。我带来的不便表示歉意。为了您的回复,我又添加了一个示例脚本。你能确认一下吗?如果这没有用,我再次道歉。
  • 再次感谢您的快速回答。现在它确实考虑了 A 列上最后一个填充的单元格(其他列上的数组公式没有问题)!但是您是否注意到,例如,如果只有一个值要复制到 MASTER,则脚本添加的值会转到错误的行?例如,如果“警报”中的第一个值有 40 天,而其他值 >=45,也会发生这种情况。我已将填充示例留在“示例”表上。
  • @user1128912 感谢您的回复。我带来的不便表示歉意。关于But did you notice that if for example there is only one value to copy to MASTER, the added values by the script go to the wrong row?,我没有注意到这一点。这是因为我的技术不好。我为我糟糕的技术深表歉意。我更新了我的底部示例脚本以供您回复。你能确认一下吗?如果您能原谅我的拙劣技能,我将不胜感激。
  • 非常感谢!有用。将在接下来的几天里使用它,看看是否还有其他问题,但我已经进行了几次测试,没有错误。它似乎仍然比原始版本更快,这是主要目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-28
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多