OmniFocus to OmniOutliner?

I’ve been thinking about organizing and reporting on OmniFocus tasks, and thought I might do some stuff with them in OmniOutliner. Does anyone know an elegant way of exporting from OF to OO?

Through some old forum posts, I have found that if I export a CSV from OF, open it in Excel, export it as a tab-delimited txt I can open it in OO, but something a little smoother or direct would be nice.

Thoughts?

Thanks!

ScottyJ

1 Like

If you have OmniFocus Pro, you can use this excellent script by Curt Clifton
Export View to OmniOutliner—curtclifton.net
Note that it doesn’t preserve completion status. So if you have completed tasks in your view, they will appear as unchecked in OmniOutliner. I use a modified version that doesn’t have this behaviour.

1 Like

Thanks so much for this, @unlocked2412! Would you be willing to share your modified version?

Cheers!

ScottyJ

You’re welcome.
Sure, no problem.
If you don’t have OmniOutliner running, it opens and creates a document with your default template. If you have documents opened, it will append the content to the end of the front document.

(*
    Modified By: unlocked2412
	This script generates an OmniOutliner outline from the currently displayed view in OmniFocus.
	
	version 1.0, by Curt Clifton
	
	Copyright © 2007–9, 2015, Curtis Clifton
	
	All rights reserved.
	
	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
	
		• Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
		
		• Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
		
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)

tell front document of application "OmniFocus"
	tell document window 1
		set topLevelTrees to every tree of content
	end tell
end tell

tell application "OmniOutliner"
	activate
	--make new document
end tell

createRows(topLevelTrees)
return

-- theItems is a list of top-level trees
on createRows(theItems)
	if (theItems is {}) then return
	createRow(item 1 of theItems)
	createRows(rest of theItems)
end createRows

-- anItem is a tree
on createRow(anItem)
	set rowData to getRowData from anItem
	tell front document of application "OmniOutliner"
		set aRow to make new row at end of every child with properties {topic:(rowTopic of rowData), note:(rowNote of rowData), state:(rowState of rowData)}
	end tell
	createChildren(anItem, aRow)
end createRow

on getRowData from anItem
	using terms from application "OmniFocus"
		set theTopic to name of anItem
		set itemValue to value of anItem
		if (completed of itemValue) is true then
			using terms from application "OmniOutliner"
				set theState to checked
			end using terms from
		else
			using terms from application "OmniOutliner"
				set theState to unchecked
			end using terms from
		end if
		
		try
			
			set theNote to (note of itemValue)
			-- Not all tree nodes have notes, so punt on error
		on error
			set theNote to ""
		end try
	end using terms from
	return {rowTopic:theTopic, rowNote:theNote, rowState:theState}
end getRowData

-- anItem is a tree
-- aRow is an OmniOutliner row
on createChildren(anItem, aRow)
	using terms from application "OmniFocus"
		set itemChildren to every tree of anItem
	end using terms from
	createChildrenHelper(itemChildren, aRow)
end createChildren

-- itemChildren is a list of trees
-- aRow is an OmniOutliner row
on createChildrenHelper(itemChildren, aRow)
	if (itemChildren is {}) then return
	set childItem to item 1 of itemChildren
	set childData to getRowData from childItem
	tell front document of application "OmniOutliner"
		set childRow to make new row with properties {topic:(rowTopic of childData), note:(rowNote of childData), state:rowState of childData} at after last child of aRow
	end tell
	createChildren(childItem, childRow)
	createChildrenHelper(rest of itemChildren, aRow)
end createChildrenHelper
2 Likes

Thanks again, @unlocked2412!

Unfortunately, something in the script language (I think relating to identifying whether or not a task is completed) is erroring on me. Any thoughts about how to troubleshoot? Screen:

I’ve tried with different selected tasks, and still get the same error.

Really appreciate your help with this!

ScottyJ

You’re welcome, @deturbulence.
Sure, I can help.
I think you are trying to run the script with a context based perspective showing in the front document window. It only works with project based perspectives, since contexts don’t have completion status.

You don’t need to select any task. For example, you multi-select 3 projects in the sidebar and they will display. When you run the script, what you see in the front document window is exported (unless it’s a context based perspective).

Ah, that makes sense!

I’m still erroring, though, referring to not being able to get completion status of a folder (which makes sense, since like a context, a folder cannot be completed), but then errors this way if I move the projects to the root of my tree (i.e. not in a folder):

error "OmniFocus got an error: Can’t get completed of value of tree 1 of content of document window id 4959 of default document." number -1728 from completed of value of tree 1 of content of document window id 4959 of default document

Thoughts? Thanks for sticking with me here :)

ScottyJ

You’re welcome, I’m sticking with you!

That’s right. A folder doesn’t have completion status, nor the top level heading. So you need to un-check Show folders in the outline, I think.

Ah ha! That did it.

The export isn’t quite as rich as my inelegant method above, though - I was hoping for columns for each of the attributes, things like context, due date, estimated time, etc. in order to manipulate and group and examine the things with summary rows in OO.

I suppose the script could be extended, or maybe there’s an easier way to process the CSV into a tab-delimited text.

Thanks for all your help to make this work, though, @unlocked2412! I really appreciate it.

ScottyJ

I’m glad it worked!

That’s interesting. In the future, if I have some spare time, I want to do something similar. I think it’s possible. And I will let you know.

You’re welcome, @deturbulence!

P.D.: Just for the record: The script gets the top level trees, and when it tries to get the completed property of tree 1 (top level heading), it shows an error.

2 Likes

High five, @unlocked2412.

I’m glad that you were able to solve it via AppleScript, but I continue to hope that more export features are put into the application. I’ve been asking for this for 10 years!

It would be very helpful to many users. If you agree, I would encourage you to contact the OmniGroup.

2 Likes

@unlocked2412, is there a way to make this script create a new document with my default template instead of a new (bare) document? I have this trouble in other scripts too: I cannot apply any themes to them and have to copy and paste into a new OO file with ⌘N .

Unfortunately, it’s not possible to apply a template via Applescript. But, I found a workaround. Do you have this option checked?

Yes, I have called the template “Default.”

Ok, so you can try this. If OO is running, it creates a new document with your default template and a new row. If OO isn’t running, it adds a row at the end of the document.
Is this an improvement to your workflow? If the answer is yes, we can add more complexity.

tell application "OmniOutliner"
	activate
	tell front document
		make new row with properties {topic:"Hello World"} at end of every child
	end tell
end tell

Thanks for still working with me. With OmniOutliner quit, the script gives me a new file from my default template with a new “Hello World” row.

But with OmniOutliner running and no outlines open, running the script I get the following error: “OmniOutliner got an error: Can’t get document 1. Invalid index.” If I click OO on the Dock I get a new default template without the script.

You’re welcome.
I understand. I found a better solution.
Locate the template in the finder.

Paste it in the property the_template_path

Code:

property the_template_path : ""

set the_template to POSIX file the_template_path
tell application "OmniOutliner"
	open the_template
	tell front document
		delete (every row)
		make new row with properties {topic:"Hello World"}
	end tell
end tell

This script is magic! Love it!