Quote:
Originally Posted by Ken Case
There's a sample "Publish to iCal" script which runs through all your contexts and creates a new calendar for each one (named "OF: [Context]"), adding any available tasks from that context to that calendar.
|
It's a great script, except for two minor annoyances — it omits nested contexts, and it crashes when you run it, unless you happen to already have calendars named OF: <context> for all of your contexts :-)
A somewhat improved script is provided below. There's an property up top you can edit to control whether the script exports available or remaining actions. It traverses into nested contexts. It does not print the full project name for a project nested in a folder; that will be a fine learning exercise for someone who needs it. No attempt is made to make the calendar events show the amount of time required for various
due items, because I don't believe that is useful in most cases. If you feel otherwise, you know where the sources are, knock yourself out :-)
Code:
(*
Copyright 2007 The Omni Group. All rights reserved.
$Header: svn+ssh://source.omnigroup.com/Source/svn/Omni/branches/OmniFocus/1.x/OmniGroup/Applications/OmniFocus/Extras/SampleScripts/Publish%20to%20iCal.applescript 93889 2007-11-02 18:06:50Z bungi $
*)
property pExportAvailableTasksOnly : false -- if false, export remaining tasks; if true, export available tasks
global currentTargetCalendar
tell first document of application "OmniFocus"
repeat with aContext in flattened contexts
set MyContextID to (id of aContext)
set MyContext to context id MyContextID
CreateContextCalendar of me from MyContext -- also deletes existing calendar
if ((count of (my GetTasks(MyContext))) > 0) then
PublishContext of me from MyContext
end if
end repeat
end tell
tell application "iCal" to activate
on GetTasks(SomeContext)
using terms from application "OmniFocus"
if (pExportAvailableTasksOnly is true) then
return tasks of SomeContext where blocked is false
else
return tasks of SomeContext where completed is false
end if
end using terms from
end GetTasks
on CreateContextCalendar from SomeContext
tell application "iCal"
set CalendarName to "OF: " & my FullContextName(SomeContext)
try
delete (first calendar whose name is CalendarName)
end try
using terms from application "OmniFocus"
set ContextTasks to my GetTasks(SomeContext)
end using terms from
set currentTargetCalendar to make calendar with properties {name:CalendarName}
end tell
end CreateContextCalendar
on PublishContext from SomeContext
using terms from application "OmniFocus"
PublishContextTasks of me from SomeContext
repeat with childContext in contexts of SomeContext
PublishContext of me from childContext
end repeat
end using terms from
end PublishContext
on PublishContextTasks from SomeContext
using terms from application "OmniFocus"
set MyTasks to my GetTasks(SomeContext)
repeat with aTask in MyTasks
set taskName to name of aTask
set taskProject to containing project of aTask
set completionDate to completion date of aTask
set dueDate to due date of aTask
if (dueDate is not missing value) then
set dueDate1 to dueDate + 60 -- if we make zero-length appointments, iCal puts them on top of each other. Make them a minute long and it spreads them out a bit.
end if
local MyEvent
using terms from application "iCal"
tell currentTargetCalendar
if completionDate is equal to missing value and dueDate is not missing value then
if taskProject is not equal to missing value then
set MyEvent to make new event at end of events with properties {summary:my FullContextName(SomeContext) & ": " & taskName & " [" & name of taskProject & "]", start date:dueDate, end date:dueDate1}
else
set MyEvent to make new event at end of events with properties {summary:my FullContextName(SomeContext) & ": " & taskName & " [Inbox]", start date:dueDate, end date:dueDate1}
end if
end if
end tell
end using terms from
end repeat
end using terms from
end PublishContextTasks
-- return full name of context, or "(None)"
-- uses ":" as hierarchy separator, as OmniFocus does not appear to expose
-- the value conveniently
on FullContextName(SomeContext)
using terms from application "OmniFocus"
local oContext
local strContextName
set strContextName to ""
set oContext to SomeContext
if (oContext is missing value) then
return "(None)" -- easy case!
end if
-- if there is a context set, we need to construct the full name,
-- climbing up the tree to the top. We take the name of our starting
-- point, then look at the container. Each time the container is not
-- of class document, there's another layer, and we tack its name on
-- to the front of the string.
set strContextName to name of oContext
repeat while (class of (container of oContext) is not document)
set strContextName to ":" & strContextName
set oContext to container of oContext
set strContextName to name of oContext & strContextName
end repeat
return strContextName
end using terms from
end FullContextName