Google Script that creates Google Calendar events from a Google Spreadsheet - “Exceeded maximum execution time”

我是研究僧i 提交于 2019-12-02 07:19:51

The idea is to count the time the script is taking inside the main function and to interrupt it when we reach the limit.

We have to store the row number where we interrupt the script and continue from there on the next run.

Since we don't want to do that manually (how lazy we are :-) we'll set up a trigger to run it every 5 minutes.

Below is a full script. It will send you an email on each run to tell you the progress... you'll have to remove this line after your test of course (unless you like receiving emails every 5 minutes from yourself !)

You will have to change the calendar ID, the row distribution (I tested it on a sheet with less column than yours) but that will be fairly easy.

function createEventsWithBatch() {
  // check if the script runs for the first time or not,
  // if so, create the trigger and PropertiesService.getScriptProperties() the script will use
  // a start index and a total counter for processed items
  // else continue the task
  if(PropertiesService.getScriptProperties().getKeys().length==0){ 
    PropertiesService.getScriptProperties().setProperties({'itemsprocessed':0});
    ScriptApp.newTrigger('createEventsWithBatch').timeBased().everyMinutes(5).create();
  }
  // initialize all variables when we start a new task, "notFinished" is the main loop condition
  var itemsProcessed = Number(PropertiesService.getScriptProperties().getProperty('itemsprocessed'));
  var startTime = new Date().getTime();
  var sheet = SpreadsheetApp.getActiveSheet();
  var headerRows = 1;  // Number of rows of header info (to skip)
  var range = sheet.getDataRange();
  var data = range.getValues();
  var calId = "h22nevo15tm0nojb6ul4hu7ft8@group.calendar.google.com";
  var cal = CalendarApp.getCalendarById(calId);
  for (var i = itemsProcessed ; i < data.length ; i++){
    if (i < headerRows) continue; // Skip header row(s)
    var row = data[i];
    var date = new Date(row[0]);  // First column
    var title = row[1];           // Second column
    var tstart = setTimeToDate(date,row[2]);
    var tstop = setTimeToDate(date,row[3]);
//    Logger.log('date = '+date+'tstart = '+tstart+'  tstop = '+tstop);
    var loc = row[4];
    var desc = row[5];
    var type = row[6];
    var times = row[7]
    var id = row[8]; 
    // Check if event already exists, update it if it does
    try {
      var event = cal.getEventSeriesById(id);
      event.setTitle('got you');
    }catch(e){
      var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc});
      row[8] = newEvent.getId();  // Update the data array with event ID
//      Logger.log('event created');
      var event = cal.getEventSeriesById(row[8]);
    }
    event.setTitle(title);
    event.setDescription(desc);
    event.setLocation(loc);
    if(type=='PM'){
      var recurrence = CalendarApp.newRecurrence().addMonthlyRule().times(times);
      event.setRecurrence(recurrence, tstart, tstop);
    }else if(type=='PW'){
      var recurrence = CalendarApp.newRecurrence().addWeeklyRule().times(times)
      event.setRecurrence(recurrence, tstart, tstop);
    }
    data[i] = row ; 
    Logger.log(i+'    '+new Date().getTime()-startTime)
    if(new Date().getTime()-startTime > 240000){ // if > 4 minutes
      var processed = i+1;// save usefull variable
      PropertiesService.getScriptProperties().setProperties({'itemsprocessed':processed});
      range.setValues(data);
      MailApp.sendEmail(Session.getEffectiveUser().getEmail(),'progress sheet to cal','item processed : '+processed);
      return;
    }
  }  
  range.setValues(data);// this time we are done !
  killTrigger();// delete the trigger
  PropertiesService.getScriptProperties().deleteAllProperties(); // clean up properties
}

function setTimeToDate(date,time){
  var t = new Date(time);
  var hour = t.getHours();
  var min = t.getMinutes();
  var sec = t.getSeconds();
  var dateMod = new Date(date.setHours(hour,min,sec,0))
  return dateMod;
}

function killTrigger(){
  var trigger = ScriptApp.getProjectTriggers()[0];
  ScriptApp.deleteTrigger(trigger);
}

There are various GAS libraries that help you get past the 5 minute execution timeout, using the same idea as @Serge suggested. I personally use the Continuous Batch Library.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!