I have recently started experimenting with this excellent library and have encountered a problem which is probably me not understanding the dictionary.
I would like to have my script obtain a list of calendar names so that the user may select one. On first reading of the dictionary the command “fetch calendars” seems to be the one to use : “fetch calendars (verb)Fetches a list of calendars” and " A list of calendar names. Pass an empty list to include all names."
Unfortunately these commands :
set theStore to fetch store
set theCals to fetch calendars {} event store theStore -- change to suit
These return what I am guessing is a list of calendar objects rather than the names implied in the dictionary. Now I can produce a list of names by looping through the events of each calendar in the list but getting the events is date based and if a calendar has no events between the two dates supplied it is not found by my code.
I hope that I have missed an obvious way of getting a list of calendars using CalendarLib EC, any thoughts?
best wishes
Simon
Is this what you’re looking for?
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "CalendarLib EC" version "1.1.5"
set theStore to fetch store
set theCals to fetch calendars {} event store theStore -- change to suit
set theTitles to {}
repeat with aCal in theCals
set end of theTitles to aCal's title() as text
end repeat
Yes it is - Thank you!
Mind you the code does raise some more questions, sorry.
I wonder where I should have discovered the call to “title()” in documentation. I have been through CalendarLib EC’s dictionary and can not find it. Apple’s Calendar only includes the word title in the description of the properties of the calendar class when describing the name property:
“name get/set text This is the calendar title.”
Where is title() defined and are there more useful calls to be discovered ?
Looking inside CalendarLib I see I can also use |type|() not that I’m sure I need to.
best wishes
Simon
It’s not there – that code is calling the Cocoa method via AppleScriptObjC. You could also ask Calendar.app for the name of all calendars.
Hi,
Thats so high above my head that it has a vapour trail.
However, I have just updated a script that draws a year planner in OmniGraffle using two of your libraries. My script now has a reasonable interface and it writes events from my calendar into the year planner whereas before I had to add events by hand.
Somewhere in the documentation of your scripts you asked for feed back :
Bloody Brilliant!
Thanks for creating them and pointing me in the right direction.
best wishes
Simon
That’s why I mentioned using Calendar.app as an alternative for that part.
Well I’m quite happy to use the code now that you have shown me how! My first version used the Fetch Events call once per day which worked but was very slow. Obviously I needed a method of storing and accessing events locally within the script so I came up with this code:
-- ** Start by preparing the calendar data **
set theStore to fetch store --ref to calendar data
set theCals to fetch calendars {} event store theStore -- change to suit
set lstCalTitles to {"None"}
set lstCalTypes to {}
repeat with aCal in theCals
set end of lstCalTitles to aCal's title() as text
set end of lstCalTypes to aCal's |type|() as text
end repeat
I present the user with the option of selecting a calendar by “Title” and they also select a date range then extract the events:
-- Call CalendarLib EC to retreive a list of events for the selected calendar
repeat with tCal in theCals
if tCal's title() as string = tChosenCalTitle then
set allEvents to fetch events starting date (item 1 of tStartEndDates) ending date (item 2 of tStartEndDates) searching cals {tCal} event store theStore
end if
end repeat
set tEventsList to {}
set tEventsList to GetListOfEvents(allEvents)
The handler GetListOfEvents builds an Applescript list of events with each item being a delimited string :
on GetListOfEvents(pAllEvents)
set tDatePrevEvent to "unset"
set tEventsList to {}
set oldDelims to AppleScript's text item delimiters -- save their current state
set AppleScript's text item delimiters to {"~"} -- declare new delimiters
repeat with anEvent in pAllEvents
set tInfo to (event info for event anEvent)
set EventDate to the event_start_date of tInfo as date
set tDateKey to (year of EventDate as string) & "-" & (month of EventDate as string) & "-" & (day of EventDate as string)
if tDateKey = tDatePrevEvent then
-- retrieve the summary
set the tLastLine to last item of tEventsList
set tSummary to item 2 of (the text items of tLastLine)
set tSummary to tSummary & "/" & the event_summary of tInfo
--remove the last item from list
set tEventsList to tEventsList's (items 1 thru -2)
else
set tSummary to the event_summary of tInfo
--set tDatePrevEvent to tDateKey
end if
set end of tEventsList to tDateKey & "~" & tSummary
set tDatePrevEvent to tDateKey
end repeat
set AppleScript's text item delimiters to oldDelims -- restore them
return tEventsList
end GetListOfEvents
Finally the code that draws box shapes in OmniGraffle requests calendar entries by date using the following :
on GetEventText(pEventsList, pDayStr, pMonthStr, pYearStr)
(*
pDayStr: string version of integer describing the day of the month (e.g. "9")
pMonthStr: string version of the month. (e.g. "March")
pYearStr: string version of integer describing the day of the year (e.g. "2021")
*)
set oldDelims to AppleScript's text item delimiters -- save their current state
set AppleScript's text item delimiters to {"~"} -- declare new delimiters
set tSearchKey to pYearStr & "-" & pMonthStr & "-" & pDayStr
repeat with tItem in pEventsList
set tDataRec to the text items of tItem
set tFoundKey to item 1 of tDataRec
if tFoundKey = tSearchKey then
set tEventText to item 2 of tDataRec
return tEventText
end if
end repeat
set AppleScript's text item delimiters to oldDelims -- restore them
set tEventText to ""
return tEventText
end GetEventText
There are probably better and faster methods but this works and does not slow the script down to make it annoying.
best wishes
Simon