CalendarLib EC getting a list of calendars

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! :smiley:

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