如何通过高级日历服务与Calendar API获取重复事件实例的Event ID
解决重复事件单个实例ID获取问题
你已经准确判断了核心问题:CalendarApp的getId()只会返回重复事件系列的ICAL UID,而非单个实例的唯一ID。要获取单个实例的独立ID,必须使用高级Calendar API,你已完成API启用的前置步骤,接下来直接修改updateEventsGeneric函数即可,核心是用Calendar.Events.list替代CalendarApp的事件获取方法,并通过关键参数展开重复事件为单个实例。
修改后的完整脚本
function updateEventsGeneric() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getSheetByName("EventsRange"); var calId = "你的日历ID"; // 替换为实际的id_cal值 var date = new Date(); var day = date.getDate(); var month = date.getMonth() + 1; var year = date.getFullYear(); // 构造当天精确时间范围:从当天0点到次日0点 var timeMin = new Date(year, month - 1, day).toISOString(); var timeMax = new Date(year, month - 1, day + 1).toISOString(); // 调用Calendar API获取当天所有单个事件实例(含重复事件的独立实例) var events = Calendar.Events.list(calId, { timeMin: timeMin, timeMax: timeMax, singleEvents: true, // 关键参数:将重复事件系列拆分为单个实例 orderBy: 'startTime' }).items; var row = sheet.getLastRow() + 1; var values = []; for (var i = 0; i < events.length; i++) { var event = events[i]; var title = event.summary || ""; var clientName = ''; var event_date = new Date(event.start.dateTime).toDateString(); var employEmail = []; var clientEmail = []; var start_time = new Date(event.start.dateTime); var end_time = new Date(event.end.dateTime); var loc = event.location || ""; var event_id = event.id; // 此处获取的是单个实例的唯一ID // 处理嘉宾列表(确保employees变量已提前定义) var guestList = event.attendees || []; for (var j = 0; j < guestList.length; j++) { var email = guestList[j].email; employees.some(({emailad}) => emailad === email) ? employEmail.push(email) : clientEmail.push(email); } // 注意:formulaString需自行定义,原脚本未提供该变量的定义逻辑 values.push([ title, formulaString || "", event_date, employEmail.join(","), // 数组转字符串避免表格格式异常 clientEmail.join(","), start_time, end_time, `=G${i + row}-F${i + row}`, loc, event_id ]); } if (values.length > 0) { sheet.getRange(row, 1, values.length, values[0].length).setValues(values); sheet.getRange(row, 6, values.length, 2).setNumberFormat("MM/dd/yyyy hh:mm:ss am/pm"); sheet.getRange(row, 8, values.length, 1).setNumberFormat("[hh]:mm:ss"); } } // 保留原listEventsFromOneCalendar函数(如需继续使用) function listEventsFromOneCalendar() { var sheet = SpreadsheetApp.getActiveSpreadsheet() .getSheetByName("ExistingEvents"); var source = "testemail@group.calendar.google.com"; var srcCalId = Calendar.Calendars.get(source).id; var syncdays = 30; var now = new Date(); var min = new Date(now.getFullYear(), now.getMonth(), now.getDate()); var max = new Date(now.getFullYear(), now.getMonth(), now.getDate() + syncdays); var srcEvents = Calendar.Events.list(srcCalId, { timeMin: min.toISOString(), timeMax: max.toISOString(), singleEvents: true, orderBy: 'startTime', }).items; var output = []; srcEvents.forEach(function(e){ var event = []; event.push(e.summary || ""); event.push(e.start.dateTime || ""); event.push(e.end.dateTime || ""); event.push(e.id || ""); event.push(e.location || ""); output.push(event); }); var header = [ "标题/主题", "开始时间", "结束时间", "事件ID", "地点" ]; output.unshift(header); sheet.clearContents(); sheet.getRange(1, 1, output.length, header.length) .setValues(output); }
关键修改说明
- 事件获取逻辑替换:用
Calendar.Events.list替代CalendarApp.getEventsForDay,通过singleEvents: true参数强制展开重复事件系列,返回每个独立实例的详细数据。 - 时间范围精确化:构造
timeMin和timeMax确保仅获取当天的事件,避免范围偏差。 - 字段映射调整:Calendar API返回的事件字段与CalendarApp不同,例如标题对应
summary、时间对应start.dateTime,需对应调整。 - 嘉宾列表补充:从事件的
attendees属性获取嘉宾信息,修正原脚本中未定义guestList的问题。 - 格式兼容处理:将邮箱数组转为逗号分隔的字符串,避免写入表格时出现格式异常。
注意事项
- 确保已在脚本编辑器中启用高级Calendar服务:点击「资源」→「高级Google服务」,找到Calendar API并启用。
- 将
calId替换为你的实际日历ID(对应原脚本中的id_cal变量)。 - 原脚本中的
formulaString和employees变量需提前定义,否则会触发报错。
内容的提问来源于stack exchange,提问作者Benjamin
相关产品推荐
相关产品推荐

