How can I get the currently selected calendar event from Calendar app through AppleScript?
I want to write a script that will get the information for the calendar event that I’ve selected and generate an e-mail template from it (kind of similar to if you right/option click on the event and select “Mail Event”). What I’m trying to do is have it create a Meeting Minutes template with the details from the event itself (title, date/time, invitees, and location). The script would need to work across any of my calendars.
I’ve seen scripts that iterate through calendar events for a particular (hardcoded) calendar, but haven’t seen any way to get the currently selected event and get its details. Any help would be greatly appreciated.
I’m using Mavericks, Calendar Ver 7.0
AppleScript: 2.3
Browser: Safari 537.71
Operating System: Mac OS X (10.8)
unfortunately in Calendar.app (as well as in former iCal.app) the selection is not accessible with AppleScript.
Maybe it could be accomplished with GUI scripting but this depends on the selected view
Hi kel1:
I’m trying to get info from meetings, primarily from a CalDav account.
At this point, I’m thinking what I may do is let the user select the date, then use that to retrieve all the meetings for the selected day, show the user the list of meetings, have them choose one, and then have the script get the details from the meeting and apply the e-mail template to it, open up a new Mail message with the template.
I also considered trying to figure out the meeting that just finished, but that’s limited in that it doesn’t allow the user to generate meeting minutes from earlier meetings.
Sorry, to be clear, my original ask was about a user selecting a meeting from the Calendar app and then running my AppleScript to have it generate a meeting minutes template for that particular meeting. But, it looks like that’s not really possible, so now I’m thinking of taking a different approach, allowing the user to just select a date. This is not nearly as useful though.
No you can still do your original thing. If the summary is unique on some day. But it also depends on what kind of events. Some events returns simple things like a string. Some events return rtf and more.
Hi. As explained by Stefan, you basically can’t use your intended in-calendar selection method, unless you want to resort to the disaster that is GUI scripting. You also can’t directly “select” a date, but you can choose events from a list. If you search the forum, you will find a previously written iCal script that I authored which allows you to narrow dates by range.
Sorry to revive an old thread, but the solution link on Johneday.com does not work anymore and I only found bad workarounds via copy… does anyone have the content of the solution at hand to post? @n0stress4me ?
I do have a script of John’s handy, as it happens, but his method for reading the Calendar cache directly with sqlite3 errors in Mojave.
However, this seems to work. Like John’s original, it has a slight weakness in that it reads the IDs of the selected events from Calendar’s User Defaults, which may not get updated until several seconds after the events are selected.
use AppleScript version "2.4" -- Mac OS 10.10 (Yosemite) or later.
use framework "Foundation"
use framework "EventKit"
use scripting additions
on getAuthorisation()
(* Handler by Shane Stanley. *)
display dialog "Access must be given in System Preferences" & linefeed & "-> Security & Privacy first." buttons {"OK"} default button 1
tell application "System Preferences"
activate
tell pane id "com.apple.preference.security" to reveal anchor "Privacy"
end tell
error number -128
end getAuthorisation
on main()
(* Based on code by Shane Stanley and John Day. *)
set |⌘| to current application
-- create event store and get the OK to access calendars
set theEKEventStore to |⌘|'s class "EKEventStore"'s alloc()'s init()
tell theEKEventStore to requestAccessToEntityType:0 completion:(missing value)
-- check if app has access; this will still occur the first time you OK authorization
set authorizationStatus to |⌘|'s class "EKEventStore"'s authorizationStatusForEntityType:(0) -- work around enum bug
if (authorizationStatus is not 3) then getAuthorisation()
-- EKEventStore event predicates only span four years. Get start and end dates two years either side of the present.
set dateRangeStart to |⌘|'s class "NSDate"'s dateWithTimeIntervalSinceNow:((-2 * 365.24 * days) as integer)
set dateRangeEnd to |⌘|'s class "NSDate"'s dateWithTimeIntervalSinceNow:((2 * 365.24 * days) as integer)
-- Get all the events between these dates.
tell theEKEventStore
set calendarsToSearch to its calendarsForEntityType:(0)
set eventPredicate to its predicateForEventsWithStartDate:(dateRangeStart) endDate:(dateRangeEnd) calendars:(calendarsToSearch)
set eventsWithinRange to its eventsMatchingPredicate:(eventPredicate)
end tell
-- Read the Event Identifiers of the events selected in Calendar from the User Defaults.
set selectedEventIdentifiers to paragraphs of (do shell script "defaults read com.apple.ical SelectedEvents | sed -En '/^ *\"([^\"]+)\".*$/ { s//\\1/; /\\// s/^[^/]+\\///; p; }'")
if (selectedEventIdentifiers is {}) then display alert "No events selected!" message "… or Calendar's User Defaults may simply not have caught up yet. Try again in a few seconds if so." buttons {"OK"} default button 1 cancel button 1 as criticall
-- Filter the events for those with the returned identifiers.
set selectedEventsPredicate to |⌘|'s class "NSPredicate"'s predicateWithFormat:("eventIdentifier IN %@") argumentArray:({selectedEventIdentifiers})
set selectedEvents to eventsWithinRange's filteredArrayUsingPredicate:(selectedEventsPredicate)
-- Get the IDs of the remaining events and their calendars as used in Calendar AppleScript.
set eventUIDs to (selectedEvents's valueForKey:("calendarItemExternalIdentifier")) as list
set calendarUIDs to (selectedEvents's valueForKeyPath:("calendar.calendarIdentifier")) as list
-- Make up and return a list of Calendar references to the selected events, omitting any duplicates due to recurring events.
set doneUIDs to {}
set CalendarRefs to {}
repeat with i from 1 to (count eventUIDs)
set thisUID to item i of eventUIDs
if (thisUID is not in doneUIDs) then
tell application "Calendar" to set end of CalendarRefs to event id thisUID of calendar id (item i of calendarUIDs)
set end of doneUIDs to thisUID
end if
end repeat
return CalendarRefs
end main
main()