The Omni Group Forums

The Omni Group Forums (http://forums.omnigroup.com/index.php)
-   OmniFocus Extras (http://forums.omnigroup.com/forumdisplay.php?f=44)
-   -   Exporting the whole OF database to OPML (http://forums.omnigroup.com/showthread.php?t=7223)

RobTrew 2008-02-19 03:30 AM

Exporting the whole OF database to OPML
 
Direct OPML export would be a welcome feature in Omnifocus.

In the meanwhile I have drafted [URL="http://web.mac.com/robinfrancistrew/Site/OF2OPML.html"]an Applescript[/URL] which requires both Omnifocus and OmniOutliner Professional. It exports the Omnifocus database to an OmniOutliner file, and saves this to an OPML file on the user’s OS X desktop. (~/Desktop/OF_All.opml).

This version excludes done items from the export, but this can be changed by editing the start of the script, so that it reads [COLOR="Blue"][B]property[/B][/COLOR] [COLOR="Green"]blnSkipDoneTasks[/COLOR] [COLOR="Blue"]: false[/COLOR]

I find it useful for exporting an OF database to [URL="http://www.novamind.com/Products/"]Novamind[/URL] or to a mobile phone outliner like [URL="http://www.kylom.com/"]Projekt[/URL].

May also be useful to anyone who needs to export their whole OF database, including the Inbox, to Omnioutliner, with columns for context, dates, etc.

[URL="http://web.mac.com/robinfrancistrew/Site/OF2OPML.html"]Download[/URL]

korm 2011-08-05 04:30 AM

Rob:

I like this, and would like to narrow the export to a section of the OF database (specifically a Perspective, but individual Projects would be helpful). I realize it's been several years since you posted, but wonder if you give some guidance to a newb in OF scripting.

RobTrew 2011-08-05 02:11 PM

[QUOTE=korm;100284]I ... would like to narrow the export to a section of the OF database (specifically a Perspective, but individual Projects would be helpful). [/QUOTE]

Two broad approaches come to mind:[LIST=1][*]Redrafting it to export only elements that are selected in the GUI,[*]redrafting to export a set of elements specified by a query (like those used by [url]http://bit.ly/OF-Find2[/url])[/LIST]
Any preference ?

(You might find some elements of a solution [URL="http://forums.omnigroup.com/showthread.php?t=15469"]here[/URL])

[COLOR="White"]--[/COLOR]

RobTrew 2011-08-10 03:17 PM

An illustrative sketch of code for exporting the selected OF items straight to an OPML file.

(I personally find it more useful to export to OO3)

[CODE]-- Indicative draft Ver 4.00 - OPTION TO DUMP ALL ACTIVE FOLDERS AND PROJECTS - (Currently slow)

-- Removed space before header, and added space after attributes,
-- for better compatibility with other applications
-- Saves anything selected in Omnifocus (Project or Context View) As an OPML
-- Including the following fields: DONE, NOTE, CONTEXT, PROJECT, START, DUE, COMPLETED, DURATION, FLAGGED}
-- Note that the whole sub-tree is copied, so only 'parent' elements need to be selected.

property pManualSelection : true

property pPROJECT : "project"
property pTASK : "task"
property pINBX_TASK : "inbox task"
property pITEM : "item"

property pOPMLHeadToExpand : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<opml version=\"1.0\">
<head>
<title>Selected in OF</title>
<expansionState>"
property pOPMLHeadFromExpand : "</expansionState>
</head>
<body>
"

property pOPMLTail : "
</body>
</opml>"

property pNodeStart : "<outline "
property pLeafClose : "/>"
property pParentClose : "</outline>"

on run

set {lstExport, blnContext} to SelectedInOF(pManualSelection)

set strOPML to MakeOPML({lstExport, blnContext})
if strOPML ≠ "" then
set oFile to choose file name with prompt "Save as OPML" default name "Untitled.opml" default location (path to desktop) as alias
WriteText2Path(strOPML, POSIX path of oFile)
end if
end run

-- READ SELECTED OmniFocus CONTENT TREE(S) TO NESTED APPLESCRIPT LISTS - Ver.04
on SelectedInOF(pManualSelection)
tell application "OmniFocus"
if pManualSelection then
tell front window
set blnContext to ((selected view mode identifier) is not equal to pPROJECT)

repeat with oPanel in {content, sidebar}
set lstNodes to value of (selected trees of oPanel where class of its value ≠ item)
set lngNodes to count of lstNodes
if lngNodes > 0 then exit repeat
end repeat
if (lngNodes < 1) then set lstNodes to value of (trees of content where class of its value ≠ item)
end tell
else
tell default document to set lstNodes to ((projects where status is active) as list) & (folders where hidden is false) as list
set blnContext to false
end if

repeat with i from 1 to length of lstNodes
tell item i of lstNodes
if (its class) is not folder then
if (number of tasks) > 0 then
--set item i of lstNodes to {name, completed, my ListSubNodes(its tasks, blnContext, blnAll), note, "", "", start date, due date, completion date, estimated minutes, flagged}
set item i of lstNodes to {name, completed, my ListSubNodes(its tasks, blnContext), note, "", "", start date, due date, completion date, estimated minutes, flagged}
else
set item i of lstNodes to {name, completed, {}, note, "", "", start date, due date, completion date, estimated minutes, flagged}
end if
else
if (number of projects) > 0 then
set item i of lstNodes to {name, false, my ListSubNodes(its projects, blnContext), note, "", "", missing value, missing value, missing value, missing value, false}
else
set item i of lstNodes to {name, false, {}, note, "", "", missing value, missing value, missing value, missing value, false}
end if
end if
end tell
end repeat

return {lstNodes, blnContext}
end tell
end SelectedInOF

on ListSubNodes(lstNodes)
using terms from application "OmniFocus"
repeat with i from 1 to length of lstNodes
tell item i of lstNodes

set oProj to its containing project
if oProj is not missing value then
set strProject to name of oProj
else
set strProject to ""
end if

set oContext to its context
if oContext is not missing value then
set strContext to name of oContext
else
set strContext to ""
end if

if (number of tasks) > 0 then
set item i of lstNodes to {name, completed, my ListSubNodes(its tasks), note, strProject, strContext, start date, due date, completion date, estimated minutes, flagged}
else
set item i of lstNodes to {name, completed, {}, note, strProject, strContext, start date, due date, completion date, estimated minutes, flagged}
end if
end tell
end repeat
return lstNodes
end using terms from
end ListSubNodes


-- BUILD OPML

on MakeOPML({lstTasks, blnContext})
if (length of lstTasks > 0) then

set {lngIndex, strExpand, strOutline} to my Tasks2OPML(-1, lstTasks, tab)
set strOPML to pOPMLHeadToExpand & strExpand & pOPMLHeadFromExpand & strOutline & pOPMLTail
return strOPML
end if
end MakeOPML

on Tasks2OPML(lngIndex, lstTasks, strIndent)
set {strExpand, strOut} to {"", ""}
repeat with oTask in lstTasks
set {strName, blnDone, lstChiln, strNote, strProject, strContext, dteStart, dteDue, dteDone, lngMins, blnFlagged} to oTask

if strNote ≠ "" then
set strOut to strOut & pNodeStart & Attr("text", strName) & Attr("_note", strNote)
else
set strOut to strOut & pNodeStart & Attr("text", strName)
end if

if blnDone then if (dteDone is not missing value) then
set strOut to strOut & Attr("_status", "checked") & Attr("Completed", short date string of dteDone & space & time string of dteDone)
end if

if strProject ≠ "" then set strOut to strOut & Attr("Project", strProject)
if strContext ≠ "" then set strOut to strOut & Attr("Context", strContext)

tell dteStart to if it is not missing value then set strOut to strOut & my Attr("Start", short date string & space & time string)
tell dteDue to if it is not missing value then set strOut to strOut & my Attr("Due", short date string & space & time string)

if lngMins > 0 then set strOut to strOut & Attr("Duration", ((lngMins / 60) as string) & "h")
if blnFlagged then set strOut to strOut & Attr("Flagged", "2")

set lngIndex to lngIndex + 1
if (length of lstChiln > 0) then
set strExpand to strExpand & "," & (lngIndex) as string
set {lngIndex, strSubExpand, strSubOutln} to Tasks2OPML(lngIndex, lstChiln, strIndent & tab)
if strSubExpand ≠ "" then set strExpand to strExpand & "," & strSubExpand
set strOut to strOut & ">" & return & ¬
strIndent & strSubOutln & return & ¬
strIndent & pParentClose
else
set strOut to strOut & pLeafClose & return
end if
end repeat
if strExpand begins with "," and length of strExpand > 1 then set strExpand to text 2 thru -1 of strExpand
return {lngIndex, strExpand, strOut}
end Tasks2OPML

on Attr(strName, strValue)
strName & "=" & EscapeChars(strValue) & space
end Attr

on EscapeChars(str)
-- QUOTE < > & ETC
set strEncoded to (do shell script "python -c 'import sys; from xml.sax.saxutils import quoteattr; print quoteattr(sys.argv[1])' " & ¬
quoted form of str)

-- ENCODE DIACRITICS AND SPECIAL CHARACTERS
set lstChars to characters of strEncoded
repeat with i from 1 to length of lstChars
set lngCode to id of item i of lstChars
if lngCode > 127 then set item i of lstChars to ("&#" & lngCode as string) & ";"
end repeat
lstChars as Unicode text
end EscapeChars

on WriteText2Path(strText, strPosixPath)
set f to (POSIX file strPosixPath)
open for access f with write permission
write strText as «class utf8» to f
close access f
end WriteText2Path
[/CODE]

grlloyd 2011-08-13 06:54 AM

Thanks Rob!
 
Rob - Your script is a lifesaver, and works perfectly with current OmniX software in Aug 2011! I've accumulated several light-weight outline threads in OmniFocus, based on OmniFocus' good Mac, iPad, iPhone synch.

I'd love to continuing to use OmniFocus a light-weight outliner awa task tool, but as the Tasking UX grows more specialized, the outline capabilities become awkward to access and useless on the iPhone OmniFocus.

I can live with exporting my outlines and using OmniOutline Mac + iPad I guess, but really liked integrated simple outlining as part of OmniFocus, and will ping Omni folk.

Shotster 2011-11-30 02:27 PM

Yeah, thanks Rob! I had to tweak it to encode special characters (ampersands, double quotes, and the like) that might appear in XML attribute values, but it otherwise worked great.

And BTW, if anyone is interested in my copy of OmniFocus for Mac, let me know! I'll sell it cheap.

-Steve

Zettt 2012-01-01 03:50 AM

Shotster, du you mind sharing your changes?

Shotster 2012-01-01 12:24 PM

[QUOTE=Zettt;105562]Shotster, du you mind sharing your changes?[/QUOTE]

Not at all. Following is the entire script. You'll have to compare it with the original to see exactly what I changed. I didn't take the time to document my changes with comments or anything.

[CODE]
-- Indicative draft Ver 0.001

-- Saves anything selected in Omnifocus (Project or Context View) As an OPML
-- Including the following fields: DONE, NOTE, CONTEXT, PROJECT, START, DUE, COMPLETED, DURATION, FLAGGED}
-- Note that the whole sub-tree is copied, so only 'parent' elements need to be selected.

property pPROJECT : "project"
property pTASK : "task"
property pINBX_TASK : "inbox task"
property pITEM : "item"

property pOPMLHeadToExpand : "
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<opml version=\"1.0\">
<head>
<title>Selected in OF</title>
<expansionState>"
property pOPMLHeadFromExpand : "</expansionState>
</head>
<body>
"

property pOPMLTail : "
</body>
</opml>"

property pNodeStart : "<outline "
property pLeafClose : "/>"
property pParentClose : "</outline>"

on run
set strOPML to MakeOPML(SelectedInOF())
if strOPML ≠ "" then
set oFile to choose file name with prompt "Save as OPML" default name "Untitled.opml" default location (path to desktop) as alias
WriteText2Path(strOPML, POSIX path of oFile)
end if
end run

-- READ SELECTED OmniFocus CONTENT TREE(S) TO NESTED APPLESCRIPT LISTS - Ver.04

on SelectedInOF()
tell application "OmniFocus"
tell front window
set blnContext to ((selected view mode identifier) is not equal to pPROJECT)

repeat with oPanel in {content, sidebar}
set lstNodes to value of (selected trees of oPanel where class of its value ≠ item)
set lngNodes to count of lstNodes
if lngNodes > 0 then exit repeat
end repeat
set blnAll to (lngNodes < 1)
if blnAll then set lstNodes to value of (trees of content where class of its value ≠ item)
end tell

repeat with i from 1 to length of lstNodes
tell item i of lstNodes
if (its class) is not folder then
if (number of tasks) > 0 then
--set item i of lstNodes to {name, completed, my ListSubNodes(its tasks, blnContext, blnAll), note, "", "", start date, due date, completion date, estimated minutes, flagged}
set item i of lstNodes to {name, completed, my ListSubNodes(its tasks, blnContext, blnAll), note, "", "", start date, due date, completion date, estimated minutes, flagged}



else
set item i of lstNodes to {name, completed, {}, note, "", "", start date, due date, completion date, estimated minutes, flagged}
end if
else
if (number of projects) > 0 then
set item i of lstNodes to {name, false, my ListSubNodes(its projects, blnContext, blnAll), note, "", "", missing value, missing value, missing value, missing value, false}
else
set item i of lstNodes to {name, false, {}, note, "", "", missing value, missing value, missing value, missing value, false}
end if
end if
end tell
end repeat

return {lstNodes, blnContext}
end tell
end SelectedInOF

on ListSubNodes(lstNodes, blnAll)
using terms from application "OmniFocus"
repeat with i from 1 to length of lstNodes
tell item i of lstNodes

set oProj to its containing project
if oProj is not missing value then
set strProject to name of oProj
else
set strProject to ""
end if

set oContext to its context
if oContext is not missing value then
set strContext to name of oContext
else
set strContext to ""
end if

if (number of tasks) > 0 then
set item i of lstNodes to {name, completed, my ListSubNodes(its tasks, blnAll), note, strProject, strContext, start date, due date, completion date, estimated minutes, flagged}
else
set item i of lstNodes to {name, completed, {}, note, strProject, strContext, start date, due date, completion date, estimated minutes, flagged}
end if
end tell
end repeat
return lstNodes
end using terms from
end ListSubNodes


-- BUILD OPML

on MakeOPML({lstTasks, blnContext})
if (length of lstTasks > 0) then

set {lngIndex, strExpand, strOutline} to my Tasks2OPML(-1, lstTasks, tab)
set strOPML to pOPMLHeadToExpand & strExpand & pOPMLHeadFromExpand & strOutline & pOPMLTail
return strOPML
end if
end MakeOPML

on Tasks2OPML(lngIndex, lstTasks, strIndent)
set {strExpand, strOut} to {"", ""}
repeat with oTask in lstTasks
set {strName, blnDone, lstChiln, strNote, strProject, strContext, dteStart, dteDue, dteDone, lngMins, blnFlagged} to oTask

if strNote ≠ "" then
set strOut to strOut & pNodeStart & Attr("text", strName) & Attr("_note", strNote)
else
set strOut to strOut & pNodeStart & Attr("text", strName)
end if

if blnDone then if (dteDone is not missing value) then
set strOut to strOut & Attr("_status", "checked") & Attr("Completed", short date string of dteDone & space & time string of dteDone)
end if

if strProject ≠ "" then set strOut to strOut & Attr("Project", strProject)
if strContext ≠ "" then set strOut to strOut & Attr("Context", strContext)

tell dteStart to if it is not missing value then set strOut to strOut & my Attr("Start", short date string & space & time string)
tell dteDue to if it is not missing value then set strOut to strOut & my Attr("Due", short date string & space & time string)

if lngMins > 0 then set strOut to strOut & Attr("Duration", ((lngMins / 60) as string) & "h")
if blnFlagged then set strOut to strOut & Attr("Flagged", "2")

set lngIndex to lngIndex + 1
if (length of lstChiln > 0) then
set strExpand to strExpand & "," & (lngIndex) as string
set {lngIndex, strSubExpand, strSubOutln} to Tasks2OPML(lngIndex, lstChiln, strIndent & tab)
if strSubExpand ≠ "" then set strExpand to strExpand & "," & strSubExpand
set strOut to strOut & ">" & return & ¬
strIndent & strSubOutln & return & ¬
strIndent & pParentClose
else
set strOut to strOut & pLeafClose & return
end if
end repeat
if strExpand begins with "," and length of strExpand > 1 then set strExpand to text 2 thru -1 of strExpand
return {lngIndex, strExpand, strOut}
end Tasks2OPML

on Attr(strName, strValue)
--strName & "=\"" & strValue & "\" "
strName & "=\"" & attributeValue(strValue) & "\" "
end Attr

on WriteText2Path(strText, strPosixPath)
set f to (POSIX file strPosixPath)
open for access f with write permission
write strText as «class utf8» to f
close access f
end WriteText2Path

on attributeValue(str)
set retVal to stringReplace("&", "&amp;", str)
set retVal to stringReplace("\"", "&quot;", retVal)
set retVal to stringReplace("<", "&lt;", retVal)
set retVal to stringReplace(">", "&gt;", retVal)
set retVal to stringReplace("
", "
", retVal)
return retVal
end attributeValue

on stringReplace(find, replace, subject)
set prevTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to find
set subject to text items of subject

set text item delimiters of AppleScript to replace
set subject to "" & subject
set text item delimiters of AppleScript to prevTIDs

return subject
end stringReplace
[/CODE]

Hope it works for you,

-Steve

myfre 2012-01-30 12:10 PM

thanks Rob! and a request...
 
I'm trying to migrate out of omnifocus into omnioutliner which I think would suit me better.

Used your opml script and works almost 100%.

problem is I lose notes attached directly to a projects (project title) in omnifocus.

that is to say, they don't show up in omnioutliner.

it shows the omnifocus project title as a checkbox item but without the note.

if the project has checkboxes and subcheckboxes then I see all the notes for each of those.

it's just the top level note that would be missing.

if that's not clear maybe we could skype? thanks so much for your apple script and your help!

RobTrew 2012-01-30 12:59 PM

[QUOTE=myfre;106725]I'm trying to migrate out of omnifocus into omnioutliner[/QUOTE]

[URL="http://web.me.com/robinfrancistrew/Site/OF2Omnioutliner.html"]This script[/URL], which does, I think, export project notes, might be quicker for OF to oo3.


All times are GMT -8. The time now is 10:19 AM.

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