Goal: Generate a text file (for printing) which contains a sorted list of iCal events (sorted by start date).
When asking iCal for a list of events, the result is not necessarily sorted by start date (I don’t know what criteria is used to determine the order of the list). Does anyone have a handler (that you care to share) that will sort a list of iCal events by start date? I can likely stumble through this but I’ve been fumbling around without success and I need this yesterday. I would truly appreciate it if someone offers code or guidance to this tired ol’ scripter.
set sorted_ to {}
tell application "iCal"
set events_ to events of calendar 1
repeat with event_ in events_
-- brain fart
-- determine that latest date in events_ and add it to end of sorted_ for further processing
end repeat
end tell
Note: I plan to limit the list of events to those which fall within the current month but I can handle that part as well as generating the text file. It’s simply the sorting that’s causing my brain fart.
I generate three lists (this is just a fragment of a larger script) sort them together on days to go and growl the output:
-- This script calculates the days remaining before the next four birthdays in an iCal calendar named "Birthdays".
-- Each birthday is entered as an all day event
-- The script uses Growl to display the result.
-- Get today's date with time set to midnight. Later days to go subtractions must have a time of day in common or differences can be off by one day.
set today to current date
set time of today to 0 -- seconds after midnight
-- Get the Birthday Date List "bDays" and Birthday Name List "bName", correct for GMT, then subtract today after correcting year.
tell application "iCal"
close window 1
set bdCals to every calendar whose title contains "Birthdays"
set bCal to first item of bdCals
set toGo to {}
set who to {}
set when to {}
-- Collect the date/name lists
set bCount to count events of bCal
repeat with n from 1 to bCount
-- Start date is the birthday for an all day event.
-- Summary should be the person's name.
-- iCal stores times of events in GMT even though it presents them in local time.
-- Times must be shifted back to a midnight base before days to go are calculated.
tell event n of bCal to set {tName, tDate} to {summary of it, start date of it}
-- adjust for GMT offset
tell tDate
if time of it = 75600 then -- 9:00 PM if ADST
set time of it to (time of it) + 10800
else -- 8:00 PM if AST
set time of it to (time of it) + 14400
end if
-- adjust the calendar year of the birthday ahead of now
repeat until (it - today) > 0
set year of it to (year of it) + 1
end repeat
-- Calculate days to go to next birthday
set daysLeft to ((it - today) / days) as integer
--set item n of tDate to daysLeft
set end of toGo to daysLeft
set end of who to tName
set end of when to it
end tell
end repeat
--quit
end tell
-- Sort by days to go
sort_items(toGo, who, when)
-- Get first four
set msg_C to " days until "
set BDNotes to ""
set r to return
set rr to r & r
set sp to space
set ap to ASCII character 240
repeat with mm from 1 to 5
set msg_A to (item mm of toGo) as text
set msg_B to (item mm of who)
set msg_D to date string of (item mm of when)
-- add possessives for names: soAndso's Birthday
if last character of msg_B = "s" then
set msg_B to msg_B & "'"
else
set msg_B to msg_B & "'s"
end if
if msg_B = "Anniversary's" then set msg_B to "Our Anniversary"
set tBDNote to msg_A & msg_C & msg_B & " on" & r & ap & sp & sp & msg_D
set BDNotes to BDNotes & tBDNote & rr
end repeat
Growl_It("Birthdays Coming Soon", BDNotes)
to sort_items(sortList, SecondList, thirdList) -- by Kai Edwards
tell (count sortList) to repeat with i from (it - 1) to 1 by -1
set s to sortList's item i
set r to SecondList's item i
set q to thirdList's item i
repeat with i from (i + 1) to it
tell sortList's item i to if s > it then
set sortList's item (i - 1) to it
set SecondList's item (i - 1) to SecondList's item i
set thirdList's item (i - 1) to thirdList's item i
else
set sortList's item (i - 1) to s
set SecondList's item (i - 1) to r
set thirdList's item (i - 1) to q
exit repeat
end if
end repeat
if it is i and s > sortList's end then
set sortList's item it to s
set SecondList's item it to r
set thirdList's item it to q
end if
end repeat
end sort_items
on Growl_It(gTitle, gMessage)
tell application "GrowlHelperApp"
notify with name "Next4BD" title gTitle description (return & gMessage) application name "Birthdays" with sticky
end tell
end Growl_It
----
Yet another approach is to extract the information you want from the events you want sorted, put them into a list, and use a bubblesort to sort the list. With the list then sorted, you can present the data any way you choose. For instance, this script extracts just the start date and the summary of every event from a calendar later than today and then displays it in a TextEdit document:
set ev_List to {}
tell application "iCal"
set some_events to every event of calendar "SpanawayWard" whose start date > (current date) --and start date < ((current date) + 30 * days)
repeat with x in my some_events
set end of ev_List to {x's start date, x's summary}
end repeat
end tell
repeat with i from length of ev_List to 2 by -1 --> go backwards
repeat with j from 1 to i - 1 --> go forwards
tell ev_List
if (item j)'s item 1 > (item (j + 1))'s item 1 then
set {item j, item (j + 1)} to {item (j + 1), item j} -- swap
end if
end tell
end repeat
end repeat
MakeText(ev_List)
to MakeText(xx)
set txt to ""
repeat with x in xx
set txt to txt & (x's item 1 as string) & space & (x's item 2) & return
end repeat
tell application "TextEdit" to make new document with properties {text:txt}
end MakeText
In my calendar, 90 events sorted in 6 seconds, while taking over 2 minutes on Kim Hunter’s script (link posted in 3rd message above). I have not tried Adam’s script yet.