Delete a bunch of events at once

We have a user with a dozens of copies of an appointment in his calender. It would be nice to be able to delete all these events at once. Deleting it one by one would take him hours. Is it possible to delete a bunch of events at once, either via the browser or even with a script or via the database?

Unfortunately, I’m not aware about such a function. It might be possible that things will change with the publishing of the Calendar app v2.0 but that hasn’t confirmed yet. In the meantime I would recommend to use Thunderbird/Lightning to subscribe to that calendar and delete the events there.

Thank you for the feedback. TB/Lightning is already the way we go.

Though it’s a bit tricky, you could try to delete the calendar objects directly in the database. The events are stored in at least two parts:

  1. in oc_calendarobjects_props
  2. in oc_calendarobjects

In my case I first allocated the calendar ID I wanted to delete from looking at table oc_calenders. It turned out to be ID 19

Then I crafted a query for the oc_calendarobjects_props like:

SELECT objectid FROM oc_calendarobjects_props WHERE calendarid = 19

In addition you can add other criteria there as well. In my case

SELECT objectid FROM oc_calendarobjects_props WHERE calendarid = 19 and id>= 8995

this gave me all the recently added events to the calendar with ID 19

Now comes the tricky part. You want to delete all the items from oc_calendarobjects which relate to any of these object IDs.

This can be done with the “where exists” statement like

DELETE FROM oc_calendarobjects
WHERE EXISTS (SELECT *
              FROM oc_calendarobjects_props
              WHERE oc_calendarobjects_props.objectid = oc_calendarobjects.id
                AND oc_calendarobjects_props.calendarid = 19
                AND oc_calendarobjects_props.id >= 8895
)

As I have done this query already some hours ago, I’m not sure if the above syntax is correct. It’s just an idea for future needs.

1 Like

I have the same problem here. I don’t know why. One calendar event has been duplicates 915 times im my calendar. Is the possible solution in this thread with NC 27 up-to-date or is there a possible better solution?

Finally I solved it with some python code and the DAV Api. Maybe it is useful for someone of you.

import caldav
from icalendar import Calendar
from datetime import datetime, timedelta

# specify your own url, username and password
url = 'https://nextcloud.your_domain.com/remote.php/dav/'
username = 'your_username'
password = 'your_password'

event_summary = input('Enter the summary of events to delete: ').strip()  # New line

client = caldav.DAVClient(url=url, username=username, password=password)
principal = client.principal()
calendars = principal.calendars()

if calendars:
    print('Calendars found:', len(calendars))
    calendar = calendars[0]

    print('Using calendar:', calendar)

    print('Starting search for events...')

    # provide start and end dates as datetime objects modify the time cause it takes possibly hours
    start_date = datetime(1900, 1, 1)
    end_date = datetime(3000, 1, 1)

    events = calendar.date_search(
        start=start_date, 
        end=end_date
    )

    delete_list = []

    # loop through events, keeping track of total and matches with count and hits
    count = 0
    hits = 0
    for event in events:
        count += 1
        ical = Calendar.from_ical(event.data)

        for component in ical.walk():
            if component.name == 'VEVENT':
                if component.get('summary') == event_summary:  # Modified line
                    hits += 1
                    print('Found', component.get('summary'), 'on', component.get('dtstart').dt)
                    delete_list.append(event)
        print(f'Searched {count} events, found {hits} matches.')

    # printing events to be deleted
    print('A total of', len(delete_list), 'events will be deleted.')
    for idx, event in enumerate(delete_list, start=1):
        print(f'{idx}. {event.instance.vevent.summary.value} - {event.instance.vevent.dtstart.value}')

    input_var = input("Are you sure you want to delete these events? Type 'yes' to proceed: ")

    if input_var.lower() == 'yes':
        for event in delete_list:
            event.delete()
        print('Events deleted.')
    else:
        print('Events not deleted.')

else:
    print('No calendars were found.')

2 Likes