[英]Exceeded maximum execution time
Here's my code do:这是我的代码:
I'm getting the exceeded maximum execution time when I'm on the step 3 part which is the to get the pubHTML and put it in my config file.当我在第 3 步部分获取 pubHTML 并将其放入我的配置文件时,我得到了超出的最大执行时间。
My code is working as expected.我的代码按预期工作。 I want to avoid the maximum limit of execution error.我想避免执行错误的最大限制。
function replicateCards() {
var ss = SpreadsheetApp.openById('configfile--xxxx');
var copyCard = SpreadsheetApp.openById('replicateCard-xxxx');
var getID = DriveApp.getFileById(copyCard.getId())
var card = copyCard.getSheetByName("Card");
var mastersheet = ss.getSheetByName("Mastersheet");
var getLastRow = mastersheet.getLastRow();
var destinationFolder = DriveApp.getFolderById('gdrivefolder-xxxx');
var changeColorToGrayList = card.getRangeList(['C7', 'E7', 'G7', 'I7', 'K7', 'M7', 'O7', 'Q7',
'C9', 'E9', 'G9', 'I9', 'K9', 'M9', 'O9', 'Q9',
'C11', 'E11', 'G11', 'I11', 'K11', 'M11', 'O11', 'Q11']);
var setValueToZero = card.getRangeList(['C8', 'E8', 'G8', 'I8', 'K8', 'M8', 'O8', 'Q8',
'C10', 'E10', 'G10', 'I10', 'K10', 'M10', 'O10', 'Q10',
'C12', 'E12', 'G12', 'I12', 'K12', 'M12', 'O12', 'Q12']);
for (i = 1; i < getLastRow; i++) {
var badgeStatus = mastersheet.getRange(i + 1, 5).getValue();
if (badgeStatus == "") {
var employeeNumber = mastersheet.getRange(i + 1, 1).getValue();
var employeeName = mastersheet.getRange(i + 1, 2).getValue();
copyCard.getRange("H3").setValue(employeeNumber);
copyCard.getRange("C3").setValue(employeeName);
SpreadsheetApp.flush();
if(mastersheet.getRange(1 + i, 5).getValue() != "completed"){
getID.makeCopy(employeeNumber, destinationFolder);
mastersheet.getRange(1 + i, 5).setValue("completed");
}
// Logger.log(i);
SpreadsheetApp.flush();
}
}
var files = DriveApp.getFolderById(SpreadsheetApp.openById("configFile-xxxx").getSheetByName("Config Sheet").getRange("B1").getValue()).getFiles();
//var fileIter = 1;
var employeeNumbers = mastersheet.getRange("A2:A").getValues();
var employeeNumbersTrunc = []
for(var i = 0; i < employeeNumbers.length; i++){
if(employeeNumbers[i][0] != "")
employeeNumbersTrunc.push("" + employeeNumbers[i][0]);
}
Logger.log(employeeNumbersTrunc);
while (files.hasNext()) {
var file = files.next();
/*var Found = false;
for (var j = 0; j < ; fileIter++) {
if (employeeNumber2[j][0] == file.getName()) {
Found = true;
}
}//*/
if (employeeNumbersTrunc.indexOf(file.getName())==-1) {
continue;
}else if(mastersheet.getRange(2 + (employeeNumbersTrunc.indexOf(file.getName())), 9).getValue() != ""){
continue;
}
try {
var fileId = file.getId();
var fileName = file.getName();
var revisions = Drive.Revisions.list(fileId);
var lastRevisionId = revisions.items[revisions.items.length - 1].id;
// get the resource and set the publish parameters
var resource = Drive.Revisions.get(fileId, lastRevisionId);
// Logger.log(resource);
resource.published = true;
resource.publishAuto = true;
resource.publishedOutsideDomain = true;
// publish to the web
Drive.Revisions.update(resource, fileId, lastRevisionId);
SpreadsheetApp.flush();
var openByID = SpreadsheetApp.openById(fileId);
SpreadsheetApp.flush();
var googleDriveSheet = openByID.getUrl().replace("edit", "pubhtml"); // or replace("edit", "pub");
SpreadsheetApp.flush();
Logger.log(file.getName());
Logger.log(employeeNumbersTrunc.indexOf(file.getName()));
mastersheet.getRange(2 + (employeeNumbersTrunc.indexOf(file.getName())), 9).setValue(googleDriveSheet);
SpreadsheetApp.flush();
} catch (err) {
Logger.log(err);
}
}
}
Run the code one time only without the exceeded maximum execution time error.只运行一次代码,不会出现超出最大执行时间的错误。 Any suggestions?有什么建议么?
The code below is modified from what I've used before.下面的代码是根据我以前使用的代码修改的。 An approach like this allows you to fully execute a batch that alone cannot be done within the execution time limit .像这样的方法允许您完全执行一个单独无法在执行时间限制内完成的批处理。 By knowing how long a single operation in the batch takes, you can save your progress in the Properties before reaching that limit and programmatically create a trigger to resume processing.通过了解批处理中的单个操作需要多长时间,您可以在达到该限制之前将进度保存在属性中,并以编程方式创建触发器以恢复处理。
You will need to do a few things to make it work:您需要做一些事情才能使其工作:
getEmployees_()
function to accurately get the employees from your config file.您需要修改我的getEmployees_()
function 以准确地从您的配置文件中获取员工。replicateForEmployee_()
function.该代码应在我的replicateForEmployee_()
function 中为 go。determineTimes()
function to see how long getting employees & file replication takes.运行determineTimes()
function 以查看获取员工和文件复制需要多长时间。determineTimes()
in the replicate()
function.在replicate()
function 中插入determineTimes()
的结果。 The output of determineTimes()
will be visible in the Executions page (View > Executions). determineTimes()
的 output 将在“执行”页面(查看 > 执行)中可见。 Expand the execution row and you will see the durations as pictured.展开执行行,您将看到如图所示的持续时间。
/**
* Get all of the employees in the sheet. Assumes row in the sheet is one employee. Adjust the range as needed.
* @returns {Object[][]}
*/
function getEmployees_() {
var source = SpreadsheetApp.openById("configfile--xxxx");
var sheet = source.getSheetByName("Mastersheet");
return sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).getValues();
}
/**
* Refactor your current code so that this function will replicate all necessary files for a single
* employee. The function will be called for every single employee.
* @param {Object[]} employee - The row representing the employee in your config file
*/
function replicateForEmployee_(employee) {
// Execute your replication process for a SINGLE employee here
}
/**
* Run this, and then examine your script executions (View > Executions) to see how long each
* function takes. The resulting durations should replace the corresponding values in the replicate()
* function (I would recommend rounding up, so 458 --> 500ms).
*/
function determineTimes() {
console.time("timeToGetEmployees");
var employees = getEmployees_(); // Get all of the employees
console.timeEnd("timeToGetEmployees");
console.time("replicationDuration");
replicateForEmployee_(employees[0]); // Execute replication once
console.timeEnd("replicationDuration");
}
/**
* Replicates the files. When approaching the time limit, will save location and set a trigger to
* continue from stopping point. Emails user upon completion.
* @param {Boolean} isFromTrigger
* @returns {undefined}
*/
function replicate(isFromTrigger) {
var employees = getEmployees(); // Get all of the employees
var timeToGetEmployees = 1000; // Assume 1 second to execute getEmployees()
var replicationDuration = 500; // Number of milliseconds it takes to execute replication for one employee.
var maxExecutionTime = 360000 - timeToGetEmployees; // 6 mins - time already used to get employees
var continueFrom = 0; // If first execution, will be zero. Otherwise, get the index to start from.
if (isFromTrigger === true) {
continueFrom = parseInt(PropertiesService.getScriptProperties().getProperty("continueFrom"), 10);
}
var lapsedTime = 0; // ESTIMATED amount of time that has lapsed since the replication started
for (var i = continueFrom; i < employees.length; i++) {
// Replicate files for the employee
replicateForEmployee_(employees[i]);
// Checks how much time you have left
lapsedTime += replicationDuration;
if (lapsedTime >= (maxExecutionTime - replicationDuration)) { // warn just before timing out
PropertiesService.getScriptProperties().setProperty("continueFrom", i + 1); // save the last iterator value + 1
createAfterTrigger("replicateFromTrigger", 60000); // Start again in one minute
console.info("About to time out. Last iterator: " + i);
return;
}
}
deleteAllTriggers(); // Cleanup any lingering triggers
PropertiesService.getScriptProperties().deleteProperty("continueFrom"); // Clean up properties
// Send completion email
MailApp.sendEmail(Session.getEffectiveUser().getEmail(), "Replication Complete", "");
}
/**
* Should ONLY ever be called from a clock trigger.
* @returns {undefined}
*/
function replicateFromTrigger() {
replicate(true);
}
/**
* Create a new trigger to execute the specified function after a certain amount of time.
* @param {String} functionName - The name of the function to execute
* @param {Number} milliseconds - The duration (in milliseconds) after the current time when the trigger should run
* @returns {undefined}
*/
function createAfterTrigger(functionName, milliseconds) {
ScriptApp.newTrigger(functionName)
.timeBased()
.after(milliseconds)
.create();
}
/**
* Deletes all triggers in the current project.
* @returns {undefined}
*/
function deleteAllTriggers() {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.