```
function syncExpiryEventsToCalendar() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
// ✅ 指定日曆(建議)
var calendar = CalendarApp.getCalendarById("YourID");
// 若要用預設日曆,改為:var calendar = CalendarApp.getDefaultCalendar();
// 欄位對應(含 Timestamp)
// 0: Timestamp(不用)
// 1: 品名
// 2: 保存期限
// 3: 提前提醒天數
// 4: 備註
// 5: 事件ID(程式自動填)
// 1) 收集目前表內的事件ID
var sheetEventIds = {};
for (var i = 1; i < data.length; i++) {
var idInSheet = data[i][5];
if (idInSheet) sheetEventIds[idInSheet] = true;
}
// 2) 新增或更新事件
for (var i = 1; i < data.length; i++) {
var foodName = data[i][1];
var rawDate = data[i][2];
var remindDays = parseInt(data[i][3], 10) || 0;
var note = data[i][4] || "";
var eventId = data[i][5];
if (!foodName || !rawDate) continue;
// 轉成 Date,並鎖在當地午夜,避免時區偏移
var d = new Date(rawDate);
if (isNaN(d)) continue;
var expiryDate = new Date(d.getFullYear(), d.getMonth(), d.getDate());
var eventTitle = foodName + "到期";
var startTime = expiryDate;
var endTime = new Date(expiryDate.getTime() + 60 * 60 * 1000); // 1小時事件
var event = null;
// 先用事件ID找舊事件
if (eventId) {
try { event = calendar.getEventById(eventId); } catch (e) { event = null; }
}
// 若找到 → 不管改了哪個欄位,都直接更新事件
if (event) {
// 更新標題、描述、時間
event.setTitle(eventTitle);
event.setDescription(note);
event.setTime(startTime, endTime);
// 先清空提醒,再依「提前提醒天數」重設
event.removeAllReminders();
if (remindDays > 0) {
event.addPopupReminder(remindDays * 24 * 60); // 分鐘
}
// 標記此事件仍存在於表內,供後面清理用
sheetEventIds[event.getId()] = true;
continue; // 已更新完畢,跳過「新建」邏輯
}
// 不存在就新建
if (!event) {
var newEvent = calendar.createEvent(eventTitle, startTime, endTime, { description: note });
if (remindDays > 0) newEvent.addPopupReminder(remindDays * 24 * 60);
// 寫回事件ID到第 6 欄
sheet.getRange(i + 1, 6).setValue(newEvent.getId());
sheetEventIds[newEvent.getId()] = true;
}
}
// 3) 清理:刪掉已從表中移除的事件(只掃未來90天,且標題以「到期」結尾的)
var today = new Date();
var future = new Date(); future.setDate(today.getDate()+360);
var allEvents = calendar.getEvents(today, future);
for (var j = 0; j < allEvents.length; j++) {
var ev = allEvents[j];
var evId = ev.getId();
if (ev.getTitle().endsWith("到期") && !sheetEventIds[evId]) {
ev.deleteEvent();
}
}
}
```