The Omni Group Forums

The Omni Group Forums (
-   OmniFocus Extras (
-   -   AppleScript for deleting completed tasks and projects (

snarke 2008-09-30 02:11 PM

AppleScript for deleting completed tasks and projects
1 Attachment(s)
I know some people love being able to refer back to tasks they've completed,
and that the 1.1 version has an "Archive Completed Tasks" option, but for those of us who want completed tasks to go away forever and not ever turn up in searches or when using "Any Status" views or whatever, and are sticking with 1.0.3 for now, here's a script to clear out the deadwood.

The script defaults to clearing items that were completed more than 30 days ago, but that's easily changed by editing the script.

The script works its way through the 'default document,' descending into folders and projects as necessary. If a project is set to repeat, then the script skips over that project (it didn't do that until I read about the bug in OF1.1 {grin}) and all the items contained therein.

A task will be deleted if: it is marked as completed, it does not repeat, and if the completion date is 30 or more days in the past. A project will be deleted if it meets those criteria, [i]and[/i] is marked "done."

Feedback regarding the script, positive or negative, is always welcome.

I put my copy of this script in [Home Folder]/Library/Scripts/Applications/OmniFocus

Since I have my script menu turned on, I can select "Clear Completed Items" from the script menu when I'm in OmniFocus.

snarke 2008-09-30 02:29 PM

Oh, yea. And "thank you" to whomever's script I stole to write this. They didn't put their name in it anywhere, and I'm not sure how long I've had it sitting around on my desktop before going back today to clean it up and post it, but it was full of variable names that I wouldn't have used, so I definitely built it on top of somebody else's code.

snarke 2008-09-30 02:38 PM

Aha. The presense of "Update Task" in my download folder strongly implies that my script is based on [URL=""]Jasonb's work[/URL].

snarke 2008-10-03 07:05 PM

Bug Fix
Apparently the set of users who want to delete old stuff from OmniFocus <1.1 is a smaller set than I thought, since nobody's posted about a bug I ran across today. The script fails if it hits a repeating project with no subsections. I'm not entirely sure a project [I]can[/I] contain other sections, so it's presumably a fairly common condition.

Anyway, here's the fixed Version 1.3 of the script, for the one person out there who might eventually download and use it. It also now pops up an alert when it's done running, reporting on how many items were actually deleted. Finally, now a project that's old enough will get axed if it's either "completed" or "dropped."

-- Dave Howell,
-- v1.3, October 3rd, 2008

-- 1.2: First publically released version.
-- 1.3: Added reporting window at end of run, and added "dropped" to valid states for a project to be deleted.

-- if a task or project was completed more than DaysBeforeDeleting days ago, then delete it
property DaysBeforeDeleting : 30

global Today -- loading the current date into Today saves a bit of time
global DeletedItemCount -- how many things got deleted?

on run
set Today to current date
set DeletedItemCount to 0
tell application "OmniFocus"
set CurrentDocument to default document
tell CurrentDocument
if number of document window is 0 then
make new document window with properties {bounds:{0, 0, 1000, 500}}
end if
end tell
set SectionList to every section of CurrentDocument
end tell
tell application "OmniFocus" to display alert "Expired Item Cleanup Completed" message (DeletedItemCount as rich text) & " items removed." buttons {"OK"} default button 1 giving up after 30
end run

-- We work through the lest backwards (ListCount to 1 by -1) because if we delete
-- a section, then the numbering of all the later sections changes. This frequently
-- causes a structure like "repeat with CurrentSection in items of SectionList" to malfunction.
-- However, see note at end of document. if the list is empty, then the contents of the
-- Repeat loop (count from 0 to 1 by -1) will simply be skipped.

on ProcessSections(SectionList)
using terms from application "OmniFocus"
repeat with SectionIndex from (count of SectionList) to 1 by -1
tell item SectionIndex of SectionList
if class is project then
if repetition is missing value then
my ProcessTasks(every task)
my DeleteIfOldEnough(item SectionIndex of SectionList)
end if -- if it *does* repeat, then don't delete it.
else -- not a project. Must be a folder.
my ProcessSections(every section)
end if
end tell
end repeat
end using terms from
end ProcessSections

on ProcessTasks(TaskList)
using terms from application "OmniFocus"
repeat with TaskIndex from (count of TaskList) to 1 by -1
set CurrentTask to item TaskIndex of TaskList
my ProcessTasks(every task of CurrentTask)
end repeat
end using terms from
end ProcessTasks

-- I wrote this routine as a whole bunch of sequential 'if' statements to make it really clear
-- what has to be true before a task or project gets deleted. If "AnItem" is a folder,
-- it will cause an error since folders don't have a "completed" property. So don't pass it any folders!

to DeleteIfOldEnough(AnItem)
tell application "OmniFocus" to tell AnItem
if completed is missing value or not completed then return -- this item isn't completed
if repetition is not missing value then return -- this item will repeat at a later date
if class of AnItem is project and not (status is done or status is dropped) then return --this project hasn't been marked as "done"
if (Today - (completion date)) / days < DaysBeforeDeleting then return --this item was completed too recently
delete -- Well, guess there's no reason not to delete this item...
end tell
set DeletedItemCount to DeletedItemCount + 1
end DeleteIfOldEnough

-- Endnote: if you ask many applications for a list of something (like mail messages or ToDo items
-- or whatever) you might get back something like {thingy 1 of application, thingy 2 of application}.
-- The problem with this is, if you start through the list, but delete "thingy 1," then
-- try to ask the system about "thingy 2," well, there ISN'T a "thingy 2" anymore. The former
-- thingy two just became thingy one. Apple's "Mail" program used to do this constantly, so deleting
-- Mail messages was a big-time pain in the ass. (For all I know, the problem's still there; I had to
-- rewrite my scripts years ago to work around it, and I'm not going to waste time fiddling with them
-- now to see if things are better.)
-- Omni, not all that surprisingly, does it the right way, passing back references that use unique, stable
-- IDs, like {task id "cBq9eJgsG-C" of document id "fSRWe8cGivB", project id "npto5zRxqHL" of
-- document id "fSRWe8cGivB"}, so even if one of the items in the list is deleted, the remaining members
-- are as valid as they were when the list was first constructed. Therefore, it should be possible to
-- count forwards instead of backwards and still have the script work properly. But I know the backwards
-- count works, so I'm not (yet) going to bother fiddling with it. :)

Christopher 2008-10-04 05:39 PM

This is great. Thanks.

Pauly17 2009-01-18 07:31 PM

This is great!!! I'm new to OF and with all your help in here it just keeps getting better and better!!

curt.clifton 2009-01-19 04:39 PM

Note that there is a built-in Archive feature (see File menu) in OF 1.5 that seems to make this script obsolete, unless I'm misunderstanding what the script does. I can't imagine anyone still running OF 1.0.3. Is there a reason to do so?

whpalmer4 2009-01-19 11:46 PM

The dates on the script and contemporaneous discussion were prior to 1.5 going out as an official release. I'd guess our recent poster was searching the archive and just happened to stumble across this without realizing it applied to a prior version.

snarke 2009-01-20 03:22 PM

[QUOTE=curt.clifton;53936]Note that there is a built-in Archive feature (see File menu) in OF 1.5 that seems to make this script obsolete, unless I'm misunderstanding what the script does. I can't imagine anyone still running OF 1.0.3. Is there a reason to do so?[/QUOTE]

Run 1.0.3? Probably not. But I can think of at least two reasons why one might still use the script instead of the archive function.

1. You don't [i]want[/i] to archive it, you just want it gone. Why have this archive file cluttering up your drive?

2. You want to have finer control over the cleanup than the archive function provides. Deciding what gets deleted when could be subject to arbitrarily complex conditions in the AppleScript.

And there's the not-inconsiderable value of just having a working script to help one figure out how the heck to make something else happen in OmniFocus. Even Omni's AppleScript Dictionaries are sometimes bafflingly cryptic. It took me a fair amount of time to figure out how the heck "sections" actually work, especially since there's also the whole "tree"-based structure, which turned out to [i]not[/i] be useful for this script.

All times are GMT -8. The time now is 04:48 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2019, vBulletin Solutions, Inc.