OmniFocus and AppleScript
I’m new to Mac, but most know that anything you give me, I’m looking to automate any task that I can get my hands on. As busy as my life is with demands, if I can get a computer to do the work for me, I will. Disaster strikes when anything is too manual in my life-
One of those tasks is my weekly report to my boss telling him what projects I’m on and what I’ve done and what I will do the upcoming week.
Work Task Simplicity with OmiFocus
Its important to keep me on task, so out of the number personal project management programs I tried, I found OmniFocus to be the best suited for what I do for my job. My boss gets credit for recommending it, as I tried out several. What I like about the application the most is that it’s very customizable and I was able to personalize it to fit my needs. This includes the ability to backup your schedule, move it to it’s Pro version with cloud support and also keep it on my phone.
Some of the custom items I added:
- I use a flag to signify that a task is high priority.
- I use different perspectives to categorize views
- I use the notes section like a real note pad and keep all notes from different meetings in OmniFocus.
- Ability to review my projects with the click of a button and see what is on the horizon for the week with different perspectives.
- Back it up to OmniFocus’ cloud or your own choice of backup location.
- Built out low, medium and high context into the system to notify my manager of what priority I thought tasks were in my list.
Apple Script for Reporting
The next feature that sold me was AppleScript. Anyone who works with servers knows the bonus of being able to automate a process via a script and scheduling it in Cron or another host scheduler. Applescript is Mac’s version of shell/command/powershell, whatever reference you wish to use, to script on a Mac.
The syntax is rather simple the what took the longest to learn was the proprietary calls for specific applications, like OmniFocus. Luckily, there are a few people who prefer this method and saved me a lot of time by having a few examples. My needs may have been a bit different from theirs, but they gave me some similar calls that I was able to source from.
Weekly_rpt.scpt
(* ====================================== // Clean up ====================================== *) set scrpt_dir to POSIX path of "/<insert Parent Directory to omnifocus>/com.omnigroup.OmniFocus2/Data/Documents/" --Set Global Working Directory set plist_ to ((path to "pref" as text) & scrpt_dir & "listoftasks.txt") tell application "Finder" if exists file plist_ then display dialog "It exists." delete file plist_ end if end tell set plist2_ to ((path to "pref" as text) & scrpt_dir & "mainProjects.txt") tell application "Finder" if exists file plist2_ then display dialog "It exists." delete file plist2_ end if end tell (* ====================================== // Create Project list-- working on this section- still won't build out flagged tasks ====================================== *) tell application "OmniFocus" set list_Projects to {} set oDoc to default document set nofolder_Projects to (name of (flattened projects of oDoc where its folder is missing value and its status is active)) set folder_Projects to (name of (flattened projects of oDoc where hidden of its folder is false and its status is active)) set projNames to nofolder_Projects & folder_Projects set projects_Sorted to my simple_sort(projNames) set old_delim to AppleScript's text item delimiters set AppleScript's text item delimiters to return set projects_Sorted to projects_Sorted as text set old_delim to AppleScript's text item delimiters set AppleScript's text item delimiters to return set AppleScript's text item delimiters to old_delim set ExportList to "Current List of Working Projects" & return & "---" & return & (current date) & return & return as text tell default document set refFolders to a reference to (flattened folders where hidden is false) repeat with idFolder in (id of refFolders) as list set oFolder to folder id idFolder set ExportList to ExportList & my IndentAndProjects(oFolder) & return end repeat set ExportList to ExportList & return & return & "---" & return & return set week_ago to (current date) - 7 * days set refDoneInLastWeek to a reference to (flattened tasks where (completion date ≥ week_ago) and name of folder of its containing project is not "Personal" and name of folder of its containing project is not "Management" and name of folder of its containing project is not "Someday/Maybe") set {lstName, lstContext, lstProject, lstDate} to {name, name of its context, name of its containing project, completion date} of refDoneInLastWeek set strText to "" repeat with iTask from 1 to length of lstName set {strName, varContext, varProject, varDate} to {item iTask of lstName, item iTask of lstContext, item iTask of lstProject, item iTask of lstDate} if varDate is not missing value then set strText to strText & short date string of varDate & " - " if varProject is not missing value then set strText to strText & " [" & varProject & "] - " set strText to strText & strName if varContext is not missing value then set strText to strText & " *@" & varContext & "*" set strText to strText & " " & return end repeat end tell set old_delim to AppleScript's text item delimiters set AppleScript's text item delimiters to return set projects_Sorted to projects_Sorted as text set AppleScript's text item delimiters to old_delim set ExportList to "Current List of Active Projects:" & return & (current date) & return & return & projects_Sorted as Unicode text set POSIXmr to POSIX path of scrpt_dir & "mainProjects.txt" tell application "System Events" set fid to open for access POSIXmr with write permission write ExportList to fid close access fid end tell end tell (* ====================================== // Create List of Tasks (Completed and Upcoming) ====================================== *) tell application "OmniFocus" set ExportList to "Upcoming Tasks and Recently Completed" & return & "---" & return & (current date) & return & return as Unicode text tell default document set ExportList to ExportList & return & return & "By Project and Due Date" & return & "---" set due_time to (current date) + 8 * days set tasksnm to a reference to (flattened tasks whose flagged is true and completed is false and due date < due_time) --Flagged and isn't completed set {lstName, lstContext, lstProject, lstDate} to {name, name of its context, name of its containing project, completion date} of tasksnm set strText to "" repeat with iTask from 1 to length of lstName set {strName, varContext, varProject, varDate} to {item iTask of lstName, item iTask of lstContext, item iTask of lstProject, item iTask of lstDate} if varProject is not missing value then set strText to strText & " [" & varProject & "] - " --this is good set strText to strText & strName if varContext is not missing value then set strText to strText & " *@" & varContext & "*" --this is used set strText to strText & " " & return end repeat end tell set ExportList to ExportList & strText & "" as Unicode text set POSIXmr to POSIX path of scrpt_dir & "listoftasks.txt" tell application "System Events" set fid to open for access POSIXmr with write permission write ExportList to fid close access fid end tell end tell (* ====================================== // UTILITY SUBROUTINES ====================================== *) on simple_sort(my_list) set the index_list to {} set the sorted_list to {} repeat (the number of items in my_list) times set the low_item to "" repeat with i from 1 to (number of items in my_list) if i is not in the index_list then set this_item to item i of my_list as text if the low_item is "" then set the low_item to this_item set the low_item_index to i else if this_item comes before the low_item then set the low_item to this_item set the low_item_index to i end if end if end repeat set the end of sorted_list to the low_item set the end of the index_list to the low_item_index end repeat return the sorted_list end simple_sort (* ====================================== // Create Top Tasks and Email ====================================== *) set theRecipient to "<insert email address>" --Your manager's email address--Update Email Address set theSubjectOfMessage to "Weekly Status Report for <Enter Your Name>" --The Subject of Email-- Update name in Subject set theSender to "<Enter Your Name>" set POSIXtl to POSIX path of scrpt_dir & "mainProjects.txt" set POSIXmr to POSIX path of scrpt_dir & "listoftasks.txt" tell application "Mail" set theMessage to make new outgoing message with properties {subject:theSubjectOfMessage, sender:theSender} tell content of theMessage make new attachment with properties {file name:POSIXtl} at after last paragraph --Will be used to send second report with completed tasks make new attachment with properties {file name:POSIXmr} at after last paragraph end tell tell theMessage make new to recipient with properties {address:theRecipient} end tell send theMessage end tell
The Reports
What the script will do is create two attachments in the email-
- List of Projects
- List of Upcoming Flagged, (high priority tasks) and list or recently completed tasks.
You can test the script before putting it into production by replacing the email address with your own for the recipient and the making sure the working directory and minor information for the email subject, etc. are correct. One thing I found was that Apples script likes to cache reports, so that’s why I added a clean up step in the report to remove any files before it creates new ones.
Scheduling the Script
Mac comes with a lovely application called the Automator. It’s pretty simple to schedule out a script like this via the Automator. There’s a great support site for learning how to work with Automator if you haven’t before. I’d check them out and that will save me from a lot of explaining… 🙂
By putting this in place, you simply need to keep OmniFocus up to date with all your tasks, completions and the rest will be taken care of by the OmniFocus, the Apple Script and Automator!
Enjoy!
Thank you for sharing! I’ve been a long time OmniFocus user, but never had motivation to play with its AppleScript capability. Your blog just St gave me the push I need. 🙂
i am getting the following error.
error “Can’t make «class FCAr» id “lVyQt2P2EcO” of «class FCDo» of application “OmniFocus” into the expected type.” number -1700 from «class FCAr» id “lVyQt2P2EcO” of «class FCDo»
it appears to be on this line
set ExportList to ExportList & my IndentAndProjects(oFolder) & return
Hi Scott- If you look at this part of the error: “”lVyQt2P2EcO” of «class FCDo» of application “OmniFocus” into the expected type.” number” The challenge is in the data that it’s pulling from your OmniFocus. I’m expecting a number and you’re passing in char in your data. I don’t know if it has to do with the version of OmniFocus or what? I haven’t had this issue, but I don’t use deferred dates, etc. in mine and there are a number of areas this is parsing through dates. I’d look at your tasks to see if you have an odd date format somewhere set.
Pingback: New Apple Script and Perspectives in Omnifocus – DBA Kevlar