Migrating from OmniFocus?

I have a huge database in OmniFocus. I love OF but they are committed to the view that data should not be stored with the actions - they say the database should be kept small. OF does not efficiently deal with situations when data is embedded with the actions. I really need to keep not only a hierarchical organization of my ideas, but to have the relevant data files with each item. So, I’m considering moving to Devonthink. Does anyone know of a way to migrate my data from OmniFocus to DT?

DEVONthink and OmniFocus serve profoundly different purposes.OmniFocus is not great at, nor is it intended to, organize information. It is intended to organize actions. DEVONthink is not great at, nor is it intended to, organize tasks or actions. In my opinion one could never replace another, they are complimentary programs. Why not use DEVONthink and OmniFocus in tandem in a way that capitalizes on each of their strengths?

One feature that might be helpful for you is the ability to create clickable links to any DEVONthink content. If you have content-heavy actions, store and organize the content in DEVONthink, which is its purpose, and add a link to that content in the Notes section of an OmniFocus action.

For example, I have DEVONthink groups devoted to each of my research informants/participants. If I have an OmniFocus action like “Follow-up with Person X” or “Outstanding consent form for Person X” I’ll paste a link to the DEVONthink group that corresponds to that person so I can have easy access to the group that contains my notes on them, a link to their address book contact card, and all other relevant info about that individual that could never live in OmniFocus. It also means that when I receive whatever I need from that person, I can just click the link to deposit their consent form or whatever the item is at the same time as I complete the action in OmniFocus.

Likewise, I might have something like “Review revisions on Manuscript XYZ”. That manuscript is in a folder in Dropbox and indexed by DEVONTthink. I’ll paste a DEVONthink link to that manuscript in the OmniFocus action so I can easily access it and never even have to dig around or search.

I wouldn’t in a million years replace OmniFocus with DEVONthink or vice versa because neither does the job of the other. Have you given DEVONthink’s Item Links a try with OmniFocus? Does this ease some of your struggles?

1 Like

This makes a lot of sense, and I get it. The thing is, I’ve clearly been using OF mostly as an information manager - my tasks are not so much precisely timed activity lists, as much as hierarchical outline of dependent tasks for various projects. And each of those has a ton of info that goes with it, which I’ve been embedding in OF. So, yes, I could go through all of those and add links to DT content. In order to do that, I’m hoping to find an automated way to import all my OF content into DT, otherwise I’ll have to move each action and its many attachments/text to DT manually. Any suggestions? And big picture: why not move to DT entirely - what does OF do that DT cannot do? It seems to me that maybe I need to only be using DT, since I don’t really follow the GTD methodology strictly. In this case, again I’m back to the issue of how I get my content from OF to DT without manually moving hundreds and hundreds of items. What do you think?

Thank you!

As far as migrating the content over to DEVONthink, not sure how best to do that, especially since you haven’t indicted in what format the information is kept in OmniFocus (embedded files? Referenced files? Plain text in the Notes section? those will all require different approaches to migration).

Why not move to DT entirely? I’m not a GTD guy either, but DT doesn’t schedule tasks, DT doesn’t have due dates. DT doesn’t give me easy access to these things on my phone, DT doesn’t give alerts, DT doesn’t allow for recurring or repeating tasks, the list goes on.

Ultimately I just find the DEVONthink is not extremely convenient for organizing lists of tasks and projects, whereas OmniFocus is very good.

I don’t mind spending time digging and rooting around for this or that file in DEVONthink, but I sure don’t want to have to spend any time trying to find the list of actions associated with a given project. Tasks are in OmniFocus, links made where appropriate to the content in DT. Content is in DEVONthink.

it's mostly embedded files and plain text.  I guess the best thing would be a script that took all the embedded files and moved them into DT and replaced them with the link in OF. But I'd be happy with a script that moved everything into DT first, just so I have a copy.  

And having it on my iPhone/iPad is an important aspect. The complexities of sync (the fact that people have complained about losing data via Dropbox sync on-line) is what's kept me from plunging in all the way so far.

Acc. to their website, OmniFocus Pro has ”extensive Applescript support", so it appears that scripting a transfer would be possible.

any idea where to advertise for someone who knew the scripting hooks for DT well enough to write such a script?

I know DT scripting well (seeing as it’s part of my job - haha!). I just downloaded OmniFocus a minute ago so I have no idea of the dictionary and capabilities. You could post something here DEVONthink: Scripting, but bear in mind, these are volunteers so you may have to be patient.

Also, a well-defined brief is best. You should think about what you want to happen. Otherwise, things will ping-pong back and forth with, “Oh wait… can it do this to? And how about this…? Could you add that…?” Again, as people are volunteering - in this section especially… :smiley:

Note: there is a script for adding reminders to OmniFocus, that may also be interesting to look at. (Building the script is more fun than just asking for one. Cheers! :mrgreen: )

.

I believe Rob stopped using OmniFocus a long time ago, around the time that the first OmniFocus 2 alpha/beta appeared. I wouldn’t expect that his scripts would be of much help, unless some of his OF 1 scripts are still compatible with OF 2.

No. Rob’s scripts are still very useful and current, sorry. But we can forget that advice.

Do you have a link to the scrip that does what the OP requested?

I would be willing to pay someone as a consultant to produce this (not huge $, but can pay).

no doubt. I used to do a lot of coding and would love to just do it myself. The problem is I am now a biologist running a large research lab and I just don’t have time for that anymore :frowning: I just need it to work and move my data…

How many “entries” do you have in your OF “database”? Depending on how you want to organize things in DT, the technicalities of transferring might only be a small part vs. grouping and tagging the entries in DT. If you have to go through them one by one anyway to do that, you might have to bite the bullet and do the transfer by hand. If we are talking about 10,000 OF entries, that would obviously not work.

not sure, probably on the order of 1000 - how to count all the Actions? Anyway, the grouping would just be hierarchical, following how I have them set up in OF (by Project, then Actions, then sub-actions, etc.) so I think a script can do it automatically.

I’d recommend to let the “verbs” in OmniFocus and put/link the “nouns” in you DevonThink database(s), as this old post on the Omni forum suggests:

forums.omnigroup.com/showpost.ph … ostcount=6

And, despite I’m a huge fan of Keyboard Maestro, Hazel and TextExpander, I wouldn’t do this using a script, but create a “gtd database” or several project databases as needed and fill them with folders and files manually.

This way, you can perhaps get rid of quite a few dead projects instead of putting them in your new structure just because the script makes it so easily possible.

I did the “script way” when going from OmniFocus to Things and it’s a pain to identify and delete the “garbage” that came over in a new system you don’t know as good as your old one …

To see how much actions you have in OF, do

  1. view all
  2. show context perspective
  3. CMD+A

To see all your file attachments, do 1. 2. and Window > Attachment list.

Just my 2p,
Franz-Josef

Here’s an OmniFocus script that Rob Trew posted a while ago. It reveals various statistics about your OmniFocus database.

property pTitle : "OmniFocus: Quick Stats"
property pVersion : "2.01"

property pstrDBPath : "$HOME/Library/Containers/com.omnigroup.OmniFocus2/Data/Library/Caches/com.omnigroup.OmniFocus2/OmniFocusDatabase2"
property pblnToClipboard : true
property pblnSubTreeCounts : true
property pToClipboard : "Copy list to clipboard"


-- Ver 0.8 adds clipboard option to dialogue
-- Ver 0.9 gives an error message if the cache schema has changed, leading to an SQL error in the script
-- Ver 1.0 slight simplification of the code
-- Ver 1.1 added count of Pending projects
-- Ver 1.2 added a count of available actions
-- Ver 1.3 added a break-down of unavailable actions
-- Ver 1.4 added count of Current projects to complement Pending projects
-- ver 1.5 replaced Applescript time function with SQL time expression
-- Ver 1.7 Reorganizes menu, and attempts to enable access for .macappstore installations of OF
--Ver 1.8 Adjusts handling of variant bundle identifiers generally
-- Ver 2.00 Redraft of task breakdown, with progressive narrowing of criteria ...
-- Ver 2.01 Change for OF2.  pstrDBPath reset


tell application "Finder"
	if pstrDBPath ≠ "" then
		set strCmd to "sqlite3 -separator ': ' \"" & pstrDBPath & "\" " & quoted form of ("
	select \"INBOX GROUPS & ACTIONS\", count(*) from task where (inInbox=1);
	select \"    Inbox action groups\", count(*) from task where (inInbox=1) and (childrenCount>0);
	select \"    Inbox actions\", count(*) from task where (inInbox=1) and (childrenCount=0);
	select null;
	select \"FOLDERS\"	, count(*) from folder;
	select \"    Active folders\", count(*) from folder where effectiveActive=1;
	select \"    Dropped folders\", count(*) from folder where effectiveActive=0;
	select null;
	select \"PROJECTS\", count(*) from projectInfo where containsSingletonActions=0;
	select \"    Active projects\", count(*) from projectInfo where (containsSingletonActions=0) and (status=\"active\");
	select \"            Current projects\", count(*) from projectInfo p join task t on t.projectinfo=p.pk where (p.containsSingletonActions=0) and (p.folderEffectiveActive=1) and (p.status=\"active\") and (t.dateToStart is null or t.dateToStart < (strftime('%s','now') - strftime('%s','2001-01-01')));
	select \"            Pending projects\", count(*) from projectInfo p join task t on t.projectinfo=p.pk where (p.containsSingletonActions=0) and (p.folderEffectiveActive=1) and (p.status=\"active\") and (t.dateToStart > (strftime('%s','now') - strftime('%s','2001-01-01')));
	select \"    On-hold projects\", count(*) from projectInfo where (containsSingletonActions=0) and (status=\"inactive\");
	select \"    Completed projects\", count(*) from projectInfo where (containsSingletonActions=0) and (status=\"done\");
	select \"    Dropped projects\", count(*) from projectInfo where (containsSingletonActions=0) and (( status=\"dropped\") or (folderEffectiveActive=0));
	select null;	
	select \"SINGLE ACTION LISTS\", count(*) from projectInfo where containsSingletonActions=1;
	select \"    Active single action lists\", count(*) from projectInfo where (containsSingletonActions=1) and (status=\"active\");
	select \"    On-hold single action lists\", count(*) from projectInfo where (containsSingletonActions=1) and (status=\"inactive\");
	select \"    Completed single action lists\", count(*) from projectInfo where (containsSingletonActions=1) and (status=\"done\");
	select \"    Dropped single action lists\", count(*) from projectInfo where (containsSingletonActions=1) and (( status=\"dropped\") or (folderEffectiveActive=0));
	select null;
	select \"CONTEXTS\", count(*) from context;
	select \"    Active contexts\", count(*) from context where (effectiveActive=1) and (allowsNextAction=1);
	select \"    On-hold contexts\", count(*) from context where (effectiveActive=1) and allowsNextAction=0;
	select \"    Dropped contexts\", count(*) from context where effectiveActive=0;
	select null;
	select \"ACTION GROUPS\", count(*) from task where (projectinfo is null) and (childrenCount>0);
	select \"    Remaining action groups\", count(*) from task where (projectinfo is null) and (dateCompleted is null) and (childrenCount>0);
	select \"    Completed action groups\", count(dateCompleted) from task where (projectinfo is null) and (childrenCount>0);
	select null;
	select \"ACTIONS\", count(*) from task where (projectinfo is null) and (childrenCount=0);
	select \"    Completed actions\", count(dateCompleted) from task where (projectinfo is null) and (childrenCount=0);
	select \"    Dropped project actions\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp where (projectinfo is null) and (childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is not null and (tp.status=\"dropped\" or tp.folderEffectiveActive=0));
	select \"    Dropped context actions\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and c.effectiveActive= 0;
	select \"    Remaining actions\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and (tp.context is null or c.effectiveActive= 1);
	select null;
	select \"        Actions in Projects on hold\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and (tp.context is null or c.effectiveActive= 1)
				and (tp.containingProjectInfo is not null and tp.status=\"inactive\");
	select \"        Actions in Contexts on hold\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and (tp.context is null or c.effectiveActive= 1)
				and (tp.containingProjectInfo is null or tp.status!=\"inactive\")
				and (tp.context is not null and c.allowsNextAction=0);
	select null;
	select \"        Blocked actions\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and (tp.context is null or c.effectiveActive= 1)
				and (tp.containingProjectInfo is null or tp.status!=\"inactive\")
				and (tp.context is null or c.allowsNextAction=1)
				and tp.blocked=1;
	select \"        	Sequentially blocked\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and (tp.context is null or c.effectiveActive= 1)
				and (tp.containingProjectInfo is null or tp.status!=\"inactive\")
				and (tp.context is null or c.allowsNextAction=1)
				and tp.blocked=1
				and tp.blockedByFutureStartDate=0;
	select \"        	Awaiting start date\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and (tp.context is null or c.effectiveActive= 1)
				and (tp.containingProjectInfo is null or tp.status!=\"inactive\")
				and (tp.context is null or c.allowsNextAction=1)
				and tp.blocked=1
				and tp.blockedByFutureStartDate=1;				
	select null;			
	select \"        Available actions\", count(*) from (task t left join projectinfo p on t.containingProjectinfo=p.pk) tp left join context c on tp.context=c.persistentIdentifier where (projectinfo is null) and (tp.childrenCount=0)  and (dateCompleted is null) 
				and (tp.containingProjectinfo is null or (tp.status !=\"dropped\" and tp.folderEffectiveActive=1))
				and (tp.context is null or c.effectiveActive= 1)
				and (tp.containingProjectInfo is null or tp.status!=\"inactive\")
				and (tp.context is null or c.allowsNextAction=1)
				and tp.blocked=0;

	")
		
		-- 		try
		
		set strList to do shell script strCmd
		-- 		on error
		-- 			display dialog "The SQL schema for the OmniFocus cache may have changed in a recent update of OF." & return & return & ¬
		-- 				"Look on the OmniFocus user forums for an updated version of this script." buttons {"OK"} with title pTitle & "Ver. " & pVersion
		-- 			return
		-- 		end try
		
		activate
		if button returned of (display dialog strList buttons {pToClipboard, "OK"} default button "OK" with title pTitle & " Ver. " & pVersion) ¬
			is pToClipboard then tell application id "com.apple.finder" to set the clipboard to strList
	else
		display dialog "OmniFocus cache not found ..." buttons {"OK"} default button 1 with title pTitle & " Ver. " & pVersion
	end if
end tell

on FileExists(strPath)
	(do shell script "test -e " & strPath & " ; echo $?") = "0"
end FileExists

on GetCachePath()
	try
		tell application "Finder" to tell (application file id "OFOC") to "$HOME/Library/Caches/" & its id & "/OmniFocusDatabase2"
	on error
		error "OmniFocus not installed ..."
	end try
end GetCachePath

As a subscriber to the “OmniFocus for verbs, DTPO for nouns” approach I would be happy to direct any users on this forum to particular resources on the OmniFocus fora. Just ask!

Here are some export ideas for the OP, although I second the suggestion by @schelmenzunft that automating the export would bring in deadwood from old projects.

ofexport2: https://github.com/psidnell/ofexport2

export to TaskPaper format which might be the easiest way to take advantage of DTPO’s textual brilliance if you have copious notes for tasks and projects:

-- OMNIFOCUS TO TASKPAPER EXPORT

-- Ver 0.5 Spaces in context names mapped to underscore
-- Ver 0.4 Adapts to the new requirement that all child bullets are preceded by space
-- Ver 0.3  2007 Dec 22
-- Now exports whatever is displayed and selected in right-hand content panel

property pblnToMail : false

on run
	tell application "OmniFocus"
		tell default document
			if number of document window is 0 then
				make new document window with properties {bounds:{0, 0, 1000, 500}}
			end if
		end tell
		
		tell document window 1 of front document
			set lstTrees to selected trees of content
			if (count of lstTrees) = 0 then
				try
					display dialog "Nothing selected in the right-hand panel." & return & return & "Select material to export, and try again." & return
				end try
			else
				-- Generate a TaskPaper string of the selected content
				set blnContext to («class FCvm» is not equal to "project")
				set lngIndent to 0
				set strTP to my ExportTrees(lstTrees, lngIndent, blnContext)
				
				if pblnToMail then
					-- Make Mail message
					try
						strTP
						tell application "Mail"
							set oMsg to make new outgoing message with properties {content:strTP & return & return}
							set visible of oMsg to true
							activate
						end tell
					on error
						display dialog "No tasks selected"
					end try
				else
					set oFile to choose file name "Export as:" default name ¬
						"OmniFocus.taskpaper" default location (path to desktop)
					set strFile to (POSIX path of oFile)
					do shell script "echo " & quoted form of strTP & " > " & strFile
				end if
			end if
		end tell
	end tell
end run

on ExportTrees(lstTrees, lngIndent, blnContextView)
	-- if the tree is a task give full detail
	-- else just name and any note
	set strTP to ""
	set strIndent to ""
	
	repeat lngIndent times
		set strIndent to strIndent & tab
	end repeat
	
	tell application "OmniFocus"
		repeat with oTree in lstTrees
			
			set oValue to value of oTree
			set clValue to class of oValue
			if clValue ≠ item then
				set strName to name of oValue
				if length of strName > 0 then set strName to my EscAmpersand(strName)
				
				set strNote to note of oValue
				if length of strNote > 0 then set strNote to my EscAmpersand(strNote)
			else
				set strName to ""
				set strNote to ""
			end if
			
			if (clValue is not equal to task) and (clValue is not equal to inbox task) then
				
				-- Project or Folder
				if clValue is not equal to folder then
					if clValue is not equal to project then
						--Inbox (No details)
						set oWin to first document window of front document
						set strName to name of first selected tree of (sidebar of oWin)
						if strName ≠ "Inbox" then set strName to ""
						set strTP to strTP & strName & ":" & return
					else
						-- Project (Name and possibly note)
						if length of strName > 0 then
							set strTP to strTP & strIndent & strName & ":" & return
							if length of strNote > 0 then ¬
								set strTP to strTP & strIndent & strNote & return
						end if
					end if
				else
					-- Folder (Just name - no note)
					set strTP to strTP & strIndent & strName & ":" & return
				end if
				
			else -- Task (with details from specified columns)
				
				
				-- set recFields to {fldName:name of oValue, fldNote:note of oValue, fldDone:completed of oValue, fldContext:strContext, fldStartDate:start date of oValue, flddueDate:due date of oValue, fldDoneDate:completion date of oValue, fldDuration:estimated minutes of oValue, fldFlagged:flagged of oValue}
				
				
				-- write first line of task, followed by tags
				set lstLines to paragraphs of strName
				
				set strTP to strTP & strIndent & "- " & item 1 of lstLines
				
				-- Add any tags
				set oContext to context of oValue
				if oContext is not equal to missing value then
					set strContext to name of oContext
					set {dlm, my text item delimiters} to {my text item delimiters, space}
					set lstContext to text items of strContext
					set my text item delimiters to "_"
					set strContext to lstContext as string
					set my text item delimiters to dlm
					
					set strTP to strTP & " @" & strContext
				end if
				
				set dteStart to defer date of oValue
				if dteStart is not equal to missing value then ¬
					set strTP to strTP & " @start(" & my DateString(dteStart) & ")"
				
				set dteDue to due date of oValue
				if dteDue is not equal to missing value then ¬
					set strTP to strTP & " @due(" & my DateString(dteDue) & ")"
				
				
				set lngDurn to estimated minutes of oValue
				if lngDurn is not equal to missing value then ¬
					set strTP to strTP & " @mins(" & (lngDurn as string) & ")"
				
				
				if flagged of oValue then set strTP to strTP & " @flag"
				
				if completed of oValue then set strTP to strTP & " @done"
				set strTP to strTP & return
				
				-- write any remaining lines of task as note text
				if length of lstLines > 1 then
					repeat with strLine in rest of lstLines
						set strLine to my RTrim(strLine)
						if length of strLine > 0 then
							-- change any trailling : to :-, to avoid misinterpretation as a header
							if last character of strLine ≠ ":" then
								set strTP to strTP & strIndent & strLine & return
							else
								set strTP to strTP & strIndent & strLine & "-" & return
							end if
						end if
					end repeat
				end if
				
				-- append any attached note text
				set lstLines to paragraphs of strNote
				
				repeat with strLine in lstLines
					set strLine to my RTrim(strLine)
					if length of strLine > 0 then
						-- change any trailling : to :-
						if last character of strLine ≠ ":" then
							set strTP to strTP & strIndent & strLine & return
						else
							set strTP to strTP & strIndent & strLine & "-" & return
						end if
					end if
				end repeat
				
			end if
			
			-- if the current node has sub-trees then recurse
			set lstSubTrees to trees of oTree
			if (count of lstSubTrees) > 0 then
				set lngNewIndent to lngIndent + 1
				set strTP to strTP & my ExportTrees(lstSubTrees, lngNewIndent, blnContextView)
			end if
			
		end repeat
	end tell
	return strTP
end ExportTrees

on RTrim(someText)
	local someText
	
	repeat until someText does not end with return
		if length of someText > 1 then
			set someText to text 1 thru -2 of someText
		else
			set someText to ""
		end if
	end repeat
	
	return someText
end RTrim

on DateString(dte)
	-- yyyy-mm-dd hh:mm
	set strDate to ""
	if dte is not equal to missing value then
		set lngMonth to month of dte as integer
		set strMonth to lngMonth as string
		if lngMonth < 10 then set strMonth to "0" & strMonth
		
		set lngDay to day of dte as integer
		set strDay to lngDay as string
		if lngDay < 10 then set strDay to "0" & strDay
		
		set strDate to strDate & (year of dte) & "-" & strMonth & "-" & strDay
		
		set lngHrs to (hours of dte) as integer
		set lngmins to (minutes of dte) as integer
		
		if (lngHrs > 0) or (lngmins > 0) then
			set strHrs to lngHrs as string
			if lngHrs < 10 then set strHrs to "0" & strHrs
			
			set strMins to lngmins as string
			if lngmins < 10 then set strMins to "0" & strMins
			
			set strDate to strDate & " " & strHrs & ":" & strMins
		end if
	end if
	return strDate
end DateString

on EscAmpersand(str)
	set strOldDelim to text item delimiters
	
	set text item delimiters to " @"
	set lstParts to text items of str
	set lngParts to count of lstParts
	if lngParts > 1 then
		
		set strNew to item 1 of lstParts
		repeat with n from 2 to lngParts
			set strNew to strNew & "_@" & item n of lstParts
		end repeat
		set text item delimiters to strOldDelim
		return strNew
	else
		set text item delimiters to strOldDelim
		return str
	end if
end EscAmpersand

Export to OmniOutliner format:

(*
	This script generates an OmniOutliner outline from the selected items in OmniFocus.
	
	version 0.1.2, by Benjamin Crist brings OO4 window upon creation
	version 0.1.1, by Curt Clifton
	
	Copyright © 2007, 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 theItems to value of selected trees of content
	end tell
	if ((count of theItems) is 0) then
		display alert "Select an item to turn into an OmniOutliner outline."
		return
	end if
	-- FIXME: OF doesn't yet support this:
	-- set theItems to expel descendants theItems
end tell

(*
tell application "OmniOutliner"
	make new document at before documents with properties {name:"Items from OmniFocus"}
	activate front window
end tell
*)

tell application "OmniOutliner"
	activate front document
end tell

createRows(theItems)
return

on createRows(theItems)
	if (theItems is {}) then return
	createRow(item 1 of theItems)
	createRows(rest of theItems)
end createRows

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)}
	end tell
	createChildren(anItem, aRow)
end createRow

on getRowData from anItem
	using terms from application "OmniFocus"
		set theTopic to name of anItem
		set theNote to (note of anItem)
	end using terms from
	return {rowTopic:theTopic, rowNote:theNote}
end getRowData

on createChildren(anItem, aRow)
	using terms from application "OmniFocus"
		set itemChildren to every task of anItem
	end using terms from
	createChildrenHelper(itemChildren, aRow)
end createChildren

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)} at after last child of aRow
	end tell
	createChildren(childItem, childRow)
	createChildrenHelper(rest of itemChildren, aRow)
end createChildrenHelper

These scripts - are they to be placed inside OF somehow, or do I just run them as standalone Applescript scripts?

And for the github.com/psidnell/ofexport2 how do I build/run - is this to be used inside of Terminal, or some specific environment (OF?)?

First, you’ll need OF2 Pro to obtain Applescript support. Then, copy the code and paste it in a new document created in Script Editor. Hit the hammer to compile, and save to a Finder location of your choice.

From within OF2, select “Open Scripts Folder” from the Help menu and move your scripts there from the previous saved location. Now, if you right-click on the OF2 toolbar and customize it your scripts will show up and can be dragged to a location on the menu.

OF2export needs to be run and maintained from Terminal. You will need other dependencies which are described in the Github documentation I linked earlier.