从电子表格创buildGoogle日历事件,但防止重复

我正在尝试编写一个脚本,用于从Google电子表格中获取数据,并在Google日历中创build事件。

我pipe理得很好,但每次运行它都会产生重复。 所以现在我试图通过在电子表格中创build一个列17来为每一行自动生成唯一的事件ID,然后每次脚本运行时都会查看每行的事件ID并删除相应的事件在日历之前重新创build原始数据或更新的数据,如果我已经改变了行。

我不熟悉任何脚本,拼凑在一起,但现在却撞上了一堵墙。 有谁能帮忙解决这个问题吗?

function CalInsert() { var cal = CalendarApp.getDefaultCalendar(); var id = SpreadsheetApp.getActiveSheet().getRange(2,17).getValue(); if (id != 0) { var event = cal.getEventSeriesById(id); event.deleteEventSeries(); } var sheet = SpreadsheetApp.getActiveSheet(); var startRow = 2; // First row of data to process var numRows = sheet.getLastRow(); // Number of rows to process var dataRange = sheet.getRange(startRow, 1, numRows, sheet.getLastColumn()); var data = dataRange.getValues(); for (i in data) { var row = data[i]; var title = row[0]; // First column var desc = row[13]; // Second column var tstart = row[14]; var tstop = row[15]; var event = cal.createEvent(title, tstart, tstop, {description:desc}); var eventid = event.getId(); SpreadsheetApp.getActiveSheet().getRange(2,17).setValue(eventid); } } 

这与两天前提出的一个问题非常相似,即将一个事件电子表格与一个日历同步。 这听起来像是你想要把电子表格看作是事件发生的主人,这将大大简化问题。 这个答案涵盖了你需要做的基础知识。 如果你只是修改现有的代码,我已经在下面实现了。

我有这个博客的代码的修改版本,将修改预先存在的日历条目,以匹配电子表格中的信息。 我已经安排了不同的电子表格,这反映在代码中。

date| 标题| 开始时间| 结束时间| 位置| 说明| 事件ID

当创build新事件时,事件ID列会被脚本填充,然后在稍后的调用中使用,以从日历中检索事件,从而避免重复。

脚本

 /** * 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 = "YOUR_CALENDAR_ID"; 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, 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"), {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 } else { event.setTitle(title); event.setDescription(desc); event.setLocation(loc); // event.setTime(tstart, tstop); // cannot setTime on eventSeries. // ... but we CAN set recurrence! var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1); event.setRecurrence(recurrence, tstart, tstop); } debugger; } // Record all event IDs to spreadsheet range.setValues(data); } 

删除/重新创build

在这个替代scheme中,eventID用于查找和删除以前存在的事件。 之后,将使用电子表格中的数据创build新事件。 这具有可以更新事件的所有值的益处,包括开始和停止时间(参见下面的注释)。 另一方面,对原始事件所做的任何更改都将丢失 – 例如,如果其他人被邀请参加事件,或者添加了自定义提醒。

要使用这个替代方法,只需用下面的代码replace匹配的代码:

 // 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; 

笔记

  • getEventSeriesById的文档错误地指出,当没有find匹配的事件时,它返回null ,而是抛出一个exception。 (讨厌的!)所以我把它放在一个try / catch块,只是为了继续游泳。
  • 不幸的是,当getEventSeriesById检索一个事件时,它returns一个EventSeries对象,它不支持setTime()方法。 如果你不希望改变事件的时间,这个确定。 否则,您可以通过设置重复规则和时间将Event更改为EventSeries ,或删除旧事件并创build一个新事件,如Delete / Recreate中所示。 问题1154 。
  • 电子表格总是胜利。 通过Google日历logging的任何事件更改(在相关字段中)都将被脚本覆盖。

编号喜欢发布这个任何人谁想要使用它,我已经修改脚本工作在我已经使用的工作表内。 date格式和事件重复是一些需要解决的问题,但在经过一些testing之后,我很满意这种工作方式。我用它来预定工作,并与我的员工分享,他们是移动的,市。 下一步是将日历事件拉到电子表格,以便它可以双向工作,我可以使用手机上的日历应用程序来即时预订工作,所以如果任何人有任何build议,我还需要一个脚本插入将响应数据形成同一张表,并添加完整的行,其中作业编号匹配,保持现有数据不变。

 `function onOpen() { var sheet = SpreadsheetApp.getActiveSpreadsheet(); var entries = [{ name : "Export Events", functionName : "exportEvents" }]; sheet.addMenu("Calendar Actions", entries); }; function parseDate(s) { var months = {jan:0,feb:1,mar:2,apr:3,may:4,jun:5, jul:6,aug:7,sep:8,oct:9,nov:10,dec:11}; var p = s.replace(".", "").split('-'); return new Date(p[2], months[p[1].toLowerCase()], p[0]); } /** * Export events from spreadsheet to calendar */ function exportEvents() { var sheet = SpreadsheetApp.getActiveSheet(); var headerRows = 6; // Number of rows of header info (to skip) var range = sheet.getDataRange(); var data = range.getDisplayValues(); //var calId = "Your calendar Id"; // PRODUCTION var calId = "Your_calendar Id to test"; // TEST var cal = CalendarApp.getCalendarById(calId); //Logger.log(cal); //Logger.log(data.length); for (i=0; i<data.length; i++) { if (i < headerRows) continue; // Skip header row(s) if (data[i][0].length < 1) continue; // Skip if no content. var row = data[i]; Logger.log(row); var date = parseDate(row[0]); // First column //Logger.log(date); var title = row[1]; // Second column var tstart = new Date(); var s = row[2].split(":"); tstart.setHours(s[0]); tstart.setMinutes(s[1]); tstart.setSeconds(s[2]); tstart.setDate(date.getDate()); tstart.setMonth(date.getMonth()); tstart.setYear(date.getYear()); var tstop = new Date(); var e = row[3].split(":"); tstop.setHours(e[0]); tstop.setMinutes(e[1]); tstop.setSeconds(e[2]); 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, update it if it does var event = null; if (id.length > 0) { try { 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"), {description:desc,location:loc}); var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId(); var r = i + 1; var cell = sheet.getRange("G" + r); cell.setValue(newEvent); } else { Logger.log(event); event.setTitle(title); event.setDescription(desc); event.setLocation(loc); // event.setTime(tstart, tstop); // cannot setTime on eventSeries. // ... but we CAN set recurrence! var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1); event.setRecurrence(recurrence, tstart, tstop); } debugger; } } 

`