Text List of Schedule from Calendar? and availability?


Hi Everyone,

I’ve been looking for different ways of getting a list of my daily schedule and/or availability. Does anyone have a script that can do this? I use multiple calendars, so it would be great if it could use two. Ideally, I’d like to use text expander to trigger the apple script to paste in my daily schedule in my journal and availability for emails (I know Apple Shortcuts can do this).

Maybe there’s an option in Fantastical I’ve missed?

I found this AppleScript, but it is very very slow:

**on** getDateRange()

**set** today **to** ( **current date** )

**set** d1 **to** today's short date string

**set** d2 **to** short date string **of** (today + 6 * days)

**set** dateRange **to** text returned **of** ( **display dialog** "Enter the required date range:" default answer d1 & " - " & d2)

**set** dateRangeStart **to** *date* ( *text* **from** *word* 1 **to** *word* 3 **of** dateRange)

**set** dateRangeEnd **to** *date* ( *text* **from** *word* -3 **to** *word* -1 **of** dateRange)

**set** dateRangeEnd's time **to** days - 1 -- Sets the last date's time to 23:59:59, the last second of the range.

**return** {dateRangeStart, dateRangeEnd}

**end** getDateRange

-- Return the start dates, summaries, and calendar names of events in the given date range.

-- {{start date, summary, calendar name}, {start date, summary, calendar name}, … }

**on** filterToDateRange(theStartDates, theSummaries, theCalendarNames, dateRangeStart, dateRangeEnd)

**script** o

**property** sDates : theStartDates

**property** summaries : theSummaries

**property** cNames : theCalendarNames

**property** filteredData : {}

**end** **script**

**repeat** **with** i **from** 1 **to** ( **count** theCalendarNames)

**set** o's sDates **to** *item* i **of** theStartDates

**set** o's summaries **to** *item* i **of** theSummaries

**set** thisCalendarName **to** *item* i **of** theCalendarNames

**repeat** **with** j **from** 1 **to** ( **count** o's sDates)

**set** thisStartDate **to** *item* j **of** o's sDates

**if** ( **not** ((thisStartDate **comes before** dateRangeStart) **or** (thisStartDate **comes after** dateRangeEnd))) **then**

**set** thisSummary **to** *item* j **of** o's summaries

**set** **end** **of** o's filteredData **to** {thisStartDate, thisSummary, thisCalendarName}

**end** **if**

**end** **repeat**

**end** **repeat**

**return** o's filteredData

**end** filterToDateRange

-- Sort the filtered data by start date.

**on** sortByDate(filteredData)

-- A sort-customisation object which compares the first items of two sublists taken from the list being sorted.

**script** custom

**on** isGreater(a, b)

**return** ( **beginning** **of** a > **beginning** **of** b)

**end** isGreater

**end** **script**

CustomShellSort(filteredData, 1, -1, {comparer:custom})

**end** sortByDate

-- Shell sort. Algorithm: Donald Shell, 1959. AppleScript implementation: Nigel Garvey, 2010.

**on** CustomShellSort(theList, l, r, customiser)

**script** o

**property** comparer : **me**

**property** slave : **me**

**property** lst : theList

**on** shsrt(l, r)

**set** step **to** (r - l + 1) **div** 2

**repeat** **while** (step > 0)

slave's setStep(step)

**repeat** **with** j **from** (l + step) **to** r

**set** v **to** *item* j **of** o's lst

**repeat** **with** i **from** (j - step) **to** l **by** -step

**tell** *item* i **of** o's lst

**if** (comparer's isGreater( **it** , v)) **then**

**set** *item* (i + step) **of** o's lst **to** **it**


**set** i **to** i + step

**exit** **repeat**

**end** **if**

**end** **tell**

**end** **repeat**

**set** *item* i **of** o's lst **to** v

slave's rotate(i, j)

**end** **repeat**

**set** step **to** (step / 2.2) **as** *integer*

**end** **repeat**

**end** shsrt

-- Default comparison and slave handlers for an ordinary sort.

**on** isGreater(a, b)

(a > b)

**end** isGreater

**on** rotate(a, b)

**end** rotate

**on** setStep(a)

**end** setStep

**end** **script**

-- Process the input parameters.

**set** listLen **to** ( **count** theList)

**if** (listLen > 1) **then**

-- Negative and/or transposed range indices.

**if** (l < 0) **then** **set** l **to** listLen + l + 1

**if** (r < 0) **then** **set** r **to** listLen + r + 1

**if** (l > r) **then** **set** {l, r} **to** {r, l}

-- Supplied or default customisation scripts.

**if** (customiser's *class* **is** *record* ) **then** **set** {comparer:o's comparer, slave:o's slave} **to** (customiser & {comparer:o, slave:o})

-- Do the sort.

o's shsrt(l, r)

**end** **if**

**return** -- nothing.

**end** CustomShellSort

-- Create a new TextEdit document with text derived from the gathered data.

**on** composeText(filteredData)

**tell** *application* "TextEdit"

-- Make a new document, with a minimal text so that we can discover the name of its font.

**set** newDoc **to** ( **make** new *document* with properties { *text* :" "})

**set** baseFont **to** font **of** newDoc's *text*

-- This ASSUMES that an equivalent bold font exists and that its name is the same as the plain font with " bold" appended.

**set** boldFont **to** baseFont & " bold"

-- Dummy text no longer needed.

**set** newDoc's *text* **to** ""


**end** **tell**

**if** (filteredData **is** {}) **then**

-- If no events have been discovered in the date range, print that fact.

**tell** *application* "TextEdit" **to** **make** new *paragraph* at **end** **of** newDoc's *text* with data "No events found in this period." with properties {font:boldFont}


-- Otherwise print the event details.

**set** currentCalendarDate **to** "" -- The calendar date currently being processed. (None yet.)

**repeat** **with** i **from** 1 **to** ( **count** filteredData)

-- Get the data for an event from the list of filtered data.

**set** {{date string:thisCalendarDate, hours:thisStartTimeH, minutes:thisStartTimeM}, thisSummary, thisCalendar} **to** *item* i **of** filteredData

-- If the calendar date is different from the one we've been processing up till now, output an empty line and the new date string to TextEdit.

**if** (thisCalendarDate **is** **not** currentCalendarDate) **then**

**tell** *application* "TextEdit"

**make** new *paragraph* at **end** **of** newDoc's *text* with data linefeed with properties {font:baseFont}

**make** new *paragraph* at **end** **of** newDoc's *text* with data (thisCalendarDate & linefeed) with properties {font:boldFont}

**end** **tell**

-- Make the new date the one currently being processed.

**set** currentCalendarDate **to** thisCalendarDate

**end** **if**

-- Create a 24-hour time string from the hours and minutes of the start date.

**tell** (10000 + thisStartTimeH * 100 + thisStartTimeM) **as** *text* **to** **set** thisStartTime **to** *text* 2 **thru** 3 & ":" & *text* 4 **thru** 5

-- Output the entry for this event to TextEdit.

**tell** *application* "TextEdit" **to** **make** new *paragraph* at **end** **of** newDoc's *text* with data ("\"" & thisCalendar & "\" calendar: " & thisStartTime & " " & thisSummary & linefeed) with properties {font:baseFont}

**end** **repeat**

**end** **if**

**end** composeText

**on** main()

**say** "Getting data from Calendar. It may take a while…"

**tell** *application* "Calendar" **to** **set** {{theStartDates, theSummaries}, theCalendarNames} **to** {{start date, summary} **of** *events* , name} **of** *calendars*

**set** {dateRangeStart, dateRangeEnd} **to** getDateRange()

**set** filteredData **to** filterToDateRange(theStartDates, theSummaries, theCalendarNames, dateRangeStart, dateRangeEnd)



**end** main



Fantastical 2 (on macOS – I assume that is where you want to do this) has several options to print calendars in various configurations and ranges – and then print that to PDF. Fantastical 2 supports multiple calendar sets, which can then be selected in the print dialog.

The Apple Calendar app has a similar, though less feature-rich, print dialog. And Apple Calendar does not support calendar sets.

You could conceivably create a Keyboard Maestro macro to control Fantastical’s calendar printing.


Thanks for pointing this out, @quorm. I don’t know if I’d ever need a printout but I didn’t realize these features were there at all.


I regularly print 2 copies of my standard Apple calendar out to PDF at the end of each month as another backup of the data. One is a month view but the other is in list format. Neither shows the available time in a really clear fashion but it does give you a list to work from.


Thanks @quorm. I didn’t even know this was a feature. The only issue is that it’s not easy to get into a text slit. Although I was hoping for something I could use in MacOS, I was able to rejigger one based on existing shortcuts in ios (named Check Remaining Meetings). Thought I’d share. This shortcut copies the text to drafts because this is the most reliable and fastest way I could figure out to get it on MacOS.

This shortcut will give you a list of the remaining events for the day. https://www.icloud.com/shortcuts/3494e4c9d6e5496493de921a5f9d8719


@omarruvalcaba I have been trying to get this Alfred workflow to function, but without much luck. It copies your schedule or availability to your clipboard.


I can’t seem to get it to work either oh well. Thanks for sharing. I’ll update if I figure it out.