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?
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…
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! )
.
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 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
- view all
- show context perspective
- 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.