繁体   English   中英

谷歌应用脚本超过最大执行时间问题

[英]Google apps script Exceeded maximum execution time issue

我构建了自己的应用程序脚本代码来更新转储文件中的日期。 我大部分时间都面临“超过最大执行时间”的问题。 但是代码运行良好。 它从工作表中导入和更新数据(16.5 K 行)的状态(29 k 行)你能支持使代码更快/工作正常吗?

function update_main_master() {
  var xngSs = SpreadsheetApp.openById('XXXX');
  var xngSh = xngSs.getSheetByName('XNG Clean Data');
  var MasterSs = SpreadsheetApp.openById('YYY');
  var MasterSh = MasterSs.getSheetByName('Master Sheet');
  var MasterData = MasterSh.getDataRange().getValues();
  var xngData = xngSh.getDataRange().getValues();

  //  clearFilter()
  if (MasterSh.getFilter() != null) {
    MasterSh.getFilter().remove();
  }

  xngData.splice(0, 1);
  MasterData.splice(0, 1);
  var OrderNumberMasterSh = [];
  var PathNameMasterSh = [];
  for (var i = 0; i < MasterData.length; i++) {
    OrderNumberMasterSh.push(MasterData[i][1]);
    PathNameMasterSh.push(MasterData[i][2]);
  }
  var i = 0;
  for (var x = 0; x < xngData.length && xngData[x][3] != undefined; x++) {
    var OrderNumber = xngData[x][3];
    var OrderDate = xngData[x][2];
    var PathName = xngData[x][4];
    var CustomerName = xngData[x][5];
    var MW_contractor = xngData[x][8];
    var OrderStatus = xngData[x][9];
    var OrderStage = xngData[x][10];
    var ProjectID = xngData[x][14];
    var OrderType = xngData[x][41];
    var StageDate = xngData[x][11];
    var InService = xngData[x][28];
    var RejectedReason = xngData[x][31];
    var District = xngData[x][15];
    var LinkID = xngData[x][24];
    var NewOrder = 'New Order';

    if (MW_contractor == 'A' || MW_contractor == 'B' || MW_contractor == 'C') {
      if (
        OrderType == 'New' ||
        OrderType == 'Repeater' ||
        OrderType == 'Visibility'
      ) {
        //        if(OrderType == "New" || OrderType == 'Repeater')

        var index = OrderNumberMasterSh.indexOf(OrderNumber);

        if (index == -1) {
          MasterData.push([
            OrderDate,
            OrderNumber,
            PathName,
            CustomerName,
            ProjectID,
            MW_contractor,
            OrderStatus,
            OrderStatus,
            OrderStage,
            OrderType,
            StageDate,
            InService,
            '',
            District,
            '',
            NewOrder,
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            RejectedReason,
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
          ]);
        } else {
          MasterData[index][4] = ProjectID;
          MasterData[index][5] = MW_contractor;
          MasterData[index][7] = OrderStatus;
          MasterData[index][8] = OrderStage;
          MasterData[index][10] = StageDate;
          MasterData[index][11] = InService;

          if (MasterData[index][51] == '') {
            MasterData[index][51] = LinkID;
          }

          if (
            OrderStatus == 'IN-PROCESS' ||
            OrderStatus == 'CANCELLED' ||
            OrderStatus == 'REJECTED'
          ) {
            MasterData[index][6] = OrderStatus;
          }

          if (OrderStatus == 'COMPLETED') {
            MasterData[index][6] = 'LIVE';
          }
          if (OrderStatus == 'REJECTED' && MasterData[index][48] == '') {
            MasterData[index][48] = RejectedReason;
          }
        }
      }
    }
  }

  var ContorlSS = SpreadsheetApp.openById('ZZZZ');
  var ContorlSh = ContorlSS.getSheetByName('Setup');
  ContorlSh.getRange('F6').setValue('Updated');
  ContorlSh.getRange('G6').setValue(new Date());

  MasterSh.getRange(2, 1, MasterData.length, MasterData[0].length).setValues(
    MasterData
  );
  SpreadsheetApp.flush();
}

我构建了自己的应用程序脚本代码来更新转储文件中的日期。 我大部分时间都面临“超过最大执行时间”的问题。 但是代码运行良好。 它从工作表中导入和更新数据(16.5 K 行)的状态(29 k 行)你能支持使代码更快/工作正常吗?

您即将达到执行时间限制,对于大多数帐户而言,该时间限制为 6 分钟。 为避免这种情况,您可以通过设置基于时间的触发器将循环拆分为不同的执行,该触发器将在前一个执行完成后触发每个后续执行。 您必须执行以下操作:

  • 每次迭代后检查执行时间。 如果这个时间接近时限,停止执行。 您可以为此使用日期 object

  • 在 function 的末尾创建以下基于时间的触发器: after(durationMilliseconds) 多亏了这一点,您可以在指定的毫秒数之后运行您指定的任何 function。 每次执行后,将创建一个触发器来触发下一个触发器。

  • 因为要拆分循环,所以必须将循环计数器 ( x ) 存储在某处(您可以在每次执行结束时使用PropertiesService ,或将其写入电子表格中)并在下一次开始时检索它,以便每个在连续执行中,脚本都知道在哪里恢复循环。 例如,如果您不知道如何存储和检索脚本属性,请参阅此答案

  • 现在,您将所需的所有数据存储在 2D 数组MasterData中,并在代码末尾使用setValues将此数据写入电子表格。 由于此操作仅在循环完成后发生,因此如果您将循环拆分为多个执行,这将是不合适的。 我建议您修改代码,以便在循环内进行编写过程,并从代码末尾删除setValues 您必须按照以下示例更改您的代码。

例如,尝试更改此:

MasterData[index][48] = RejectedReason;

有了这个:

MasterSh.getRange(index + 1, 49).setValue(RejectedReason);

和这个:

MasterData.push([OrderDate, OrderNumber, ...]);

有了这个:

MasterSh.appendRow([OrderDate, OrderNumber, ...]);

示例代码(检查内联注释):

function update_main_master() {
  var begin = new Date(); // Time when execution begins
  // Your code before loop
  var x_old = // Retrieve x stored in previous execution (from PropertiesService? Spreadsheet?) (should be 0 if first execution)
  var timeLimit = 1000 * 60 * 5; // 5 minutes (in milliseconds)
  while (new Date() - begin < timeLimit) { // Check if 5 minutes passed since execution start
    for (var x = 0; x < xngData.length && xngData[x][3] != undefined; x++) {
      // Your code inside loop
    }
  }
  // Store current x index (using PropertiesService? Or write to the spreadsheet itself?
  var ContorlSS = SpreadsheetApp.openById('ZZZZ');
  var ContorlSh = ContorlSS.getSheetByName('Setup');
  ContorlSh.getRange('F6').setValue('Updated');
  ContorlSh.getRange('G6').setValue(new Date());
  if (x < xngData.length) { // Create trigger if x hasn't reach the total number of iteration
    ScriptApp.newTrigger("update_main_master")
    .timeBased()
    .after(1000 * 60) // This fires the function 1 minute after the current execution ends. Change this time according to your preferences
    .create();  
  }
}

参考:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM