I need help with Calendar events lists

I’m new to Calendar in AppleScript. In spite of tutorials and other posts, clearly I am not grasping something in the basic structure of Calendar:

1. I create an event.

2. I run this snippet:


tell application "Calendar"
		return every event of calendar "Home"
		--delete every event of calendar "Home"-- whose description is "TEST"
end tell

and the result is the expected events list for “Home”.

3. I run this snippet:

tell application "Calendar"
		--return every event of calendar "Home
		delete every event of calendar "Home"-- whose description is "TEST"
end tell

4. Run the first snippet again:

tell application "Calendar"
		return every event of calendar "Home"
		--delete every event of calendar "Home"-- whose description is "TEST"
end tell

and the result is as expected, “{}”. Seems the delete worked, the event list is empty, but the event remains there on the calendar. All other calendars are unchecked, the event is on the “Home” calendar. Uncheck “Home” and the event disappears.

My question: If the events list is empty, why is there an event displayed on the calendar? (I think I’m going quite mad!)

I would be grateful for help on this. Thanks in advance!!

Model: MacBook Pro
AppleScript: 2.5
Browser: Safari 602.4.8
Operating System: Mac OS X (10.10)

Hi. Calendar if rife with glitches. Sometimes things may be deleted only to be magically repopulated by its internal database.

Shane STANLEY wrote and delivered a powerful library to drive Calendar.
Two versions are available :
CalendarLib v1.1.2 for OS X 10.9 or later completed by BridgePlus script library
CalendarLib EC v1.1.2 for macOS 10.11 or later

The three items are available for free from : https://www.macosxautomation.com/applescript/apps/Script_Libs.html

Yvan KOENIG running Sierra 10.12.4 in French (VALLAURIS, France) mercredi 5 avril 2017 20:40:54

Hi all,

Thanks for getting back to me.

So you’re saying that Calendar doesn’t really know what events it has? Where does that leave me? I can’t delete the event through AppleScript because Calendar doesn’t know it’s there?

This also doesn’t work: Make a new event, no problem, wait for response to a dialog and then delete it. It makes the thing fine, but won’t delete it.


set startDate to date "Saturday, April 8, 2017 at 2:15:00 PM"
set endDate to date "Saturday, April 8, 2017 at 2:15:00 PM"
set allDay to false
set alertPrior to 2
set alertPriorUnit to "day"
set duration to 45

return markCalendar(startDate, endDate, duration, alertPrior, alertPriorUnit, allDay)

on markCalendar(startDate, endDate, duration, alertPrior, alertPriorUnit, allDay)
	if alertPriorUnit is not "minute" and alertPriorUnit is not "hour" and alertPriorUnit is not "day" then return "Calendar error: alert unit must be \"hour\", \"minute\", or \"day\"."
	set alertSeconds to alertPrior * 60
	if alertPriorUnit is "hour" then set alertSeconds to alertPrior * 3600
	if alertPriorUnit is "day" then set alertSeconds to alertPrior * 86400
	tell application "Calendar"
		tell calendar "Home"
			set thisEvent to make new event with properties {description:"TEST", summary:"TEST", location:"Event Location", start date:startDate, end date:endDate + duration * minutes, allday event:allDay}
			tell thisEvent
				make new display alarm with properties {trigger date:startDate - alertSeconds}
			end tell
			display dialog "How's yer father?"
			delete thisEvent
		end tell
	end tell
end markCalendar

I repeat : the tools delivered by Shane STANLEY are designed to get rid of the failures of the “in the box” support.
Now, if you want to waste your time you may continue to fight against a dead horse.

Yvan KOENIG running Sierra 10.12.4 in French (VALLAURIS, France) jeudi 6 avril 2017 09:42:00

Thank you for your cordial response. I have downloaded the Calendar.lib and am looking into it. I thank you for that. But it does have disadvantages as Mr. Stanley notes, which include the need for two libraries and lack of support for all features. I would like to waste my time learning a little more about Calendar.app as well, if that’s OK.

How do others work “in the box” at all if the calendar display does not respond to the events array?


tell application "Calendar" to return every event of calendar "TEST"

returns “{}” as expected after deleting events through AppleScript, yet the events remain displayed in the Calendar. It seems to me, a fundamental question.

I’m going to hop on my dead horse now and trot over to Calendar.lib. But if anyone can answer this question, I thank you in advance for any positive replies.

I’m really puzzled because here your script does its duty. But maybe I did miss something (remember that English is not my main language).
I changed the name of the calendar to fit an existing one here and I got :

{event id "3FF667CB-9B3E-42CE-A5BD-D5357E19A763" of calendar id "15796FB4-0796-43DD-ACD4-C41067C1012D" of application "Calendar", event id "1B7B6C3A-53A2-4AFF-AE3E-4BA34293058E" of calendar id "15796FB4-0796-43DD-ACD4-C41067C1012D" of application "Calendar", event id "8C7C4D92-1644-48DC-938B-FAB328E432D1" of calendar id "15796FB4-0796-43DD-ACD4-C41067C1012D" of application "Calendar", event id "69B4B5CA-C9D1-4D2D-A46A-A9FF18004B84" of calendar id "15796FB4-0796-43DD-ACD4-C41067C1012D" of application "Calendar", event id "4B1BE7C4-3669-4AFB-BE0A-A5F5D65C4031" of calendar id "15796FB4-0796-43DD-ACD4-C41067C1012D" of application "Calendar", event id "F619A8D3-1063-4941-B766-05B04E94514F" of calendar id "15796FB4-0796-43DD-ACD4-C41067C1012D" of application "Calendar"}

Maybe, under 10.10 you must activate the application before asking it to return something.
It was the case for several apps which no longer requires that under 10.12.
Try with :

tell application "Calendar"
	activate
	delay 0.2 # maybe useless
	return every event of calendar "TEST"
end tell

Yvan KOENIG running Sierra 10.12.4 in French (VALLAURIS, France) jeudi 6 avril 2017 17:45:59

On my El Capitan system, Calendar’s display isn’t updated when an event’s deleted with AppleScript, but it is updated (including ceasing to display previously deleted events) when AppleScript adds or moves events. The delay before a change becomes visible ” or even if it becomes visible at all ” seems to depend on the total number of events in Calendar at the time, how long it’s been open, and how recently an AppleScript was run on it before the current one!

This version of LouK’s test script cheats by changing the event’s dates to a slot that’s unlikely to be seen and then deleting it. The event remains visible but deleted in the other date slot, but at least it’s gone from the original slot and will be cleared altogether next time an update does take place. I’m afraid it’s more a lesson in workaroundery than in scripting Calendar. :confused:

on makeDate(dateDetails)
	set aDate to (current date)
	set {year:y, month:m, day:d} to aDate
	set {year:y, month:m, day:d, hours:h, minutes:min, seconds:s} to dateDetails & {year:y, month:m, day:d, hours:0, minutes:0, seconds:0}
	tell aDate to set {its day, its year, its month, its day, its hours, its minutes, its seconds} to {1, y, m, d, h, min, s}
	
	return aDate
end makeDate

-- The compilation of this property depends on the makeDate() handler being above it in the script.
property longAgoDate : makeDate({year:1850, month:January, day:1})

set startDate to makeDate({year:2017, month:April, day:8, hours:14, minutes:15})
copy startDate to endDate
set allDay to false
set alertPrior to 2
set alertPriorUnit to "day"
set duration to 45

return markCalendar(startDate, endDate, duration, alertPrior, alertPriorUnit, allDay)

on markCalendar(startDate, endDate, duration, alertPrior, alertPriorUnit, allDay)
	if alertPriorUnit is not "minute" and alertPriorUnit is not "hour" and alertPriorUnit is not "day" then return "Calendar error: alert unit must be \"hour\", \"minute\", or \"day\"."
	set alertSeconds to alertPrior * minutes
	if alertPriorUnit is "hour" then set alertSeconds to alertPrior * hours
	if alertPriorUnit is "day" then set alertSeconds to alertPrior * days
	tell application "Calendar"
		activate
		tell calendar "Home"
			set thisEvent to make new event with properties {description:"TEST", summary:"TEST", location:"Event Location", start date:startDate, end date:endDate + duration * minutes, allday event:allDay}
			tell thisEvent
				--make new display alarm with properties {trigger date:startDate - alertSeconds}
			end tell
		end tell
		display dialog "How's yer father?"
		-- Move the event to a date you're unlikely to view and delete it there.
		tell thisEvent
			set {its start date, its end date} to {longAgoDate, longAgoDate}
			delete
		end tell
	end tell
end markCalendar

Yvan,

Fighting a dead horse actually sounds really easy. That’s one fight I’m pretty sure I could win… :wink:

I know, English isn’t your first language, and your English is much better than I am in my second language.

The expression is “beating a dead horse,” meaning a futile act.

</grammar nazi>

On my Mavericks system, Calendar’s display is updated when an event deletes but refuses to move an event (then returns a database error). It seems unreliable in terms of basic scriptability, and it could benefit from a save function”à la Contacts.

My workaround’s no good to you then. :wink:

I must admit that although I use Calendar myself, I seldom have reason to script for it. Every fifteen years or so, I may run a script to enter the Easter, Christmas, and New Year holiday periods for the next few years, but the rest is all recurring events and individual events entered manually. Occasionally, I may want to do something which can only be achieved by script, such as “crossing out” an event rather than deleting it, or setting a recurrence rule not catered for in Calendar’s presets, or locating an event whose date I’ve forgotten.

Thanks t.spoon, I learnt something.

Here is a sample showing how we may easily beat the dead horse ;

use script "CalendarLib" version "1.1.1" -- put this at the top of your scripts
use scripting additions
set startDate to "12/12/12"
set startDate to date startDate
set year of startDate to 2017
set month of startDate to 4
set day of startDate to 8
set hours of startDate to 14
set minutes of startDate to 15
copy startDate to endDate

set allDay to false
set alertPrior to 2
set alertPriorUnit to "day"
set duration to 45

return markCalendar(startDate, endDate, duration, alertPrior, alertPriorUnit, allDay)

on markCalendar(startDate, endDate, duration, alertPrior, alertPriorUnit, allDay)
	if alertPriorUnit is not "minute" and alertPriorUnit is not "hour" and alertPriorUnit is not "day" then return "Calendar error: alert unit must be \"hour\", \"minute\", or \"day\"."
	set alertSeconds to alertPrior * 60
	if alertPriorUnit is "hour" then set alertSeconds to alertPrior * 3600
	if alertPriorUnit is "day" then set alertSeconds to alertPrior * 86400
	
	set theStore to fetch store
	set theCal to fetch calendar "Work" cal type cal local event store theStore -- change to suit
	set theEvent to create event event store theStore destination calendar theCal event summary "A test event" starting date startDate ending date (endDate + duration * minutes) event location "Event Location" event description "some notes" runs all day allDay
	store event event theEvent event store theStore with future events
	tell me to display dialog "How's yer father?"
	delay 2
	
	remove event event theEvent event store theStore with future events
end markCalendar

As you may see, I built the dates from scratch because here I use the french format (day month year).

Yvan KOENIG running Sierra 10.12.4 in French (VALLAURIS, France) vendredi 7 avril 2017 11:03:27

Hi Ivan, thanks for your script. I think there’s a little forgetfulness: where is the “alertSeconds” setting?

Honestly I don’t remember what I made.

At first look it seems that I dropped the use of alertSeconds because there is no property trigger date in CalendarLib but I may be wrong.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 24 octobre 2019 12:32:53