[This post starts with the general problem and some basic scripts -- but don't worry -- it ends with two definitive solutions.]
Yesterday I described
several clumsy hacks to get a plaintext display of upcoming Calendar events from one or more Mac or Google Calendars. In today's post I look at what's possible with AppleScript [1] (or
Python and AppScript) support -- though as of 8/4/13 I'm not done with it.
Specifically I want to get a plaintext list of events on one or more Google Calendars through AppleScript and Calendar.app when Calendar.app is configured to read Calendars from a Google share. Based on some articles I found, it looks possible:
I was able to
retrieve the references and names of all my Google Calendars using 2005 code from MacTech
tell application "iCal"
set theCalendars to every calendar
end tell
and
tell application "iCal"
set theCalendarNames to title of every calendar
end tell
I was also able to
view a calendar at a specified date and I found it used the selected calendars though not in my desired format.
This
script listed events by event id for the current date and it seems easy to modify if I study some AppleScript date arithmetic ...
set {year:y, month:m, day:d} to current date
set str to (m as string) & " " & (d as string) & " " & (y as string)
set today to date str
set tomorrow to today + 60 * 60 * 24
tell application "iCal"
tell calendar "Lotus Notes"
set curr to every event whose start date is greater than or equal to today ¬
and start date is less than or equal to tomorrow
end tell
end tell
This one worked, but search can take a very long time...
tell application "iCal"
tell calendar "Domestic"
set theEventList to every event whose summary contains "Recycling"
end tell
set theEvent to first item of theEventList
return summary of theEvent
end tell
I'll have to leave this task for a bit, but I have a long family car drive coming up and I might be able to play with it on the way. I've also
asked about this on MacScripter.net, where respondents have
been known to solve problems very thoroughly.
Or I could just try Automator...
Using Automator to create a plaintext list of upcoming events from OS X Calendar.app
- fn -
[1] SQL, AppleScript and COBOL all have one thing in common - they were designed for use by "non-programmers". Let that be a lesson.
See also
-- Ask the user for the range of dates to be covered.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 and summaries which are in the given date range.on filterToDateRange(theStartDates, theSummaries, dateRangeStart, dateRangeEnd)
set {eventDatesInRange, eventSummariesInRange} to {{}, {}}
repeat with i from 1 to (count theStartDates)
set thisStartDate to item i of theStartDates
if (not ((thisStartDate comes before dateRangeStart) or (thisStartDate comes after dateRangeEnd))) then
set end of eventDatesInRange to thisStartDate
set end of eventSummariesInRange to item i of theSummaries
end if
end repeat
return {eventDatesInRange, eventSummariesInRange}
end filterToDateRange
-- Sort both the start-date and summary lists by start date.on sortByDate(eventDatesInRange, eventSummariesInRange)
-- A sort-customisation object for sorting the summary list in parallel with the date list. script custom
property summaries : eventSummariesInRange
on swap(i, j)
tell item i of my summaries
set item i of my summaries to item j of my summaries
set item j of my summaries to it
end tell
end swap
end script
CustomBubbleSort(eventDatesInRange, 1, -1, {slave:custom})
end sortByDate
-- CustomBubbleSort from "A Dose of Sorts" by Nigel Garvey.-- The number of items to be sorted here is likely to be small.on CustomBubbleSort(theList, l, r, customiser)
script o
property comparer : me
property slave : me
property lst : theList
on bsrt(l, r)
set l2 to l + 1
repeat with j from r to l2 by -1
set a to item l of o's lst
repeat with i from l2 to j
set b to item i of o's lst
if (comparer's isGreater(a, b)) then
set item (i - 1) of o's lst to b
set item i of o's lst to a
slave's swap(i - 1, i)
else
set a to b
end if
end repeat
end repeat
end bsrt
-- Default comparison and slave handlers for an ordinary sort. on isGreater(a, b)
(a > b)
end isGreater
on swap(a, b)
end swap
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 bsrt(l, r)
end if
return -- nothing end CustomBubbleSort
-- Compose the text from the items in the start-date and summary lists.on composeText(eventDatesInRange, eventSummariesInRange)
set txt to ""
set gap to linefeed & linefeed
repeat with i from 1 to (count eventDatesInRange)
set txt to txt & (date string of item i of eventDatesInRange) & (linefeed & item i of eventSummariesInRange & gap)
end repeat
return text 1 thru -3 of txt
end composeText
on main()
tell application "iCal" to set {theStartDates, theSummaries} to {start date, summary} of events of calendar "FL Family Calendar"
set {dateRangeStart, dateRangeEnd} to getDateRange()
set {eventDatesInRange, eventSummariesInRange} to filterToDateRange(theStartDates, theSummaries, dateRangeStart, dateRangeEnd)
sortByDate(eventDatesInRange, eventSummariesInRange)
set txt to composeText(eventDatesInRange, eventSummariesInRange)
tell application "TextEdit"
make new document with properties {text:txt}
activate
end tell
end main
main()
Update 8/6/13: Clark Goble codes up comingevents.py, which uses PyObjC, AppScript, Osax and, of course, Python. It includes Parsedatetime so date entry can be free text and outputs plain text, HTML, Clipboard and probably sends a message to another dimension. I think at this point we've got scripted plaintext event publication covered. Be sure not to miss his links to related posts.