How to synchronize Google Calendar & Spreadsheet w

2019-04-10 17:04发布

问题:

I am trying to create a Google Apps Script that keeps a Google Calendar and a "master spreadsheet" on Drive synchronized -- is this possible? I found these two posts:

  • http://blog.ouseful.info/2010/03/04/maintaining-google-calendars-from-a-google-spreadsheet/

  • http://blog.ouseful.info/2010/03/05/grabbing-google-calendar-event-details-into-a-spreadsheet/

I'm quite sure this could be done using a lot of if statements and logic, but maybe there's a simpler way?

I ended up just providing the following simple script. All that was really necessary was adding events based on two columns, and this would've taken too long to develop.

function onOpen() {
  //spawns a menu with a button that triggers AddToCal
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Add event to calendar",
    functionName : "AddToCal"
  }];
  sheet.addMenu("Data To Calendar Plugin", entries);
};

function AddToCal(){

  //get the current row
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var cell = ss.getActiveCell();
  var R = cell.getRow();

  //grab values for current row to pass to calendar event
  var date_of_event = ss.getRange('G'+R).getValue();
  var date = new Date(date_of_event);
  var event_title = ss.getRange('A'+R).getValue();
  //access the calendar
  var cal = CalendarApp.getCalendarById('[IDREMOVED]');
  cal.createAllDayEvent(event_title,date);

  ss.toast("Event added to " + cal.getName());
  }

回答1:

Yes, it's possible to write a two-way event synchronization script, but it isn't going to be simple. Those two posts you refer have parts that could be reused, but they are quite elementary compared to the challenges you'll face with actual synchronization. You may want to read over Using Google Apps Script for a event booking system which does create calendar entries based on a spreadsheet (but doesn't do on-going synchronization). I've done some debugging of that script in past.

Synchronization would need to support:

  • Creation of events in either location
  • Modification of event details in either location (although you could opt to consider only a subset of event details for simplification)
  • Deletion of events in either location
  • Recurrence, e.g. CalendarEvent.getEventSeries() handling (or choose to avoid)

This is pseudo-code that you could start with:

Open Calendar, Read Calendar events into calArray (will all attributes you care for)
Open Spreadsheet, Read Spreadsheet events into sheetArray

For each event in calArray:
  Search for calEvent in sheetArray.
  If found, compare lastUpdated values.
    If equal, do nothing
    Otherwise copy most recently updated to least recently updated
    Continue with next event
  If not found then copy calEvent to new sheetEvent, including lastUpdated value.
  Continue with next event

For each event in the sheetArray (...that hasn't been handled yet)
  Similar logic above.

Write updated sheetArray to spreadsheet.
Write updated calEvents to calendar API (see note 1 below)

Notes:

  1. All updates to calEvents could be made to array and written to calendar API immediately, as an alternative to a bulk update. This would eliminate the need to track the changes locally, although it would be a good idea to touch the lastUpdated value.

  2. You will want to use CalendarEvent.getLastUpdated() when reading calEvents, and store a similar value in your spreadsheet (tied to an onEdit trigger) to facilitate comparisons.

  3. It would simplify comparisons to record CalendarEvent.getId() against events in the spreadsheet. You also have CalendarEvent.setTag(key,value) that could be used to record custom metadata into the calendar, for instance to indicate events that originated or have been synchronized with your spreadsheet. (These tags are not accessible through the GCal UI, so would only be accessible via script.)

  4. You should think about the range of dates or number of events you want to deal with, and limit the scope of the script. If you don't, you are sure to run into execution time limits in real operation.

  5. Some Calendar Event characteristics don't lend themselves to easy expression in a spreadsheet, for instance:

    • Guest list
    • Reminder list


回答2:

As mentioned (thanks Henrique) in the other post I've spent some time - it was actually what brought me to GAS originally - on data exchange between spreadsheets and calendars mainly because people I worked with where used to organize their time schedule (for a highschool) in spreadsheets and I had to take care of the transition to Google Calendars.

After some time though it appeared that the online Calendar interface is far more effective to create events so they don't use the sheet to Calendar scripts anymore !!

On the other hand, the printing and presentation options in GCal are very limited so the other direction is still very useful and we use it all the time !

I know this will seem to be out of subject regarding the original question and maybe too anecdotic but I just wanted to point out that you should thoroughly think about what you really need before reinventing the wheel... As Mogsdad mentioned, some events parameter are not easily described in spreadsheet logic and finally it could become a lot more complicated to use than the original tool.

The only really useful tool I developed using bidirectional data transfer is a 'batch modification tool" when I need to delete or edit a big number of similar events.

For example if we need to change a teacher's name for some reason all along the year I import all the events for a number of class, replace the name in the spreadsheet and update back the class calendar... it takes me 5 minutes and is very easy but these are very specific use cases and I'm not sure it is very common.

Anyway I wouldn't call that "synchronization" since it only takes some events some time and changes them... I've never attempted to keep a spreadsheet up to date with a calendar, from my experience calendars are pretty reliable and I consider them as the original data source. As I already said, we import data in spreadsheets every week just for printing and local archiving.

Sorry for this long and a bit vague comment (that was way too long to fit in a normal 500 chrs comment ;-)



回答3:

No there isn't. And although a lot of issues regarding Apps Script Calendar Service has been solved (timezones, all day events, queries and so on), it's still a fairly complex task.

I know Serge, the top contributor here in SO on #google-apps-script tag, has developed quite some scripts involving the Calendar Service.

But I don't know of anyway that made a two-way update between a calendar and a spreadsheet. It should be a hard one. If you ever do, please be kind to share :)