The Omni Group
These forums are now read-only. Please visit our new forums to participate in discussion. A new account will be required to post in the new forums. For more info on the switch, see this post. Thank you!

Go Back   The Omni Group Forums > OmniFocus > OmniFocus Extras
FAQ Members List Calendar Search Today's Posts Mark Forums Read

AppleScript for deleting completed tasks and projects Thread Tools Search this Thread Display Modes
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, and 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.
Attached Files
File Type: zip Clear Completed OmniFocus (7.0 KB, 406 views)

Last edited by snarke; 2008-09-30 at 02:30 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.
Aha. The presense of "Update Task" in my download folder strongly implies that my script is based on Jasonb's work.
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 can 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. :)
This is great!!! I'm new to OF and with all your help in here it just keeps getting better and better!!
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?

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.
Originally Posted by curt.clifton View Post
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?
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 want 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 not be useful for this script.

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
Thread Thread Starter Forum Replies Last Post
AppleScript for Generating a Report of Completed Tasks gattaca Applying OmniFocus 1 2013-02-24 07:23 AM
Deleting completed recurring Project pakiyabhai OmniFocus 1 for Mac 0 2011-02-04 08:46 PM
Applescript to write todays completed tasks to a text file december76 OmniFocus Extras 7 2010-09-02 12:03 PM
Hide Completed Tasks vs. Deleting Them BillU OmniFocus 1 for Mac 2 2008-01-14 09:51 AM
Add tasks to Completed Projects? type11 OmniFocus 1 for Mac 1 2007-11-30 07:12 PM

All times are GMT -8. The time now is 08:11 PM.

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