如何在 Google Sheet 中更新单元格时自动更新或自动删除 Google 日历事件,事件创建自?
How to Auto-Update or Auto-Delete Google Calendar Events when Cells are Updated in the Google Sheet the Event is Created From From?
我已经查看了看似相似问题的其他答案,但尚未找到解决方案。我目前正在使用下面的脚本(感谢很多帮助!)从工作簿中的多个工作表自动填充事件;然而,我也希望实现:
- 如果 C4:F24 中预先存在的数据发生变化(没有创建重复事件),日历中的事件会自动更新
- 如果单元格 E4:F24 中的数据被删除,事件也会删除。
我已经启用了“onEdit”触发器;但是,它不允许上述任何一种情况。非常感谢任何帮助!我已经更新了脚本以反映我当前正在测试的内容。此脚本 returns 安装的“OnEdit”触发器运行时出现以下错误:ReferenceError: e is not defined
在 simpleSheetsToCalendar(代码:4:17)
function simpleSheetsToCalendar() {
var sheetNames = ["Oct-08-2021 | Plan", "Oct-15-2021 | Plan"]; // Please set the sheet names you want to use.
var calendarId = "myCalendar"; // Please set your calendar ID.
var {range} = e;
var sheet = range.getSheet();
if (!(sheetNames.includes(sheet.getSheetName()) && range.rowStart >= 4 && range.rowEnd <= 24 && range.columnStart >= 3 && range.columnStart <= 6)) return;
// 1. Retrieve all events from the Calendar and create an object for checking the duplicated titles.
var events = [];
var pageToken = "";
do {
var res = Calendar.Events.list(calendarId, {maxResults: 2500, fields: "nextPageToken,items(id,summary,start(dateTime),end(dateTime))", pageToken});
events = events.concat(res.items);
pageToken = res.nextPageToken;
} while(pageToken);
var obj = events.reduce((o, e) => Object.assign(o, {[e.summary]: e}), {});
// 2. Retrieve sheets from a Google Spreadsheet and retrieve the values from "C4:F24", and create an object for creating new events, deleting events and updating events.
var values = sheet.getRange("C4:F24").getValues().reduce((o, [title,,startTime,endTime]) => {
if (!obj[title] && title && startTime && endTime && !o[title]) {
o.add[title] = {startTime, endTime};
} else if (obj[title] && title && startTime && endTime) {
if (new Date(obj[title].start.dateTime).getTime() != startTime.getTime() || new Date(obj[title].end.dateTime).getTime() != endTime.getTime()) {
obj[title].start.dateTime = startTime;
obj[title].end.dateTime = endTime;
o.modify.push(obj[title]);
}
} else if (obj[title] && title && !startTime && !endTime) {
o.remove.push(obj[title].id);
}
return o;
}, {add: {}, remove: [], modify: []});
// 3. Create new events.
var eventCal = CalendarApp.getCalendarById(calendarId);
var ar = Object.entries(values.add);
if (ar.length > 0) {
ar.forEach(([title, {startTime, endTime}]) => eventCal.createEvent(title, startTime, endTime));
}
// 4. Modify events.
if (values.modify.length > 0) {
values.modify.forEach(({id, start, end}) => eventCal.getEventById(id).setTime(start.dateTime, end.dateTime));
}
// 5. Delete events.
if (values.remove.length > 0) {
values.remove.forEach(id => eventCal.getEventById(id).deleteEvent());
}
}
根据您的后续问题和您的回复,
- the events auto update in the calendar if pre-existing data in C4:F24 is changed (without a duplicate event being created)
- the event deletes if data in cells E4:F24 is deleted.
针对你的情况,我是这样理解的
- 您想在编辑规范 sheet 的单元格“C4:C24”时自动执行脚本。
- 当列“E”和“F”发生变化而“C”列有值时,您想更改事件的开始和结束时间。
- 当单元格“E4:F24”被删除而单元格“C4:C24”未被删除时,您想从日历中删除事件。
这样的话,下面的流程如何?
- 从日历中检索所有事件并创建一个 object 用于检查重复的标题。
- 从 Google Spreadsheet 中检索 sheets 并从“C4:F24”检索值,并创建一个 object 用于创建新事件,删除事件和更新事件。
- 找到新标题后,创建新事件。
- 当标题存在且开始和结束时间发生变化时,修改事件。
- 当标题存在且删除开始和结束时间时,删除事件。
而且,为了执行脚本,在这种情况下,使用了可安装的 OnEdit 触发器。因为使用了 Calendar API。当此流程反映在您的脚本中时,它会变成如下。
修改后的脚本:
在此示例脚本中,为了检索日历事件的所有标题,使用了日历 API。所以在你使用这个脚本之前,please enable Calendar API at Advanced Google services。并且,请设置 sheetNames
和 calendarId
.
此外,please install the installable OnEdit trigger 到函数 simpleSheetsToCalendar
。
function simpleSheetsToCalendar(e) {
var sheetNames = ["Sheet1", "Sheet2",,,]; // Please set the sheet names you want to use.
var calendarId = "calendarId"; // Please set your calendar ID.
var {range} = e;
var sheet = range.getSheet();
if (!(sheetNames.includes(sheet.getSheetName()) && range.rowStart >= 4 && range.rowEnd <= 24 && range.columnStart >= 3 && range.columnStart <= 6)) return;
// 1. Retrieve all events from the Calendar and create an object for checking the duplicated titles.
var events = [];
var pageToken = "";
do {
var res = Calendar.Events.list(calendarId, {maxResults: 2500, fields: "nextPageToken,items(id,summary,start(dateTime),end(dateTime))", pageToken});
events = events.concat(res.items);
pageToken = res.nextPageToken;
} while(pageToken);
var obj = events.reduce((o, e) => Object.assign(o, {[e.summary]: e}), {});
// 2. Retrieve sheets from a Google Spreadsheet and retrieve the values from "C4:F24", and create an object for creating new events, deleting events and updating events.
var values = sheet.getRange("C4:F24").getValues().reduce((o, [title,,startTime,endTime]) => {
if (!obj[title] && title && startTime && endTime && !o[title]) {
o.add[title] = {startTime, endTime};
} else if (obj[title] && title && startTime && endTime) {
if (new Date(obj[title].start.dateTime).getTime() != startTime.getTime() || new Date(obj[title].end.dateTime).getTime() != endTime.getTime()) {
obj[title].start.dateTime = startTime;
obj[title].end.dateTime = endTime;
o.modify.push(obj[title]);
}
} else if (obj[title] && title && !startTime && !endTime) {
o.remove.push(obj[title].id);
}
return o;
}, {add: {}, remove: [], modify: []});
// 3. Create new events.
var eventCal = CalendarApp.getCalendarById(calendarId);
var ar = Object.entries(values.add);
if (ar.length > 0) {
ar.forEach(([title, {startTime, endTime}]) => eventCal.createEvent(title, startTime, endTime));
}
// 4. Modify events.
if (values.modify.length > 0) {
values.modify.forEach(({id, start, end}) => eventCal.getEventById(id).setTime(start.dateTime, end.dateTime));
}
// 5. Delete events.
if (values.remove.length > 0) {
values.remove.forEach(id => eventCal.getEventById(id).deleteEvent());
}
}
- 当此脚本为运行时,更新和删除的事件将从Calendar 的所有事件列表和Spread 的值中检索sheet。并且,当“E”和“F”列的值发生变化时,“C”列标题的事件也会更新。当“E”和“F”列的值为空时,删除“C”列标题的事件。
注:
在这个答案中,从你的问题来看,它假设当列“E”和“F”的值被删除时,列“C”的标题的值是存在的。请注意这一点。
在这个修改后的脚本中,当指定sheets的单元格“C4:F24”时,脚本会自动执行。所以当你直接运行这个函数的时候,就会出现Cannot destructure property 'range' of 'e' as it is undefined.
这样的错误。当您 运行 脚本时,请编辑 sheetNames
的特定 sheet 的单元格“C4:F24”。请注意这一点。
请确认您的 sheet 姓名。请注意这一点。
参考文献:
我已经查看了看似相似问题的其他答案,但尚未找到解决方案。我目前正在使用下面的脚本(感谢很多帮助!)从工作簿中的多个工作表自动填充事件;然而,我也希望实现:
- 如果 C4:F24 中预先存在的数据发生变化(没有创建重复事件),日历中的事件会自动更新
- 如果单元格 E4:F24 中的数据被删除,事件也会删除。
我已经启用了“onEdit”触发器;但是,它不允许上述任何一种情况。非常感谢任何帮助!我已经更新了脚本以反映我当前正在测试的内容。此脚本 returns 安装的“OnEdit”触发器运行时出现以下错误:ReferenceError: e is not defined 在 simpleSheetsToCalendar(代码:4:17)
function simpleSheetsToCalendar() {
var sheetNames = ["Oct-08-2021 | Plan", "Oct-15-2021 | Plan"]; // Please set the sheet names you want to use.
var calendarId = "myCalendar"; // Please set your calendar ID.
var {range} = e;
var sheet = range.getSheet();
if (!(sheetNames.includes(sheet.getSheetName()) && range.rowStart >= 4 && range.rowEnd <= 24 && range.columnStart >= 3 && range.columnStart <= 6)) return;
// 1. Retrieve all events from the Calendar and create an object for checking the duplicated titles.
var events = [];
var pageToken = "";
do {
var res = Calendar.Events.list(calendarId, {maxResults: 2500, fields: "nextPageToken,items(id,summary,start(dateTime),end(dateTime))", pageToken});
events = events.concat(res.items);
pageToken = res.nextPageToken;
} while(pageToken);
var obj = events.reduce((o, e) => Object.assign(o, {[e.summary]: e}), {});
// 2. Retrieve sheets from a Google Spreadsheet and retrieve the values from "C4:F24", and create an object for creating new events, deleting events and updating events.
var values = sheet.getRange("C4:F24").getValues().reduce((o, [title,,startTime,endTime]) => {
if (!obj[title] && title && startTime && endTime && !o[title]) {
o.add[title] = {startTime, endTime};
} else if (obj[title] && title && startTime && endTime) {
if (new Date(obj[title].start.dateTime).getTime() != startTime.getTime() || new Date(obj[title].end.dateTime).getTime() != endTime.getTime()) {
obj[title].start.dateTime = startTime;
obj[title].end.dateTime = endTime;
o.modify.push(obj[title]);
}
} else if (obj[title] && title && !startTime && !endTime) {
o.remove.push(obj[title].id);
}
return o;
}, {add: {}, remove: [], modify: []});
// 3. Create new events.
var eventCal = CalendarApp.getCalendarById(calendarId);
var ar = Object.entries(values.add);
if (ar.length > 0) {
ar.forEach(([title, {startTime, endTime}]) => eventCal.createEvent(title, startTime, endTime));
}
// 4. Modify events.
if (values.modify.length > 0) {
values.modify.forEach(({id, start, end}) => eventCal.getEventById(id).setTime(start.dateTime, end.dateTime));
}
// 5. Delete events.
if (values.remove.length > 0) {
values.remove.forEach(id => eventCal.getEventById(id).deleteEvent());
}
}
根据您的后续问题和您的回复,
- the events auto update in the calendar if pre-existing data in C4:F24 is changed (without a duplicate event being created)
- the event deletes if data in cells E4:F24 is deleted.
针对你的情况,我是这样理解的
- 您想在编辑规范 sheet 的单元格“C4:C24”时自动执行脚本。
- 当列“E”和“F”发生变化而“C”列有值时,您想更改事件的开始和结束时间。
- 当单元格“E4:F24”被删除而单元格“C4:C24”未被删除时,您想从日历中删除事件。
这样的话,下面的流程如何?
- 从日历中检索所有事件并创建一个 object 用于检查重复的标题。
- 从 Google Spreadsheet 中检索 sheets 并从“C4:F24”检索值,并创建一个 object 用于创建新事件,删除事件和更新事件。
- 找到新标题后,创建新事件。
- 当标题存在且开始和结束时间发生变化时,修改事件。
- 当标题存在且删除开始和结束时间时,删除事件。
而且,为了执行脚本,在这种情况下,使用了可安装的 OnEdit 触发器。因为使用了 Calendar API。当此流程反映在您的脚本中时,它会变成如下。
修改后的脚本:
在此示例脚本中,为了检索日历事件的所有标题,使用了日历 API。所以在你使用这个脚本之前,please enable Calendar API at Advanced Google services。并且,请设置 sheetNames
和 calendarId
.
此外,please install the installable OnEdit trigger 到函数 simpleSheetsToCalendar
。
function simpleSheetsToCalendar(e) {
var sheetNames = ["Sheet1", "Sheet2",,,]; // Please set the sheet names you want to use.
var calendarId = "calendarId"; // Please set your calendar ID.
var {range} = e;
var sheet = range.getSheet();
if (!(sheetNames.includes(sheet.getSheetName()) && range.rowStart >= 4 && range.rowEnd <= 24 && range.columnStart >= 3 && range.columnStart <= 6)) return;
// 1. Retrieve all events from the Calendar and create an object for checking the duplicated titles.
var events = [];
var pageToken = "";
do {
var res = Calendar.Events.list(calendarId, {maxResults: 2500, fields: "nextPageToken,items(id,summary,start(dateTime),end(dateTime))", pageToken});
events = events.concat(res.items);
pageToken = res.nextPageToken;
} while(pageToken);
var obj = events.reduce((o, e) => Object.assign(o, {[e.summary]: e}), {});
// 2. Retrieve sheets from a Google Spreadsheet and retrieve the values from "C4:F24", and create an object for creating new events, deleting events and updating events.
var values = sheet.getRange("C4:F24").getValues().reduce((o, [title,,startTime,endTime]) => {
if (!obj[title] && title && startTime && endTime && !o[title]) {
o.add[title] = {startTime, endTime};
} else if (obj[title] && title && startTime && endTime) {
if (new Date(obj[title].start.dateTime).getTime() != startTime.getTime() || new Date(obj[title].end.dateTime).getTime() != endTime.getTime()) {
obj[title].start.dateTime = startTime;
obj[title].end.dateTime = endTime;
o.modify.push(obj[title]);
}
} else if (obj[title] && title && !startTime && !endTime) {
o.remove.push(obj[title].id);
}
return o;
}, {add: {}, remove: [], modify: []});
// 3. Create new events.
var eventCal = CalendarApp.getCalendarById(calendarId);
var ar = Object.entries(values.add);
if (ar.length > 0) {
ar.forEach(([title, {startTime, endTime}]) => eventCal.createEvent(title, startTime, endTime));
}
// 4. Modify events.
if (values.modify.length > 0) {
values.modify.forEach(({id, start, end}) => eventCal.getEventById(id).setTime(start.dateTime, end.dateTime));
}
// 5. Delete events.
if (values.remove.length > 0) {
values.remove.forEach(id => eventCal.getEventById(id).deleteEvent());
}
}
- 当此脚本为运行时,更新和删除的事件将从Calendar 的所有事件列表和Spread 的值中检索sheet。并且,当“E”和“F”列的值发生变化时,“C”列标题的事件也会更新。当“E”和“F”列的值为空时,删除“C”列标题的事件。
注:
在这个答案中,从你的问题来看,它假设当列“E”和“F”的值被删除时,列“C”的标题的值是存在的。请注意这一点。
在这个修改后的脚本中,当指定sheets的单元格“C4:F24”时,脚本会自动执行。所以当你直接运行这个函数的时候,就会出现
Cannot destructure property 'range' of 'e' as it is undefined.
这样的错误。当您 运行 脚本时,请编辑sheetNames
的特定 sheet 的单元格“C4:F24”。请注意这一点。请确认您的 sheet 姓名。请注意这一点。