Google Apps Script多日历事件获取异常:仅首个日历能取到事件
问题排查与修复
你的脚本有两个关键问题导致仅第一个日历能获取到事件:
1. 日历ID数组处理错误
sheetsoptions.getRange("A5:A6").getValues()返回的是二维数组(比如[["cal1-id"], ["cal2-id"]]),但你直接用id_cal[j]作为日历ID传入getCalendarById,实际传入的是一个数组而非字符串,导致无法正确获取后续日历实例,自然拿不到事件。
2. 变量名冲突覆盖时间范围
在内部循环里,你重新定义了start_time和end_time来存储事件的起止时间,这会直接覆盖外层定义的全局时间范围变量。当处理第二个日历的时候,start_time已经变成了第一个日历最后一个事件的开始时间,而非你最初从表格A2、B2获取的时间范围,导致后续日历查询的时间范围错误,返回空结果。
修复后的完整代码
function getEvents() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getSheetByName("Sheet1"); var sheetsoptions = ss.getSheetByName("Options"); // 保留全局时间范围变量,避免被覆盖 var globalStartTime = sheet.getRange("A2").getValue(); var globalEndTime = sheet.getRange("B2").getValue(); // 将二维数组转为一维字符串数组,过滤空值 var idCalList = sheetsoptions.getRange("A5:A6").getValues() .map(row => row[0]) // 提取每行的第一个元素(日历ID字符串) .filter(id => id !== ""); // 过滤空ID var cellEvents = 5; for (var j = 0; j < idCalList.length; j++) { var calId = idCalList[j]; var cal = CalendarApp.getCalendarById(calId); // 用全局时间范围查询事件 var events = cal.getEvents(new Date(globalStartTime), new Date(globalEndTime)); for (var i = 0; i < events.length; i++) { var title = events[i].getTitle(); // 换变量名,避免覆盖全局时间 var eventStartTime = events[i].getStartTime(); var eventEndTime = events[i].getEndTime(); var loc = events[i].getLocation(); var des = events[i].getDescription(); var vis = events[i].getVisibility(); // 批量写入提升性能(可选,但比逐个setValue高效) sheet.getRange(cellEvents, 1, 1, 6).setValues([[title, eventStartTime, eventEndTime, loc, des, vis]]); cellEvents++; } } Logger.log("Events have been added to the Spreadsheet"); }
额外优化说明
- 新增
map和filter处理日历ID数组,确保拿到的是纯字符串列表且无空值,无需手动判断空值break。 - 把逐个
setValue改成批量setValues,减少与表格的交互次数,提升脚本运行效率(Google Apps Script中IO操作是性能瓶颈)。 - 重命名事件相关的时间变量,彻底避免变量名冲突。
内容的提问来源于stack exchange,提问作者Luca Ridolfo
相关产品推荐
相关产品推荐

