mbb
mbb

Reputation: 3110

Copy events from one Google Calendar to another, without duplication

I'm working on building some logic between a couple calendars.

I'm getting stuck after retrieving the two calendars. I'm not sure how to gracefully add the logic I have in comments at the bottom.

function copyInstalls(){
  var now = new Date();
  var later = new Date("January 1, 2015 08:00:00 PDT"); // be lazy for now

  // get my calendar to see whether I have install events scheduled 
  var my_calendar = CalendarApp.getDefaultCalendar();
  var my_install_events =  
  CalendarApp.getCalendarById('[email protected]').getEvents(now, later, {search: 'Install'});


  // snag the Installation Events calendar 
  var install_calendar = CalendarApp.getCalendarById('[email protected]');
  var install_events = CalendarApp.getCalendarById('[email protected]').getEvents(now, later, {search: 'Install'});  

  for (var event in my_install_events){

     // if it doesn't exist in install_events, create a new event
     // Not sure how to do this part

  }

}

Upvotes: 2

Views: 2121

Answers (1)

Mogsdad
Mogsdad

Reputation: 45720

You need to be clear about what criteria would identify whether one of your "Install" events is already on the InstallCalendar. Since your intent is to reproduce a copy of the original event, we can't expect that the event ID will be the same. (However, if you invited the InstallCalendar instead, it would be - and better yet, rescheduling would be automatically reflected.)

We could assume that matching "Install" in the subject + identical start times is sufficient for a match. But then rescheduling on one calendar would orphan the event on the other, leading to duplication.

A better choice is to apply a custom tag to the event in InstallCalendar, setting it to the ID of the original event for convenience. Then we just need to search through all the previously-set tags looking for a match for event IDs from my_calendar. To prepare for this, we can build an array of those tags:

  // build array of event tags for comparison
  var install_event_Tags = [];
  install_events.forEach( function (event) {
    install_event_Tags.push(event.getTag('origID'));
  });

With that done, here's how we'd ensure we copy events exactly once:

  ...
  my_install_events.forEach( function (event) {
     // if it doesn't exist in install_events, create a new event
    var eventId = event.getId();
    var match = install_event_Tags.indexOf(eventId);
    if (match === -1) {
      // Duplicate the event from my_calendar
      var newEvent = install_calendar.createEvent(event.getTitle(), event.getStartTime(), event.getEndTime());
      // Apply a tag with original event ID
      newEvent.setTag('origID', eventId);
    }
  });

Other issues

There appear to be other problems in your code that you should address.

  1. When retrieving my_install_events, you are opening the shared example calendar, which is also used later for install_events.

      // get my calendar to see whether I have install events scheduled 
      var my_calendar = CalendarApp.getDefaultCalendar();
      var my_install_events =  
      CalendarApp.getCalendarById('[email protected]').getEvents(now, later, {search: 'Install'});
    

    Perhaps you mean...

      // get my calendar to see whether I have install events scheduled 
      var my_calendar = CalendarApp.getDefaultCalendar();
      var my_install_events = my_calendar.getEvents(now, later, {search: 'Install'});
                              ^^^^^^^^^^^
    
  2. Not a bug, per se, but repeating the call to getCalendarById will slow your code. Since you've calculated install_calendar, may as well use it.

    // snag the Installation Events calendar 
    var install_calendar = CalendarApp.getCalendarById('[email protected]');
    var install_events = CalendarApp.getCalendarById('[email protected]').getEvents(now, later, {search: 'Install'});  
    

    More easily maintained:

    // snag the Installation Events calendar 
    var install_calendar = CalendarApp.getCalendarById('[email protected]');
    var install_events = install_calendar.getEvents(now, later, {search: 'Install'});  
                         ^^^^^^^^^^^^^^^^
    

Final script

function copyInstalls(){
  var now = new Date();
  var later = new Date("January 1, 2015 08:00:00 PDT"); // be lazy for now

  // get my calendar to see whether I have install events scheduled 
  var my_calendar = CalendarApp.getDefaultCalendar();
  var my_install_events = my_calendar.getEvents(now, later, {search: 'Install'});

  // snag the Installation Events calendar 
  var install_calendar = CalendarApp.getCalendarById('[email protected]');
  var install_events = install_calendar.getEvents(now, later, {search: 'Install'});

  // build array of event tags for comparison
  var install_event_Tags = [];
  install_events.forEach( function (event) {
    install_event_Tags.push(event.getTag('origID'));
  });

  my_install_events.forEach( function (event) {
     // if it doesn't exist in install_events, create a new event
    var eventId = event.getId();
    var match = install_event_Tags.indexOf(eventId);
    if (match === -1) {
      // Duplicate the event from my_calendar
      var newEvent = install_calendar.createEvent(event.getTitle(), event.getStartTime(), event.getEndTime());
      // Apply a tag with original event ID
      newEvent.setTag('origID', eventId);
    }
  });
}

Next steps

This script will make unique copies of Install events from my_calendar to InstallCalendar. That may be sufficient for your needs. However, there are additional scenarios you might want to consider:

  • What if the Install event exists in InstallCalendar, but was rescheduled?
  • What if an event previously copied to InstallCalendar gets deleted from my_calendar?
  • What if an event previously copied to InstallCalendar gets deleted there? The current script would copy it again, but maybe the desired behavior is to delete it from my_calendar as well.

Upvotes: 4

Related Questions