The Omni Group Forums

The Omni Group Forums (http://forums.omnigroup.com/index.php)
-   OmniFocus Extras (http://forums.omnigroup.com/forumdisplay.php?f=44)
-   -   Reusable approach to exporting from OF (http://forums.omnigroup.com/showthread.php?t=15469)

RobTrew 2010-03-02 08:08 AM

Reusable approach to exporting from OF
 
In case anyone needs to write a custom data exporter for OmniFocus, the sample code below might conceivably be helpful.

I have drafted the first version of a re-usable function, [COLOR="RoyalBlue"]SelectedInOF()[/COLOR], which simply returns a nested applescript list representation of the OF tree(s) selected in a Project view or a Context view.

It is generally fairly straightforward to use its output to transfer data to some other application or format.

In [URL="http://forums.omnigroup.com/showthread.php?t=15447"]another post[/URL], I have shown how [COLOR="RoyalBlue"]SelectedInOF()[/COLOR] can be used to export data to OmniPlan.

(A [URL="http://forums.omnigroup.com/showthread.php?t=15470"]second post[/URL] illustrates the use of [COLOR="RoyalBlue"]SelectedInOF()[/COLOR] to export from OF to the Merlin 2 project management package).

The following illustrative draft exports to OmniOutliner Pro, including the various OF fields as OmniOutliner columns. (It differs from an applescript which I posted some years ago in that it allows for export from Context views).

(Note that all the visible children of any selected parent element are exported, so there is no need to select children as well as parents)

[CODE]-- Illustrative draft Ver 0.8

-- Copies anything selected in Omnifocus (Project or Context View) into OmniOutliner
-- Including the following fields: DONE, NOTE, CONTEXT or PROJECT, START, DUE, COMPLETED, DURATION, FLAGGED}
-- Note that the whole sub-tree is copied, so only 'parent' elements need to be selected.
-- The destination is the currently open OmniOutliner document.
-- (A fresh OmniOutliner document is created if none is open)

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

property pColProjContext : 3 as integer
property pSTART : 4 as integer
property pDUE : 5 as integer
property pCOMPLETED : 6 as integer
property pDURATION : 7 as integer
property pFLAGGED : 8 as integer

on run
PlaceInOO(SelectedInOF())
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}
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, blnContext, blnAll)
using terms from application "OmniFocus"
repeat with i from 1 to length of lstNodes
tell item i of lstNodes
if blnContext then
set oParent to its containing project
else
set oParent to its context
end if
if oParent is not missing value then
set strParent to name of oParent
else
set strParent to ""
end if

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


-- PLACING IN OMNIOUTLINER

on PlaceInOO({lstTasks, blnContext})
if (length of lstTasks > 0) then
tell application id "OOut"
activate
set docTarget to make new document at before documents
set bounds of (front window) to {0, 0, 1000, 500}

-- Create required columns
tell docTarget
if blnContext then
make new column with properties {type:rich text, name:"Project"}
else
make new column with properties {type:rich text, name:"Context"}
end if
repeat with recProps in {{type:date, name:"Start"}, {type:date, name:"Due"}, {type:date, name:"Completed"}, ¬
{type:duration, name:"Duration"}, {type:checkbox, name:"Flagged", width:64}}
make new column with properties recProps
end repeat
end tell

my Tasks2OO(lstTasks, docTarget)
tell docTarget to set expanded of every row to true
return docTarget
end tell
end if
end PlaceInOO

on Tasks2OO(lstTasks, oParent)
tell application id "OOut"
tell oParent
repeat with oTask in lstTasks
set {strName, blnDone, lstChiln, strNote, strProjContext, dteStart, dteDue, dteDone, lngMins, blnFlagged} to oTask

if length of strNote > 0 then
set recRow to {topic:strName, note:strNote, expanded:true}
else
set recRow to {topic:strName, expanded:true}
end if
if blnDone then set recRow to recRow & {state:checked}

tell (make new row at end of children with properties recRow)
if strProjContext is not missing value then set value of cell pColProjContext to strProjContext
if dteStart is not missing value then set value of cell pSTART to dteStart
if dteDue is not missing value then set value of cell pDUE to dteDue
if blnDone then if (dteDone is not missing value) then set value of cell pCOMPLETED to dteDone
if lngMins > 0 then set value of cell pDURATION to lngMins / 60
if blnFlagged then set state of cell pFLAGGED to checked

if (length of lstChiln > 0) then my Tasks2OO(lstChiln, it)
end tell
end repeat
end tell
end tell
end Tasks2OO

[/CODE]

chris_leonard 2011-06-21 08:37 AM

Hi Rob just wanted to say how well your piece of code works! I spent all morning trying to get my task list for a subset of experiments into a format that looked OK in Word. Grabbing it into OO with your script and then exporting it into Word was the final solution. I really think the Export option from OF should be improved but in the mean time your script works very well! Thanks.
-Chris

RobTrew 2011-06-22 12:44 PM

Good !!

(Haven't looked at it for a while, and just made a couple of quick edits - possibly fractionally faster now, but imperceptible in practice, I suspect :-)

gcrump 2013-05-25 07:20 AM

[QUOTE=RobTrew;98798]Good !!

(Haven't looked at it for a while, and just made a couple of quick edits - possibly fractionally faster now, but imperceptible in practice, I suspect :-)[/QUOTE]

Rob, Not sure if you will ever come back to this but now with Omnipressence OO is suddenly interesting to me again. For some reason though when I run version .08 or .9 of this script it does not copy the project name over. All the other fields end up in the right column...Any chance you could dust it off and take a quick look?

RobTrew 2013-05-25 07:48 AM

The approach [URL="http://www.complexpoint.macmate.me/Site/OF2Omnioutliner.html"]it[/URL] takes (in exports from project view) is that the names of selected projects are exported as part of the Topic tree.

Would you prefer a version with a project name column as well ?

gcrump 2013-05-25 07:55 AM

1 Attachment(s)
Rob, Wow! Thanks for the fast response. See the attached screenshot... This is after I ran the script on the selected task. It fills in everything but the project column. So I guess yes, is there away to have the project name (full hierarchy) into the project column that it creates. - Does that make sense?

RobTrew 2013-05-25 08:09 AM

We can no longer update earlier posts, but I think this version may fix that for export from Context view, though not will the full path. I'll take a look at the latter.

[CODE]-- Illustrative draft Ver 1.0

-- Copies anything selected in Omnifocus (Project or Context View) into OmniOutliner
-- Including the following fields: DONE, NOTE, CONTEXT or PROJECT, START, DUE, COMPLETED, DURATION, FLAGGED}
-- Note that the whole sub-tree is copied, so only 'parent' elements need to be selected.
-- The destination is the currently open OmniOutliner document.
-- (A fresh OmniOutliner document is created if none is open)

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

property pColProjContext : 3 as integer
property pSTART : 4 as integer
property pDUE : 5 as integer
property pCOMPLETED : 6 as integer
property pDURATION : 7 as integer
property pFLAGGED : 8 as integer

on run
PlaceInOO(SelectedInOF())
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 blnContext then
set oParent to its containing project
else
set oParent to its context
end if
if oParent is not missing value then
set strParent to name of oParent
else
set strParent to ""
end if
if (its class) is not folder then
set item i of lstNodes to {name, completed, my ListSubNodes(its tasks, blnContext, blnAll), note, strParent, start date, due date, completion date, estimated minutes, flagged}
else
set item i of lstNodes to {name, false, my ListSubNodes(its projects, blnContext, blnAll), note, strParent, missing value, missing value, missing value, missing value, false}
end if
end tell
end repeat

return {lstNodes, blnContext}
end tell
end SelectedInOF

on ListSubNodes(lstNodes, blnContext, blnAll)
if lstNodes ≠ {} then
using terms from application "OmniFocus"
repeat with i from 1 to length of lstNodes
tell item i of lstNodes
if blnContext then
set oParent to its containing project
else
set oParent to its context
end if
if oParent is not missing value then
set strParent to name of oParent
else
set strParent to ""
end if

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


-- PLACING IN OMNIOUTLINER

on PlaceInOO({lstTasks, blnContext})
if (length of lstTasks > 0) then
tell application id "OOut"
activate
set docTarget to make new document at before documents
set bounds of (front window) to {0, 0, 1000, 500}

-- Create required columns
tell docTarget
if blnContext then
make new column with properties {type:rich text, name:"Project"}
else
make new column with properties {type:rich text, name:"Context"}
end if
repeat with recProps in {{type:date, name:"Start"}, {type:date, name:"Due"}, {type:date, name:"Completed"}, ¬
{type:duration, name:"Duration"}, {type:checkbox, name:"Flagged", width:64}}
make new column with properties recProps
end repeat
end tell

my Tasks2OO(lstTasks, docTarget)
tell docTarget to set expanded of every row to true
return docTarget
end tell
end if
end PlaceInOO

on Tasks2OO(lstTasks, oParent)
tell application id "OOut"
tell oParent
repeat with oTask in lstTasks
set {strName, blnDone, lstChiln, strNote, strProjContext, dteStart, dteDue, dteDone, lngMins, blnFlagged} to oTask

if length of strNote > 0 then
set recRow to {topic:strName, note:strNote, expanded:true}
else
set recRow to {topic:strName, expanded:true}
end if
if blnDone then set recRow to recRow & {state:checked}

tell (make new row at end of children with properties recRow)
if strProjContext is not missing value then set value of cell pColProjContext to strProjContext
if dteStart is not missing value then set value of cell pSTART to dteStart
if dteDue is not missing value then set value of cell pDUE to dteDue
if blnDone then if (dteDone is not missing value) then set value of cell pCOMPLETED to dteDone
if lngMins > 0 then set value of cell pDURATION to lngMins / 60
if blnFlagged then set state of cell pFLAGGED to checked

if (length of lstChiln > 0) then my Tasks2OO(lstChiln, it)
end tell
end repeat
end tell
end tell
end Tasks2OO
[/CODE]

RobTrew 2013-05-25 08:21 AM

Here's a first sketch of a version which tries to export the full project/context paths:

[CODE]-- Illustrative draft Ver 1.1

-- Copies anything selected in Omnifocus (Project or Context View) into OmniOutliner
-- Including the following fields: DONE, NOTE, CONTEXT or PROJECT, START, DUE, COMPLETED, DURATION, FLAGGED}
-- Note that the whole sub-tree is copied, so only 'parent' elements need to be selected.
-- The destination is the currently open OmniOutliner document.
-- (A fresh OmniOutliner document is created if none is open)

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

property pColProjContext : 3 as integer
property pSTART : 4 as integer
property pDUE : 5 as integer
property pCOMPLETED : 6 as integer
property pDURATION : 7 as integer
property pFLAGGED : 8 as integer

on run
PlaceInOO(SelectedInOF())
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 blnContext then
set oParent to its containing project
else
set oParent to its context
end if
if oParent is not missing value then
set strParent to my ReadNodePath(oParent)
else
set strParent to ""
end if
if (its class) is not folder then
set item i of lstNodes to {name, completed, my ListSubNodes(its tasks, blnContext, blnAll), note, strParent, start date, due date, completion date, estimated minutes, flagged}
else
set item i of lstNodes to {name, false, my ListSubNodes(its projects, blnContext, blnAll), note, strParent, missing value, missing value, missing value, missing value, false}
end if
end tell
end repeat

return {lstNodes, blnContext}
end tell
end SelectedInOF

on ListSubNodes(lstNodes, blnContext, blnAll)
if lstNodes ≠ {} then
using terms from application "OmniFocus"
repeat with i from 1 to length of lstNodes
tell item i of lstNodes
if blnContext then
set oParent to its containing project
else
set oParent to its context
end if
if oParent is not missing value then
set strParent to ReadNodePath(oParent)
else
set strParent to ""
end if

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


-- PLACING IN OMNIOUTLINER

on PlaceInOO({lstTasks, blnContext})
if (length of lstTasks > 0) then
tell application id "OOut"
activate
set docTarget to make new document at before documents
set bounds of (front window) to {0, 0, 1000, 500}

-- Create required columns
tell docTarget
if blnContext then
make new column with properties {type:rich text, name:"Project"}
else
make new column with properties {type:rich text, name:"Context"}
end if
repeat with recProps in {{type:date, name:"Start"}, {type:date, name:"Due"}, {type:date, name:"Completed"}, ¬
{type:duration, name:"Duration"}, {type:checkbox, name:"Flagged", width:64}}
make new column with properties recProps
end repeat
end tell

my Tasks2OO(lstTasks, docTarget)
tell docTarget to set expanded of every row to true
return docTarget
end tell
end if
end PlaceInOO

on Tasks2OO(lstTasks, oParent)
tell application id "OOut"
tell oParent
repeat with oTask in lstTasks
set {strName, blnDone, lstChiln, strNote, strProjContext, dteStart, dteDue, dteDone, lngMins, blnFlagged} to oTask

if length of strNote > 0 then
set recRow to {topic:strName, note:strNote, expanded:true}
else
set recRow to {topic:strName, expanded:true}
end if
if blnDone then set recRow to recRow & {state:checked}

tell (make new row at end of children with properties recRow)
if strProjContext is not missing value then set value of cell pColProjContext to strProjContext
if dteStart is not missing value then set value of cell pSTART to dteStart
if dteDue is not missing value then set value of cell pDUE to dteDue
if blnDone then if (dteDone is not missing value) then set value of cell pCOMPLETED to dteDone
if lngMins > 0 then set value of cell pDURATION to lngMins / 60
if blnFlagged then set state of cell pFLAGGED to checked

if (length of lstChiln > 0) then my Tasks2OO(lstChiln, it)
end tell
end repeat
end tell
end tell
end Tasks2OO


on ReadNodePath(oNode)
set lst to GetNodePath(oNode, "")
set {dlm, my text item delimiters} to {my text item delimiters, ":"}
set str to lst as string
set my text item delimiters to dlm
return str
end ReadNodePath

on GetNodePath(oNode, strProjMarker)
tell application id "OFOC"
set {cClass, oParent, strName} to {class, container, name} of oNode
set cParentClass to class of oParent
if cParentClass is document or cParentClass is folder then
if cClass is task or cClass is project then
tell oNode
if (cClass is project) or (it is root task of its containing project) then
if strProjMarker ≠ "" then
set strName to strName & strProjMarker
end if

set oFolder to folder of containing project of oNode
if oFolder is not missing value then
set cParentClass to folder
set oParent to oFolder
end if
end if
end tell
end if
end if
if cParentClass is not document then
return my GetNodePath(oParent, strProjMarker) & {strName}
else
return {strName}
end if
end tell
end GetNodePath

[/CODE]

gcrump 2013-05-25 08:46 AM

Rob, Works like a champ. Thanks for the fast work and on a Saturday too. Awesome.

thart 2014-01-02 01:43 PM

Import feature to OPML export script
 
Rob,

I have been experimenting with ways to export from OF to OO using this script (direct OO) and the one below (through OMPL). Both are winners. Thank you.

My ultimate goal is to export existing & completed OF tasks preserving the original features (links to emails, embedded files), etc.

I had two questions.

1. Can the link to the original email be preserved for any exported notes?

- In the direct to OPML, the note (as email) format is jumbled & difficult to read, but it sort of preserve the link to the original email as it does in the OF task if you search through all the jumble. This is useful.

- In the direct OO, the note (as email) format is preserved & readable (which is great), but it does not preserve the link to the original email as found in OF


2. How difficult is exporting attachments?

Note: The location of the OPML export script
[url]http://forums.omnigroup.com/showthread.php?t=25965[/url]
Script: Filtered export to iThoughtsHD & OPML (& .txt)


All times are GMT -8. The time now is 10:41 PM.

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