0

I've been trying to create a code that takes info from a Google Spreadsheet, and creates Google Calendar events. I'm new to this, so bear with my lack of in-depth coding knowledge!

I initially used this post to create a code: Create Google Calendar Events from Spreadsheet but prevent duplicates

I then worked out that it was timing out due to the number of rows on the spreadsheet, and wasn't creating eventIDs to avoid the duplicates. I got an answer here to work that out! Google Script that creates Google Calendar events from a Google Spreadsheet - "Exceeded maximum execution time"

And now I've realised that it's over-writing the formulas, I have in the spreadsheet, auto-completing into each row, as follows:

Row 12 - =if(E4="","",E4+1) // Row 13 - =if(C4="","",C4+1) // Row 18 - =if(B4="","","WHC - "&B4) // Row 19 - =if(B4="","","Docs - "&B4)

Does anyone have any idea how I can stop it doing this?

/**
 * Adds a custom menu to the active spreadsheet, containing a single menu item
 * for invoking the exportEvents() function.
 * The onOpen() function, when defined, is automatically invoked whenever the
 * spreadsheet is opened.
 * For more information on using the Spreadsheet API, see
 * https://developers.google.com/apps-script/service_spreadsheet
 */
function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Export WHCs",
    functionName : "exportWHCs"
  },
                {
    name : "Export Docs",
    functionName : "exportDocs"
  }];
  sheet.addMenu("Calendar Actions", entries);
};

/**
 * Export events from spreadsheet to calendar
 */
function exportWHCs() {
  // 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('exportWHCs').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 = 4;  // Number of rows of header info (to skip)
  var range = sheet.getDataRange();
  var data = range.getValues();
  var calId = "flightcentre.com.au_pma5g2rd5cft4lird345j7pke8@group.calendar.google.com";
  var cal = CalendarApp.getCalendarById(calId);
  for (i in data) {
    if (i < headerRows) continue; // Skip header row(s)
    var row = data[i];
    var date = new Date(row[12]);  // First column
    var title = row[18];           // Second column
    var tstart = new Date(row[15]);
    tstart.setDate(date.getDate());
    tstart.setMonth(date.getMonth());
    tstart.setYear(date.getYear());
    var tstop = new Date(row[16]);
    tstop.setDate(date.getDate());
    tstop.setMonth(date.getMonth());
    tstop.setYear(date.getYear());
    var id = row[17];              // Sixth column == eventId
    // Check if event already exists, update it if it does
    try {
      var event = cal.getEventSeriesById(id);
    }
    catch (e) {
      // do nothing - we just want to avoid the exception when event doesn't exist
    }
    if (!event) {
      //cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"));
      var newEvent = cal.createEvent(title, tstart, tstop).addEmailReminder(5).getId();
      row[17] = newEvent;  // Update the data array with event ID
    }
    else {
      event.setTitle(title);
    }
    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;
    }    
    debugger;
  }
  // Record all event IDs to spreadsheet
  range.setValues(data);
}



/**
 * Export events from spreadsheet to calendar
 */
function exportDocs() {
  // 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('exportDocs').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 = 4;  // Number of rows of header info (to skip)
  var range = sheet.getDataRange();
  var data = range.getValues();
  var calId = "flightcentre.com.au_pma5g2rd5cft4lird345j7pke8@group.calendar.google.com";
  var cal = CalendarApp.getCalendarById(calId);
  for (i in data) {
    if (i < headerRows) continue; // Skip header row(s)
    var row = data[i];
    var date = new Date(row[13]);  // First column
    var title = row[19];           // Second column
    var tstart = new Date(row[15]);
    tstart.setDate(date.getDate());
    tstart.setMonth(date.getMonth());
    tstart.setYear(date.getYear());
    var tstop = new Date(row[16]);
    tstop.setDate(date.getDate());
    tstop.setMonth(date.getMonth());
    tstop.setYear(date.getYear());
    var id = row[20];              // Sixth column == eventId
    // Check if event already exists, update it if it does
    try {
      var event = cal.getEventSeriesById(id);
    }
    catch (e) {
      // do nothing - we just want to avoid the exception when event doesn't exist
    }
    if (!event) {
      //cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"));
      var newEvent = cal.createEvent(title, tstart, tstop).addEmailReminder(5).getId();
      row[20] = newEvent;  // Update the data array with event ID
    }
    else {
      event.setTitle(title);
    }
    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;
    }    
    debugger;
  }
  // Record all event IDs to spreadsheet
  range.setValues(data);
}
Community
  • 1
  • 1
Ingrid
  • 15
  • 2
  • 8

1 Answers1

0

You have to ways to solve that problem.

First possibility : update your sheet with array data only on columns that have no formulas, proceeding as in this other post but in your case (with multiple columns to skip) it will rapidly become tricky

Second possibility : (the one I would personally choose because I 'm not a "formula fan") is to do what your formulas do in the script itself, ie translate the formulas into array level operations.

following your example =if(E4="","",E4+1) would become something like data[n][4]=data[n][4]==''?'':data[n+1][4]; if I understood the logic (but I'm not so sure...).


EDIT

There is actually a third solution that is even simpler (go figure why I didn't think about it in the first place...) You could save the ranges that have formulas, for example if col M has formulas you want to keep use :

var formulM = sheet.getRange('G1:G').getFormulas();

and then, at the end of the function (after the global setValues()) rewrite the formulas using :

sheet.getRange('G1:G').setFormulas(formulM);

to restore all the previous formulas... as simple as that, repeat for every column where you need to keep the formulas.

Community
  • 1
  • 1
Serge insas
  • 45,904
  • 7
  • 105
  • 131