[英]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.