The Omni Group Forums

The Omni Group Forums (http://forums.omnigroup.com/index.php)
-   OmniFocus Extras (http://forums.omnigroup.com/forumdisplay.php?f=44)
-   -   Things to OF importer (http://forums.omnigroup.com/showthread.php?t=14846)

A to the B 2009-12-23 08:22 AM

Things to OF importer
 
Hi All,
1st post here. And 1st apple script late last night... It would be awesome if someone said "Hey, your reinventing the wheel here. Just follow this link."

I was able to get my data out of Things and into a tab delimited txt file. I then used the trial version of oo3 to convert the txt to an OmniOutliner file. The resulting txt file looks like this:
"projectName" \t "nextAction" \t "@Context" \t "duration eg. 5min or 1h" \t "priority eg. High, Low" \t "hugeChunkOfNotesWith\n'sRemovedToKeepOOHappy" \n (or \r I forget which) repeat...

Here are the issues I am working through:
-The resulting OmniOutliner file looks like the txt file (of course) but with many columns (and no outlining?). Is there a preferred way to format a txt file so that OO opens it and sees an outline and not just a 2d string array?

-OF brings everything in flat and doesn't recognize the project attribute (also flat-ish in OO hmmm, pg. 50 in the OO manual talks about out-denting... is there something here I am missing?)

-My durations go straight to metadata instead of the duration field (this could be my naming convention: 5min, 15min, 30min, 1h, 2h, 1d. What naming conventions are supported/recognized?)

-The notes show up but with a "Metadata: " string prepended to them. Any way to write directly to the notes object?

-I guess "Metadata: Priority: High" is fine. What do you use to set H M L priorities in your OF setup?

I know there is a lot here. Thanks for taking time to read it all. My script code is (will be) pasted below. It began life here: [url]http://culturedcode.com/things/wiki/index.php/Log_Today_List_(AppleScript)[/url]. BTW they have one that does OF to Things [url]http://culturedcode.com/things/wiki/index.php/Omni_To_Things[/url]. I'll check that out for ideas.

---On a silly XP machine at work, I'll post the script code later---

whpalmer4 2009-12-23 12:51 PM

[QUOTE=A to the B;70996]Hi All,
1st post here. And 1st apple script late last night... It would be awesome if someone said "Hey, your reinventing the wheel here. Just follow this link."
[/quote]
Welcome! Now why would you want someone else's script when you could have the satisfaction of building your own? :)
[quote]

Here are the issues I am working through:
-The resulting OmniOutliner file looks like the txt file (of course) but with many columns (and no outlining?). Is there a preferred way to format a txt file so that OO opens it and sees an outline and not just a 2d string array?
[/quote]
I don't know how you could structure a text file to tell OmniOutliner to build an indented outline from it. I would probably just convert the Applescript you're using to make the text file to build the structure in OmniOutliner directly. When you have a chance to post your code, I'll have a look at it and see what I can suggest. Others with more substantial Applescript chops may chime in as well.

[quote]
-OF brings everything in flat and doesn't recognize the project attribute (also flat-ish in OO hmmm, pg. 50 in the OO manual talks about out-denting... is there something here I am missing?)
[/quote]
Yeah, you can select a row (or rows) in OO and indent it with cmd-] or the Reorganize->Indent command. That will establish an outline structure, and OF will honor that structure during import.

[quote]
-My durations go straight to metadata instead of the duration field (this could be my naming convention: 5min, 15min, 30min, 1h, 2h, 1d. What naming conventions are supported/recognized?)
[/quote]
The underlying problem seems to be that the importer is broken -- I'm not able to get it to understand start/due dates or durations. I've filed a report.
[quote]
-The notes show up but with a "Metadata: " string prepended to them. Any way to write directly to the notes object?
[/quote]
Yes, if you use an Applescript to do it. Given that the importer seems to have some troubles with dates and durations, if you were already going to the trouble of making an script that wrote an OmniOutliner file to be imported and cared about dates and durations, one might as well just tell OmniFocus to build the rows directly. Too busy trying to convert this to a previously solved problem to take a step back and think of that before!
[quote]
-I guess "Metadata: Priority: High" is fine. What do you use to set H M L priorities in your OF setup?
[/quote]
I don't. I'm not a believer in putting on priority labels. I'll flag things and use start and due dates to manage the list as needed. One thing I've suggested in the past for people who want such a thing is repurposing the Duration field as a priority field. Make 1-5m your highest priority group, 6-15m your next priority group, etc. following the steps in the duration filter. Set the duration filter to 5 min and you'll only see your highest priority items. Set it to 15 minutes and you see the top two groups. Also sort by duration and you can have various shadings in each group.

A to the B 2009-12-23 08:23 PM

[QUOTE=A to the B;70996]
---On a silly XP machine at work, I'll post the script code later---[/QUOTE]

Later...

[CODE]on ReplaceText(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 ReplaceText

--get replaceText("Windows", "the Mac OS", "I love Windows and I will always love Windows and I have always loved Windows.")


tell application "Things"
-- Include date in the filename.
-- Filename will be ThingsToday.2009June5.txt
set {year:y, month:m, day:d} to (current date)
set fileName to "ThingsNext." & y & m & d & ".txt"

-- Set the path. You should replace 'username' with your actual
-- username, and change the path as you please
set pathName to "Macintosh HD:Users:Alan:Desktop:" & fileName

set fullReport to ""

-- To number the lines in the output
set itemCount to 0

repeat with aToDo in to dos of list "Next"
set itemCount to itemCount + 1

-- Create an empty list for tags and notes and well everything...
set allTags to {}

-- Get project name
if (project of aToDo) is not missing value then
set todoDataRow to (name of project of aToDo) & ": " & (name of aToDo) & tab
else
set todoDataRow to "no project" & ": " & (name of aToDo) & tab
end if

-- Get item name
--set todoDataRow to todoDataRow & (name of aToDo) & tab

-- Get all tags on the todo item
set todoTags to tags of aToDo
repeat with aTag in todoTags
copy (name of aTag) to the end of allTags
end repeat

-- Get all tags on the project, if there is one
if (project of aToDo) is not missing value then
set projTags to tags of (project of aToDo)
repeat with aTag in projTags
copy (name of aTag) to the end of allTags
end repeat
end if

-- Get all tags on the area, if there is one --not needed for my application but you may need this
-- if (area of aToDo) is not missing value then
-- set areaTags to tags of (area of aToDo)
-- repeat with aTag in areaTags
-- copy (name of aTag) to the end of allTags
-- end repeat
-- end if

-- Get all notes on the todo, if there is one
if (notes of aToDo) is not missing value then
repeat with x from ((count allTags) + 1) to 4
copy "" to the end of allTags
end repeat

-- Replace line feeds
set aString to ""
copy (notes of aToDo) to aString
copy my ReplaceText("\n", "--- CR GUID ---", aString) to aString
copy aString to the end of allTags
end if

-- Combine the tags (and notes) into a tab-delimited list
if allTags is not missing value then
set AppleScript's text item delimiters to {"\t"}
set todoDataRow to todoDataRow &
(allTags as text)
end if

set fullReport to fullReport & (todoDataRow & return as string)
end repeat

-- Get the count of inbox items
set inboxItems to count of (to dos of list "Inbox")

-- Compile the contexts and notes of the output for this run
-- Include full date and time, and counts of items in Today and Inbox
(* set fullReport to (((the current date) as string) &
(tab as string) &
(tab as string) &
(itemCount as string) & " items in Today, " &
(inboxItems as string) & " items in Inbox" &
return as string) & fullReport & return as string
*)
-- Open and write to the ouput file
set outputFile to open for access (pathName as string) with write permission
write (fullReport & return as string) to outputFile starting at eof
close access outputFile
end tell
[/CODE]

It is pretty much a hack of some otherwise nice code written by someone else. I plan to clean up the mess I made :D and alter it to write straight to OF. I am still ramping up on apple script and the syntax...

Script question: Performance wise which is better?

A)
Tell app things to give me a big struct, all at once;
Then tell app OF to parse it and create OF rows all at once;

or B)
For (thisItem in allThingsItems)
{
Tell Things to copy anItem to thisItem;
Tell OF to set thisItem to someNewItem;
}

or C)
is this stuff doable/easier in xcode?

Thanks,
Ab

A to the B 2009-12-23 08:29 PM

Thanks for the response! Hopefully I'll have some time over the break to roll up my sleeves and dive into the OF API. I agree writting straight to OF and skipping the txt is ideal.

darrenburgess 2009-12-27 04:48 AM

there seems to be a syntax error in this line:

-- To number the lines in the output
set itemCount to 0

repeat with aToDo in [B]to[/B] dos of list "Next"
set itemCount to itemCount + 1


Error is "Expected expression but found "to"

A to the B 2009-12-31 08:30 AM

Done.
 
Below is code to export tasks from Things into OmniFocus. The importer grabs everything in "Next" and moves it over. It does NOT get items in "Someday" or "Scheduled" (it would be an easy change for you to make if you need it). It preserves projects and contexts (tags that look like "@_____").

This is my first real script. I hope you find it helpful.

Enjoy.
Ab

[CODE]
--------------------------------------------------
--------------------------------------------------
-- Import tasks from Things to OmniFocus
--------------------------------------------------
--------------------------------------------------
tell application "Things"

-- Loop through ToDos in Things
repeat with aToDo in to dos of list "Next"

-- Get title and notes of Things task
set theTitle to name of aToDo
set theNote to notes of aToDo

-- Get project name
if (project of aToDo) is not missing value then
set theProjectName to (name of project of aToDo)
else
set theProjectName to "NoProjInThings"
end if

-- Get Contexts from tags
-- get all tags from one ToDo item...
set allTagNames to {}
copy (name of tags of aToDo) to allTagNames
-- ...and from the project...
if (project of aToDo) is not missing value then
copy (name of tags of project of aToDo) to the end of allTagNames
end if
-- ...now extract contexts from tags
copy my FindContextName(allTagNames) to theContextName

-- Create a new task in OmniFocus
tell application "OmniFocus"

tell default document

-- Set (or create new) task context
if context theContextName exists then
set theContext to context theContextName
else
set theContext to make new context with properties {name:theContextName}
end if

-- Set (or create new) project
if project theProjectName exists then
set theProject to project theProjectName
else
set theProject to make new project with properties {name:theProjectName}
end if

-- Create new task
tell theProject
set newTask to make new task with properties {name:theTitle, note:theNote, containing project:theProject, context:theContext}
end tell

end tell -- document
end tell -- OF application
end repeat -- Main loop
end tell -- Things application


--------------------------------------------------
--------------------------------------------------
-- Get context from array of Things tags
--------------------------------------------------
--------------------------------------------------
on FindContextName(tagNames)
-- Example usage
--FindContextName("@Mac", "1/2hr", "High") -- FYI, my tags are context, duration and priority

repeat with aTagName in tagNames
if aTagName starts with "@" then
return aTagName
end if
end repeat
return ""

end FindContextName -- End FindContextName


--------------------------------------------------
--------------------------------------------------
-- Remove the CRs from a string,
-- not used in this script,
-- carry over from prior implementation
--------------------------------------------------
--------------------------------------------------
on ReplaceText(find, replace, subject)
-- Example usage
-- ReplaceText("Windows", "the Mac OS", "I love Windows and I will always love Windows and I have always loved Windows.")

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 ReplaceText -- End replaceText()
[/CODE]

darrenburgess 2010-01-01 04:34 AM

Where do the actions go once the get into OF? Inbox?

Does it import the projects as well?

Darren

A to the B 2010-01-01 09:44 AM

[QUOTE=darrenburgess;71155]Where do the actions go once the get into OF? Inbox?

Does it import the projects as well?

Darren[/QUOTE]

Projects are imported. Nonproject actions go to the inbox.

robclaisse 2010-01-14 10:05 PM

Thanks A to the B for the script. I've made a small change so that Areas get import and changed into normal projects rather than all areas getting put into a single project.

[CODE]
--------------------------------------------------
--------------------------------------------------
-- Import tasks from Things to OmniFocus
--------------------------------------------------
--------------------------------------------------
tell application "Things"

-- Loop through ToDos in Things
repeat with aToDo in to dos of list "Next"

-- Get title and notes of Things task
set theTitle to name of aToDo
set theNote to notes of aToDo

-- Get project name
if (project of aToDo) is not missing value then
set theProjectName to (name of project of aToDo)
else if (area of aToDo) is not missing value then
set theProjectName to (name of area of aToDo)
else
set theProjectName to "NoProjInThings"
end if

-- Get Contexts from tags
-- get all tags from one ToDo item...
set allTagNames to {}
copy (name of tags of aToDo) to allTagNames
-- ...and from the project...
if (project of aToDo) is not missing value then
copy (name of tags of project of aToDo) to the end of allTagNames
end if
-- ...now extract contexts from tags
copy my FindContextName(allTagNames) to theContextName

-- Create a new task in OmniFocus
tell application "OmniFocus"

tell default document

-- Set (or create new) task context
if context theContextName exists then
set theContext to context theContextName
else
set theContext to make new context with properties {name:theContextName}
end if

-- Set (or create new) project
if project theProjectName exists then
set theProject to project theProjectName
else
set theProject to make new project with properties {name:theProjectName}
end if

-- Create new task
tell theProject
set newTask to make new task with properties {name:theTitle, note:theNote, containing project:theProject, context:theContext}
end tell

end tell -- document
end tell -- OF application
end repeat -- Main loop
end tell -- Things application


--------------------------------------------------
--------------------------------------------------
-- Get context from array of Things tags
--------------------------------------------------
--------------------------------------------------
on FindContextName(tagNames)
-- Example usage
--FindContextName("@Mac", "1/2hr", "High") -- FYI, my tags are context, duration and priority

repeat with aTagName in tagNames
if aTagName starts with "@" then
return aTagName
end if
end repeat
return ""

end FindContextName -- End FindContextName


--------------------------------------------------
--------------------------------------------------
-- Remove the CRs from a string,
-- not used in this script,
-- carry over from prior implementation
--------------------------------------------------
--------------------------------------------------
on ReplaceText(find, replace, subject)
-- Example usage
-- ReplaceText("Windows", "the Mac OS", "I love Windows and I will always love Windows and I have always loved Windows.")

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 ReplaceText -- End replaceText()

[/CODE]

kimomni 2010-02-03 11:11 AM

Help using scripts
 
I am ready to come back to Omni Focus from Things.

Please tell me how to use this script.
I don't have a clue.

Thank you in advance for any instructions you can provide.

Kim


All times are GMT -8. The time now is 06:33 AM.

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