如何在不复制其余事件的情况下更新单个事件
How to update a single event without duplicating the rest of the events
我目前正在使用应用程序脚本将我的 google sheet 同步到 google 日历。这个过程非常简单,我的脚本只从传播中获取日期和标题sheet,并在该日期创建一个带有该标题的全天活动。
我面临的问题是,如果我不小心输入了错误的日期,或者我必须更新价差内的日期之一sheet,运行 scheduleShifts 函数再次出现,所有事件被再次创建,这导致许多我不打算出现的重复事件。我正在尝试找到一种解决方案,以帮助更新事件的标题或删除事件并在传播 sheet 中的日期错误的情况下创建一个新事件。
更新传播中的数据sheet然后更新日历也不是很有效,因为如果必须更改相当多的日期或标题,则需要相当长的时间花一点时间在日历中更改它们。删除当前日历,创建一个新日历,将那个 id 复制到 spreadsheet 然后再次更新所有内容也会很麻烦。
这是我当前的代码:
function scheduleShifts()
{
/*Identify calendar*/
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange("C1").getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
/*Import data from the spreadsheet*/
var signups = spreadsheet.getRange("C4:F73").getValues();
/*Create events*/
for (x=0; x<signups.length; x++)
{
var shift = signups[x];
var title = shift[0];
var date = shift[3];
eventCal.createAllDayEvent(title, date);
}
}
/*Make the script shareable for others to use*/
function onOpen()
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('Sync to Calendar')
.addItem('Schedule shifts', 'scheduleShifts')
.addToUi();
}
我试图通过使用 Advanced Calendar Service 检索所有事件、将它们的标题推入数组然后使用 IndexOf 进行验证来避免重复事件。但是,我不确定如果标题保持不变而该事件的日期有更新,此方法是否有效。
我引用的执行此操作的代码:
var existingEvents=Calendar.Events.list(calendarId);
var eventArray=[];
existingEvents.items.forEach(function(e){eventArray.push(e.summary)});
for (x=0; x<signups.length; x++) {
var shift = signups [x];
var startTime = shift[0];
var endTime = shift[1];
var inspector = shift[2];
if(eventArray.indexOf(inspector)==-1){
eventCal.createEvent(inspector, startTime, endTime);
}else{
Logger.log('event exists already');
}
}
如果有人需要更多信息,请随时在评论中提问,我们将不胜感激。
- 您已经开发了一个脚本来使用来自 sheet 的数据创建事件。
- 您希望能够更新以前创建的事件,同时避免创建重复项。
第 1 步。避免重复:
为了避免创建重复项,您可以让脚本在创建每个事件后写入相应的 eventId
。这样,下次脚本运行时,它可以检查 eventId
是否已填充(在这种情况下事件已经存在),并且仅在事件不存在时才创建事件。它可能是这样的(在此示例中,eventIds
被写入 G 列):
function scheduleShifts() {
const spreadsheet = SpreadsheetApp.getActiveSheet();
const calendarId = spreadsheet.getRange("C1").getValue();
const eventCal = CalendarApp.getCalendarById(calendarId);
const signups = spreadsheet.getRange("C4:G7").getValues();
for (let x = 0; x < signups.length; x++) {
const shift = signups[x];
const title = shift[0];
const date = shift[3];
const eventId = shift[4];
if (eventId == "") { // Check the event doesn't exist
const newEvent = eventCal.createAllDayEvent(title, date);
const newEventId = newEvent.getId();
spreadsheet.getRange(4 + x, 7).setValue(newEventId); // Write new eventId to col G
}
}
}
步骤 2. 更新事件:
关于更新过程,我建议你install an onEdit trigger, either manually or programmatically. This this action requires authorization, a simple onEdit
trigger would not work here (see Restrictions)。
这样,您可以使用 event object to only update the event corresponding to the row that was edited, thus avoiding having to update all events every time, which would make the process very inefficient. The update process itself would consist on calling setTitle and setAllDayDate。
onEdit
触发器触发的函数可能是这样的:
function updateEvent(e) {
var editedRow = e.range.getRow();
var editedData = e.source.getActiveSheet().getRange(editedRow, 3, 1, 5).getValues()[0];
var eventId = editedData[4];
try {
var event = CalendarApp.getEventById(eventId);
event.setTitle(editedData[0]);
event.setAllDayDate(editedData[3]);
} catch(err) {
console.log("There was a problem updating the event. This event might not exist yet.");
}
}
备注:
- 如果事件数量可能不同,您可能不想手动设置范围 (
C4:G73
)。您可以使用 getLastRow() 之类的方法使此范围动态化,基于传播sheet 内容。
- 这里用到的
eventId
,对应Class CalendarEvent, are not identical to the API Event resource. Take this into account in case you use the Advanced Service.
我目前正在使用应用程序脚本将我的 google sheet 同步到 google 日历。这个过程非常简单,我的脚本只从传播中获取日期和标题sheet,并在该日期创建一个带有该标题的全天活动。
我面临的问题是,如果我不小心输入了错误的日期,或者我必须更新价差内的日期之一sheet,运行 scheduleShifts 函数再次出现,所有事件被再次创建,这导致许多我不打算出现的重复事件。我正在尝试找到一种解决方案,以帮助更新事件的标题或删除事件并在传播 sheet 中的日期错误的情况下创建一个新事件。
更新传播中的数据sheet然后更新日历也不是很有效,因为如果必须更改相当多的日期或标题,则需要相当长的时间花一点时间在日历中更改它们。删除当前日历,创建一个新日历,将那个 id 复制到 spreadsheet 然后再次更新所有内容也会很麻烦。
这是我当前的代码:
function scheduleShifts()
{
/*Identify calendar*/
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange("C1").getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
/*Import data from the spreadsheet*/
var signups = spreadsheet.getRange("C4:F73").getValues();
/*Create events*/
for (x=0; x<signups.length; x++)
{
var shift = signups[x];
var title = shift[0];
var date = shift[3];
eventCal.createAllDayEvent(title, date);
}
}
/*Make the script shareable for others to use*/
function onOpen()
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('Sync to Calendar')
.addItem('Schedule shifts', 'scheduleShifts')
.addToUi();
}
我试图通过使用 Advanced Calendar Service 检索所有事件、将它们的标题推入数组然后使用 IndexOf 进行验证来避免重复事件。但是,我不确定如果标题保持不变而该事件的日期有更新,此方法是否有效。
我引用的执行此操作的代码:
var existingEvents=Calendar.Events.list(calendarId);
var eventArray=[];
existingEvents.items.forEach(function(e){eventArray.push(e.summary)});
for (x=0; x<signups.length; x++) {
var shift = signups [x];
var startTime = shift[0];
var endTime = shift[1];
var inspector = shift[2];
if(eventArray.indexOf(inspector)==-1){
eventCal.createEvent(inspector, startTime, endTime);
}else{
Logger.log('event exists already');
}
}
如果有人需要更多信息,请随时在评论中提问,我们将不胜感激。
- 您已经开发了一个脚本来使用来自 sheet 的数据创建事件。
- 您希望能够更新以前创建的事件,同时避免创建重复项。
第 1 步。避免重复:
为了避免创建重复项,您可以让脚本在创建每个事件后写入相应的 eventId
。这样,下次脚本运行时,它可以检查 eventId
是否已填充(在这种情况下事件已经存在),并且仅在事件不存在时才创建事件。它可能是这样的(在此示例中,eventIds
被写入 G 列):
function scheduleShifts() {
const spreadsheet = SpreadsheetApp.getActiveSheet();
const calendarId = spreadsheet.getRange("C1").getValue();
const eventCal = CalendarApp.getCalendarById(calendarId);
const signups = spreadsheet.getRange("C4:G7").getValues();
for (let x = 0; x < signups.length; x++) {
const shift = signups[x];
const title = shift[0];
const date = shift[3];
const eventId = shift[4];
if (eventId == "") { // Check the event doesn't exist
const newEvent = eventCal.createAllDayEvent(title, date);
const newEventId = newEvent.getId();
spreadsheet.getRange(4 + x, 7).setValue(newEventId); // Write new eventId to col G
}
}
}
步骤 2. 更新事件:
关于更新过程,我建议你install an onEdit trigger, either manually or programmatically. This this action requires authorization, a simple onEdit
trigger would not work here (see Restrictions)。
这样,您可以使用 event object to only update the event corresponding to the row that was edited, thus avoiding having to update all events every time, which would make the process very inefficient. The update process itself would consist on calling setTitle and setAllDayDate。
onEdit
触发器触发的函数可能是这样的:
function updateEvent(e) {
var editedRow = e.range.getRow();
var editedData = e.source.getActiveSheet().getRange(editedRow, 3, 1, 5).getValues()[0];
var eventId = editedData[4];
try {
var event = CalendarApp.getEventById(eventId);
event.setTitle(editedData[0]);
event.setAllDayDate(editedData[3]);
} catch(err) {
console.log("There was a problem updating the event. This event might not exist yet.");
}
}
备注:
- 如果事件数量可能不同,您可能不想手动设置范围 (
C4:G73
)。您可以使用 getLastRow() 之类的方法使此范围动态化,基于传播sheet 内容。 - 这里用到的
eventId
,对应Class CalendarEvent, are not identical to the API Event resource. Take this into account in case you use the Advanced Service.