0

I'm trying to create a sheet that creates events into multiple google calendars from a single google sheet. I am using a sheet modified from the fantastic solution on this post Create Google Calendar Events from Spreadsheet but prevent duplicates from Mogsdad. However I have been triplicating my work to go into 3 different calendars and would like to have my first go at programming. My idea is I would like to go one step further and add a drop down column (labeled status) containing either (Unconfirmed, Save the date, Confirmed) which would then create an even in one or all three calendars named the same as the conditional drop down.

My sheet is arranged as :-

Date | Title | Start Time | End Time | Location | Description | Even ID | Status | Confirmed details | Confirmed Start time | confirmed end time |

As you can see my idea is to have slightly different info in the confirmed calendar than the other two.

The existing code i'm using is

/**
 * 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 Events",
    functionName : "exportEvents"
  }];
  sheet.addMenu("Calendar Actions", entries);
};

/**
 * Export events from spreadsheet to calendar
 */
function exportEvents() {
  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 = "30kpfnt5jlnooo688qte6ladnk@group.calendar.google.com";
  var cal = CalendarApp.getCalendarById(calId);
  for (i=0; 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 = new Date(row[2]);
    tstart.setDate(date.getDate());
    tstart.setMonth(date.getMonth());
    tstart.setYear(date.getYear());
    var tstop = new Date(row[3]);
    tstop.setDate(date.getDate());
    tstop.setMonth(date.getMonth());
    tstop.setYear(date.getYear());
    var loc = row[4];
    var desc = row[5];
    var id = row[6];              // Sixth column == eventId
// Check if event already exists, delete it if it does
try {
  var event = cal.getEventSeriesById(id);
  event.deleteEventSeries();
  row[6] = '';  // Remove event ID    
}
catch (e) {
  // do nothing - we just want to avoid the exception when event doesn't exist
}
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
row[6] = newEvent;  // Update the data array with event ID
debugger;
  }
  // Record all event IDs to spreadsheet
  range.setValues(data);
}

So I realize I need to define the new info to go into the "confirmed" calendar as well as the 2 additional calendars. My issue is I don't know how to fit in a series of if loops to direct events to the 3 calendars. I would also like the calendars to be additive e.g. all events appear in "unconfirmed calendar" events get added to save the date when uprated to that status and then finally appear in "confirmed" when set to that. So a confirmed event appears in all 3 calendars but an unconfirmed only appears there.

I'm virtually brand new to programming so please be nice and excuse my blatant plagarism of others work (thanks Mogsdad) and I appreciate any help!

Community
  • 1
  • 1

1 Answers1

0

Welcome to programming! Once you get the hang of it, you'll want to script every Google product you use. :)

If I understand your question correctly, you would like to be able to choose which calendar an event goes into when you run the function exportEvents(). There are several ways to do this, and you don't need any additional loops! You can make use of objects and refer to them by name.

What I would do first, where you currently define cal and calId, is create an object that defines the three calendars like this:

var cal1 = "30kpfnt5jlnooo688qte6ladnk@group.calendar.google.com";
var cal2 = "string url for second calendar";
var cal3 = "string url for third calendar";
var calendars = {
   Unconfirmed: CalendarApp.getCalendarById(cal1),
   SaveTheDate: CalendarApp.getCalendarById(cal2),
   Confirmed: CalendarApp.getCalendarById(cal3)
}

The object calendars now contains the calendar objects for the three calendars such that the key is the status and the value is the object. Then, when you're grabbing the data for each row, add

var cal = row[7];

Now, cal contains the string indicating the status. You can make great use of chaining by making one change to your newEvent definition:

var newEvent = calendars[cal].createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();

What's happening here is calendars[cal] gets the calendar object corresponding to the string in the table, to which you can then add the new event. This does require making a change to your sheet - change the label in your status column from 'Save the Date' to 'SaveTheDate' so it matches the variable name. That should do it!

EDIT

To add the event to multiple calendars, I would use if statements, but you don't need a loop. Something like the following would work:

calendars['Unconfirmed'].createEvent(title...  // Add to unconfirmed no matter what
if (cal != 'Unconfirmed'){
  calendars['SaveTheDate'].createEvent(title... // Add to SaveTheDate only if not Unconfirmed
}
if (cal == 'Confirmed'){
  calendars['Confirmed'].createEvent(title...  // Only add to Confirmed if Confirmed
}
  • Hi Tiffany, Thanks very much thats very helpful and works well. I have a follow up question I would like to ask. I would like the "confirmed" events to go into all 3 calendars, the "SaveTheDate" to go into "SaveTheDate" and "Unconfirmed" calendars and then "Unconfirmed" to only go into "Unconfirmed" calendar. Do you know how I can make them additive rather than selecting just the one calendar to go too. In my original idea i would have an "if" if loop to then send it to each calendar but your method makes me feel like there could be a simplar way! Thanks in advance – Alex Parky Parker Aug 17 '16 at 15:02
  • See my answer - I added something that should help. Please accept my answer if you feel it was useful! – Tiffany G. Wilson Aug 17 '16 at 22:23
  • I forgot to say before your previous answer lost the scrips ability to deleate old events (to avoid duplicates) untill I the deleat event line was updated too. `try { var event = calendars['Unconfirmed'].getEventSeriesById(id);` all is now working except for the the 2 new calenders introduced don't delete updated events. I've tried adding 2 addtional try and catch functions with `try { var event = calendars['Confirmed'].getEventSeriesById(id); event.deleteEventSeries(); } catch (e) { }` but this does not seem to work (in fact is does nothing any idea why? – Alex Parky Parker Aug 18 '16 at 08:40
  • any idea why im getting the duplicate events again now in the 2 new calendars? – Alex Parky Parker Aug 21 '16 at 08:37
  • I imagine that you're getting duplicate events because the event ID you're recording only refers to the first calendar. In order for your delete section to work, you would have to record the event ID for all three calendars and then check each calendar with its respective event ID. Your other option is to clear all three calendars each time you run the export function. It will almost certainly be slower, but it will work. – Tiffany G. Wilson Aug 22 '16 at 12:08
  • Hmm that means I'm not quite doing what I thought! oops. I thought I was using event ID's to serch for and then deleate events currently my deleate section is `try { var event = calendars[cal].getEventSeriesById(id); event.deleteEventSeries(); row[6] = ''; // Remove event ID` I thiought the use of `calendars[cal]` would serch and deleate from all 3 calendars? If not how do I record the event ID for all three calendars as you descride (I can't deleate whole calendar as that would remove the reoccuring events also in the calendar (created seperately)) as always thanks in advance! – Alex Parky Parker Aug 25 '16 at 07:29
  • very sorry to bug but i'm still struggling to fix this. Each way I try ends with the same effect of duplicates in the 2 new calendars? – Alex Parky Parker Sep 05 '16 at 09:36
  • I'm still struggling to stop the duplicates can you offer any advice to how to make the script search each calendar sequentially and remove events at the moment it seems capable of just one and then when it get to the second and third it does nothing (o seconds in the execution transcript)? thanks – Alex Parky Parker Oct 10 '16 at 12:49