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.
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.replicateForEmployee_()
function.determineTimes()
function to see how long getting employees & file replication takes.determineTimes()
in the replicate()
function. The output of determineTimes()
will be visible in the Executions page (View > Executions). 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]);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.