So I'm trying to delete all events that are older than a month from my calendars.
This script goes halfway; the logger prints out the name of the first event, but then I receive this error:
Exception: Action not allowed deleteOldEvents @ deleteOldEvents.gs.gs:13
The error points to ev.deleteEvent(); so something went wrong there.
Here is the full script:
function deleteOldEvents() {
var fromDate = new Date(2013, 0, 1, 0, 0, 0);
var lastMonth = new Date()
lastMonth.setMonth(lastMonth.getMonth() - 1)
var calendars = CalendarApp.getAllCalendars();
for (var i = 0; i < calendars.length; i ) {
var calendar = calendars[i];
var events = calendar.getEvents(fromDate, lastMonth);
for (var j = 0; j < events.length; j ) {
var ev = events[i];
Logger.log(ev.getTitle()); // show event name in log
ev.deleteEvent();
}
}
}
CodePudding user response:
Modification points:
- I think that
var ev = events[i];
should bevar ev = events[j];
. CalendarApp.getAllCalendars()
returns all calendars. In this case, the calendars of "contacts" and "holiday" are also included in the returned calendars. From your error message ofException: Action not allowed
, I guessed that the reason for your current issue might be due to this.
When these points are reflected in your script, how about the following modification?
Modified script:
function deleteOldEvents() {
var fromDate = new Date(2013, 0, 1, 0, 0, 0);
var lastMonth = new Date()
lastMonth.setMonth(lastMonth.getMonth() - 1)
var calendars = CalendarApp.getAllCalendars();
for (var i = 0; i < calendars.length; i ) {
var calendar = calendars[i];
var id = calendar.getId();
if (!["#contacts", "#holiday"].some(e => id.includes(e))) {
var events = calendar.getEvents(fromDate, lastMonth);
for (var j = 0; j < events.length; j ) {
var ev = events[j];
Logger.log(ev.getTitle()); // show event name in log
ev.deleteEvent();
}
}
}
}
For example,
CalendarApp.getAllCalendars()
includes the other user's calendars and you have no writer permission, how about modifying the above script as follows?From
if (!["#contacts", "#holiday"].some(e => id.includes(e))) {
To
if (!["#contacts", "#holiday"].some(e => id.includes(e)) && calendar.isOwnedByMe()) {
Or
From
var events = calendar.getEvents(fromDate, lastMonth); for (var j = 0; j < events.length; j ) { var ev = events[j]; Logger.log(ev.getTitle()); // show event name in log ev.deleteEvent(); }
To
try { var events = calendar.getEvents(fromDate, lastMonth); for (var j = 0; j < events.length; j ) { var ev = events[j]; Logger.log(ev.getTitle()); // show event name in log ev.deleteEvent(); } } catch(e) { console.log(e.message); }
Or, use just try-cath as follows.
function deleteOldEvents() { var fromDate = new Date(2013, 0, 1, 0, 0, 0); var lastMonth = new Date() lastMonth.setMonth(lastMonth.getMonth() - 1) var calendars = CalendarApp.getAllCalendars(); for (var i = 0; i < calendars.length; i ) { var calendar = calendars[i]; try { var events = calendar.getEvents(fromDate, lastMonth); for (var j = 0; j < events.length; j ) { var ev = events[j]; Logger.log(ev.getTitle()); // show event name in log ev.deleteEvent(); } } catch(e) { console.log(e.message); } } }
Reference:
Added:
If the number of events is large, I'm worried that the process cost might become high. If you want to reduce the process cost of the script, as another direction, how about the following sample script?
In this case, the batch requests method is used for deleting the events. So, before you run this script, please do the following flow.
1. Install a Google Apps Script library.
In this sample script, batch requests are used. But, the script for requesting batch requests might be a bit complicated. So, in this sample script, a Google Apps Script library is used.
Please install a Google Apps Script library of "BatchRequest". Ref You can see how to install it at here.
2. Enable Calendar API.
Please enable Calendar API at Advanced Google services.
3. Sample script:
function myFunction() {
// Retrieve calendar IDs of calendars with the owner or writer.
const calendarIds = Calendar.CalendarList.list({ maxResults: 250, minAccessRole: "writer" }).items.map(({ id }) => id);
// or const calendarIds = ["###calendarId of your sample Calendar###"];
// Search all events older than 1 month
const max = new Date();
max.setMonth(max.getMonth() - 1);
const timeMax = max.toISOString();
calendarIds.forEach(calendarId => {
const requests = Calendar.Events.list(calendarId, { maxResults: 2500, timeZone: "UTC", timeMax }).items.map(({ id }) => ({
method: "DELETE",
endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${id}`,
}));
const len = requests.length;
// Delete searched events.
if (len > 0) {
console.log(`${len} items are deleted.`);
BatchRequest.EDo({ batchPath: "batch/calendar/v3", requests });
console.log(`"${calendarId}" was done.`);
} else {
console.log(`"${calendarId}" has no delete events.`);
}
});
}
- In this sample script, from your showing script, for the Google Calendars that you have permission for writing, all events older than 1 month are retrieved. And, those events are deleted.
IMPORTANT:
When this script is run, the events are deleted. So, please be careful about this. I would like to recommend testing this script using a sample Calendar. At that time, please modify
const calendars = Calendar.CalendarList.list({ maxResults: 250, minAccessRole: "writer" }).items.map(({ id }) => id);
toconst calendarIds = ["###calendarId of your sample Calendar###"];
, and test it. By this, the specific calendar is used.In this sample script, as a simple script,
pageToken
is not used. So, the maximum number of Calendars is 250 and the maximum number of events is 2500. If your actual situation is more than theirs, please usepageToken
. By this, all events from all Calendars can be retrieved.
CodePudding user response:
Deleet Events occuring between 100 years ago and 1 month ago:
function deleteEventsOlderThanNMonths(n=1) {
let dt = new Date();
let edt = new Date(dt.getFullYear(),dt.getMonth() - n,dt.getDate());//a months ago
let sdt = new Date(dt.getFullYear() -100,dt.getMonth(),dt.getDate());//100 years ago
let cal = CalendarApp.getCalendarById(calid);
let evs = cal.getEvents(sdt,edt);
evs.forEach(ev => {ev.deleteEvent()})
}