Mac

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-

lucy_disaster

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:

  1.  I use a flag to signify that a task is high priority.
  2. I use different perspectives to categorize views
  3. I use the notes section like a real note pad and keep all notes from different meetings in OmniFocus.
  4. Ability to review my projects with the click of a button and see what is on the horizon for the week with different perspectives.
  5. Back it up to OmniFocus’ cloud or your own choice of backup location.
  6. 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 dateweek_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-

  1. List of Projects
  2. 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!

 

Kellyn

http://about.me/dbakevlar

4 thoughts on “OmniFocus and AppleScript

  • 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

  • DBAkevlar

    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

Comments are closed.