Evernote to DEVONthink Exporter

Description

Important Note

Screen Shot 2013-09-16 at 12.55.21 AM DEVONthink Pro has recently added it's own "Import from Evernote" feature. You should probably use that instead of this, but I'll leave this script up for reference purposes.

Script Updated on March 10, 2013

I've designed a script that:

  • Utilizes Evernote's HTML Export to copy the exported HTML file (and its constituent elements) to a temporary folder
  • Detects and Imports the Note as a PDF if the source note contained a PDF, or...
  • Bundles everything up from other types of notes into a single Web archive file and then imports it into DEVONthink, and
  • Throws the temporary files in the trash for you

Features

  • This AppleScript detect the items you've selected in Evernote and imports them into DEVONthink Pro. It also attempts to preserve metadata like tags, dates, etc. (See Below)
  • Want to steer items into a group (or make a new group)? No problem -- the script now uses DEVON's own "Group Selector" interface which will let you do that on the fly!
    DTP Group
  • The script changes the "Creation" and "Last Modified" dates to match the original item in Evernote. Tag transfer is also supported -- but must be enabled manually (see below).

Tagging

I have added the ability to transfer tags from your Evernote items into the new DEVONthink items but, for this version at least, YOU HAVE TO ENABLE IT MANUALLY!

The reason I've chosen to do it this way is because, simply put, DEVONthink treats tags like they are groups. If you bring over a bunch of notes from Evernote with lots of different tags, your group list is going to be populated with them as well. To me, this is counter-intuitive enough to where I feel the need to leave it "shut off" -- but you can certainly turn it on if that's what you prefer. If you do decide to try it, I'd suggest that you start with a few notes and examine the results in DEVONthink to see if you like it.

To enable transfer of tags, you just need open up the script in your favorite editor and change the value of the first property (called transferTags) to "ON":

Other Notes

  • The file names are sometimes altered in the exported version if they include typographical characters that would halt the file creation process;
  • Attachment transfer can be inconsistent and your file may not save with the new note. (This is something that I hope to revamp in the "2.0" version of the script!)
  • You should always proceed cautiously at first to understand how the script works before moving large amounts of your files around. I use this script myself and feel very comfortable with using it, but I cannot accept any responsibility for any data misadventure you might suffer. Use at your own risk!

INSTALLATION

  1. On this page, click the link below "The Code" preview window which says "Click here to open it in your Script Editor". This will open the AppleScript inside your system's default AppleScript Editor application.
  2. You can save this script to DEVONthink's Script Directory (in your user directory under ~/Library/Application Support/DEVONthink Pro 2/Scripts) or, in the alternate, /Library/Scripts/ and launch it using the system-wide script menu from the Mac OS X menu bar. If you don't see the system script menu, it can be activated in the Preferences of the AppleScript Editor application. (You can, of course, save the script anywhere you like!)
  3. To use, highlight the Evernote items you want to move into DEVONthink and run this script file.
  4. The "User Switches" at the beginning of the script allow you to customize the way it works. Take a look to familiarize yourself with the options I've put in for you!

FastScripts Keyboard Shortcuts (Optional)

Do yourself a favor and download FastScripts from Red Sweater. Triggering the script from the keyboard really supercharges the process -- you'll watch items practically fly into DEVONthink Pro with a few keystrokes!

For my FastScripts workflow, I am using ⌘ D (as in DEVONthink Pro) for my global "Send to DEVONthink Pro Shortcut". I use AppleScripts to move items from several programs into DEVONthink Pro -- FastScripts can detect which program I'm in and pick the appropriate script to create the note. All I have to remember is ⌘ D!

HAVING TROUBLE? FIND A BUG?

The comment thread isn't a great way to report and diagnose individual bug reports or questions. Please click here to send a bug report directly to me.

TERMS OF USE

This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

The Code

(*
http://veritrope.com
EVERNOTE TO DEVONTHINK EXPORTER
VERSION 1.72
March 10, 2013

// TERMS OF USE:
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

// LIKE THIS SCRIPT?
If this AppleScript is helpful to you, please show your support here:
http://veritrope.com/support

// SCRIPT INFORMATION AND UPDATE PAGE
-- Project Page: http://veritrope.com/code/evernote-to-devonthink-exporter/
-- FastScripts (Optional): http://bit.ly/FastScripts

// INSTALLATION:  
-- You can save this script to /Library/Scripts/ and launch it using the system-wide script menu from the Mac OS X menu bar. (The script menu can be activated using the AppleScript Utility application).
-- To use, highlight the note(s) you want to move from Evernote and run this script file;
-- The "User Switches" below allow you to customize the way this script works.

    (Optional but recommended)
    Easier Keyboard Shortcut with FastScripts
    -- Download and Install FastScripts here:
    -- http://bit.ly/FastScripts

// CHANGELOG:
* 1.72   BUGFIXES
* 1.71   DETECTION OF APP STORE/ DIRECTLY DOWNLOADED EVERNOTE VERSION
* 1.70   BUGFIXES (FILE EXPORT / SANDBOX)
* 1.63   FIX TO MAKE FILE NAME FIX WORK WITH VERITROPE "OPEN IN SCRIPT EDITOR" BUTTON
* 1.62   FIXED PDF/TAG ISSUE
* 1.61   ADDED NOTE LINKS
* 1.60   TEMPORARY REMOVAL OF GROWL
* 1.51   ADD CREATION DATE / MODIFICATION DATE TO PDF SUBROUTINE
* 1.50   MAINTENANCE RELEASE: BUGFIXES, CHANGES TO USE EVERNOTE'S NATIVE SELECTION, NEW APPROACH TO SLASHES AND COLONS IN NOTE NAMES
* 1.40   (Internal Test)
* 1.30   FIX TO ALLOW SCRIPT TO RUN FROM DEVONTHINK'S INTERNAL SCRIPT MENU, ADD SOURCE URL, CREATION DATE, MODIFICATION DATE DATA FROM EVERNOTE TO IMPORTED NOTE, TAGGING SUPPORT
* 1.23   BUGFIX FOR QUOTATION IN TITLE ISSUE
* 1.22   BUGFIX FOR ADDITIONAL CASE OF "Can’t get item 1 of {}" ERROR ("find notes"/quotation issue)
* 1.21   BUG FIXES ("Can’t get item 1 of {}" ERROR, isRunning PROPERTY)
* 1.20   BUG FIXES / BEGINNING WORK ON SNOW LEOPARD COMPATIBILITY. ADDED CREATION DATE. MODIFIED TO USE NEW GROUP SELECTOR.
* 1.10   REWRITTEN TO USE NATIVE HTML EXPORT, DETECT PDF FILES, RUN IN BACKGROUND
* 1.00   INITIAL RELEASE

*)


(*
======================================
// USER SWITCHES (YOU CAN CHANGE THESE!)
======================================
*)


property transferTags : "ON"

(*
======================================
// PROPERTIES (USE CAUTION WHEN CHANGING)
======================================
*)


property theNum : "0"
property itemexists : ""
property theFile : ""
property SaveLoc : ""
property ArchiveInput : ""
property EVNote : ""
property isRunning : "false"
property theString : ""
property noteTags : {}
property noteSource : {}
property ResourceFolder : ""
property noteName : ""
property thePDF : ""
property appType : ""

(*
======================================
// MAIN PROGRAM
======================================
*)


--SETUP
set myPath to (path to home folder)
tell application "Evernote"
    try
        --GET THE NOTES
        set SelNotes to selection
        if (SelNotes is not false) then
           
            --TEST HOME FOLDER TO DETECT APP STORE OR DIRECTLY-DOWNLOADED VERSION
            set homeFolder to (path to home folder) as text
            if homeFolder contains "Containers" then
                set appType to "AS"
            else
                set appType to "DD"
            end if
           
            --TEMP FILES PROCESSED IN EVERNOTE CONTAINER
            set ExportFolder to ((path to home folder) & "Documents:Temp Export From Evernote:" as string) as string
            set SaveLoc to my f_exists(ExportFolder)
           
            --DO THE CONVERSION
            my ENExport(SelNotes, ExportFolder)
        end if
    end try
end tell

(*
======================================
// EXPORT SUBROUTINES
======================================
*)


on ENExport(SelNotes, ExportFolder)
    --SET FOLDER FOR NOTE
    set theGroup to my GroupList()
   
    tell application "Evernote"
        set theNum to 0
       
        --PROCESS THE NOTES
        repeat with SelNote in SelNotes
            set ArchiveInput to (ExportFolder & (theNum + 1))
            set noteSource to missing value
            set evernoteName to (title of item 1 of SelNote)
           
            --TEMP CHANGE TITLE IF SLASH OR COLON IN NOTE NAME
            set html_Slash to "&#" & "47;" as string
            set html_Colon to "&#" & "58;" as string
            set noteName to my replaceString(evernoteName, "/", html_Slash)
            set noteName to my replaceString(noteName, ":", html_Colon)
            set title of SelNote to noteName
           
            --HTML EXPORT
            set theNote to (SelNote) as list
            export theNote ¬
                to ArchiveInput ¬
                format HTML
           
            --GET NOTE INFO
            set noteID to (local id of item 1 of SelNote)
            set noteSource to (source URL of item 1 of SelNote)
            set noteCreated to (creation date of item 1 of SelNote)
            set noteModified to (modification date of item 1 of SelNote)
            set noteTags to (tags of item 1 of SelNote)
            set noteLink to (note link of item 1 of SelNote)
           
            --LOOK FOR RESOURCE FOLDER
            tell application "Finder"
                try
                    set EVNote to (every document file of folder ArchiveInput whose name extension is "html")
                    set theHTML to POSIX path of (EVNote as alias)
                    set ArchiveInput to POSIX path of (ArchiveInput as alias)
                   
                    set ResourceFolder to POSIX path of ((ArchiveInput & noteName & ".resources") as string)
                    set hfs_Resource to POSIX file ResourceFolder as text
                   
                    --LOOK FOR PDF
                    set theFile to (every document file of folder hfs_Resource whose name extension is "PDF")
                    set thePDF to POSIX path of (theFile as alias)
                    set itemexists to my PDFDetect(theFile)
                end try
            end tell
           
            --IMPORT PDF IF PRESENT…
            tell application id "com.devon-technologies.thinkpro2"
                if itemexists is true then
                    set resultRecord to import thePDF ¬
                        name noteName ¬
                        to theGroup ¬
                        type pdf and postscript
                   
                    --ADD BACK EVERNOTE DATA
                    set theRecord to resultRecord
                    if noteSource is not missing value then
                        set the URL of resultRecord to noteSource
                    else
                        set the URL of resultRecord to noteLink
                    end if
                    set the creation date of resultRecord to noteCreated
                    set the modification date of resultRecord to noteModified
                   
                    if transferTags is "ON" then
                        --PROCESS TAGS
                        -- Combine the tags into a comma-delimited list
                        set allTags to {}
                        if noteTags is not missing value then
                            set oldDelim to AppleScript's text item delimiters
                            set AppleScript's text item delimiters to {", "}
                            repeat with eachTag in noteTags
                                copy (name of eachTag) to the end of allTags
                            end repeat
                        end if
                        set the tags of resultRecord to allTags
                        set AppleScript's text item delimiters to oldDelim
                    end if
                   
                    --… OR CONVERT TO WEBARCHIVE FILE!
                else
                    set outputTitle to (POSIX path of (ArchiveInput & noteName & ".webarchive"))
                    do shell script "/usr/bin/textutil -convert webarchive " & (quoted form of theHTML) & " -output " & (quoted form of outputTitle)
                   
                    --IMPORT INTO DEVONTHINK
                    set resultRecord to import outputTitle ¬
                        name noteName ¬
                        to theGroup ¬
                        type html
                   
                    --ADD BACK EVERNOTE DATA
                    set theRecord to resultRecord
                    if noteSource is not missing value then
                        set the URL of resultRecord to noteSource
                    else
                        set the URL of resultRecord to noteLink
                    end if
                    set the creation date of resultRecord to noteCreated
                    set the modification date of resultRecord to noteModified
                   
                    --FIX NAMES IF NEEDED
                    set html_Slash to "&#" & "47;" as string
                    set html_Colon to "&#" & "58;" as string
                    set (name of resultRecord) to evernoteName
                    set devonSource to source of resultRecord
                    set devonSource to my replaceString(devonSource, html_Slash, "/")
                    set devonSource to my replaceString(devonSource, html_Colon, "/")
                    set source of resultRecord to devonSource
                    tell application "Evernote" to set (title of item 1 of SelNote) to evernoteName
                   
                    if transferTags is "ON" then
                        --PROCESS TAGS
                        -- Combine the tags into a comma-delimited list
                        set allTags to {}
                        if noteTags is not missing value then
                            set oldDelim to AppleScript's text item delimiters
                            set AppleScript's text item delimiters to {", "}
                            repeat with eachTag in noteTags
                                copy (name of eachTag) to the end of allTags
                            end repeat
                        end if
                        set the tags of resultRecord to allTags
                        set AppleScript's text item delimiters to oldDelim
                    end if
                end if
            end tell
            set theNum to theNum + 1
            set itemexists to ""
        end repeat --SelNotes
       
        --DELETE THE TEMP FILE/FOLDER
        tell application "Finder" to delete SaveLoc
    end tell --EV
end ENExport

--GET LIST OF GROUPS FROM DEVONTHINK
on GroupList()
    tell application id "com.devon-technologies.thinkpro2"
        activate
        set SelGroup to display group selector "Select DEVONthink Group" buttons {"Cancel", "OK"} (*USER SELECTION FROM GROUP LIST *)
        set PreGroup to SelGroup
    end tell
end GroupList

(*
======================================
// UTILITY SUBROUTINES
======================================
*)


--APP RUNNING?
on appIsRunning(appName)
    tell application "System Events" to (name of processes) contains appName
end appIsRunning

--FOLDER CHECK
on f_exists(the_path)
    try
        get the_path as alias
        set SaveLoc to the_path
    on error
        -- MAKE NEW FOLDER IN APPROPRIATE LOCATION
        -- APP STORE VERSION
        if appType is "AS" then
            set theLocation to (path to home folder) & "Library:Containers:com.evernote.Evernote:Data:Documents" as string
            -- DIRECTLY-DOWNLOADED VERSION
        else if appType is "DD" then
            set theLocation to (path to documents folder)
        end if
        -- MAKE IT!
        tell application "Finder" to make new folder at theLocation with properties {name:"Temp Export From Evernote"}
    end try
end f_exists

--PDF CHECK
on PDFDetect(theFile)
    try
        set PDFalias to theFile as alias
        return true
    on error
        return false
    end try
end PDFDetect

--REPLACE SUBROUTINE
on replaceString(theString, theOriginalString, theNewString)
    set {od, AppleScript's text item delimiters} to {AppleScript's text item delimiters, theOriginalString}
    set theStringParts to text items of theString
    if (count of theStringParts) is greater than 1 then
        set theString to text item 1 of theStringParts as string
        repeat with eachPart in items 2 thru -1 of theStringParts
            set theString to theString & theNewString & eachPart as string
        end repeat
    end if
    set AppleScript's text item delimiters to od
    return theString
end replaceString

28 Responses to “Evernote to DEVONthink Exporter”

  1. Justin Burt April 25, 2011 at 6:00 pm #

    I am still getting this error:

    “Can’t get item 1 of {}”

    along with this one:

    Can’t set URL of missing value to “http://forum.xda-developers.com/showthread.php?t=745205″.” application name “Evernote to Devon”

    Can you be my hero and help me fix this?? I will do anything to help, I am really in trouble without this script, thanks!

    • Justin Lancy April 25, 2011 at 6:15 pm #

      Have a number of new AppleScripts — including a completely rewritten version of this one with a bunch of bug fixes!

      Hope to publish very soon… but anyone who wants to get an early look can always send me a message with the Contact Form or a note to the Veritrope.com Twitter account

    • Justin Lancy July 4, 2011 at 2:24 pm #

      Justin — I just posted a “maintenance release” of the script which I think might help… Let me know if you’re “back in business”! 😉

  2. Steve Jamieson July 1, 2011 at 12:53 am #

    Justin, any news on this script update? The current official script crashes after a few exports.
    Much appreciated.

    Steve J

    • Justin Lancy July 4, 2011 at 2:23 pm #

      Steve,

      Version 1.5 is now posted, hopefully fixing this bug. Take it for a spin and let me know if it’s better for you!

      • Steve Jamieson July 5, 2011 at 4:31 am #

        Justin, great – working well. Really well. Thanks +++. Makes using Evernote long-term reassuringly feasible.

        Steve J

  3. John July 11, 2011 at 5:15 am #

    I get a syntax error when trying to run it: Can’t get application id “com.devon-technologies.thinkpro2”.

    • Justin Lancy July 11, 2011 at 11:12 am #

      Hi John — Which version of DEVONthink are you using? (Personal, Pro, Pro Office)

      • Michael July 30, 2011 at 10:25 am #

        Hi there, I am getting the same problem. I am using DT Personal, so I changed the App ID to com.devon-technologies.think2. The result was that I get another error message:

        “Expected end of line but found identifier.”

        At this point (last line of the code excerpt):

        –IMPORT PDF IF PRESENT…
        tell application id “com.devon-technologies.think2”
        if itemexists is true then
        set resultRecord to import thePDF ¬

        Thanks for any hints!

        • Justin Lancy July 30, 2011 at 6:28 pm #

          Hi Michael,

          I’m pretty sure that DEVONthink Personal doesn’t fully support scripting — or at least not to the level necessary for this script to function.

          Since I only have DEVONthink Pro, I have no way to independently verify this… and after checking their most recent “Compare Editions” chart, it wasn’t any clearer to me! You might want to ask on the DEVONthink AppleScript forum to get some clarification.

          Please let us know what you find out!

          • Michael July 31, 2011 at 6:38 am #

            Hey Justin, thanks for the quick reply!
            I browsed the DT applescript forum and it seems that DT Personal and DT Note do not support applescript at all or just rudimentary.

            As a workaround I will install DTPro, run the script and then continue with DTPersonal…I just need the conversion once!

            Thanks for the support!
            Michael

  4. Todd Hart November 1, 2011 at 5:37 pm #

    Justin,

    I am attempting to use your script to import from Evernote Version 3.0.3 to DT Pro Office, but am getting this error, “the variable theHTML is not defined.”

    Newbie error? Fixable? Many thanks.

    Regards,
    Todd

  5. oliver April 14, 2012 at 1:19 pm #

    hey, it seemed to have stopped working; suspect that´s with Evernote 3.0.7 Beta 5 (236389)…?!

    • oliver April 14, 2012 at 1:30 pm #

      … sorry, correction:
      it also doesn´t work in the EN 3.0.5 / DTpro 2.3.3 combination 🙁

      • Justin Lancy April 14, 2012 at 2:09 pm #

        I don’t have Evernote 3.0.5 anymore, but just tested it again on 3.0.6 and 3.0.7b5 and it’s working fine here!

        If it still doesn’t work after updating Evernote to 3.0.6 and restarting, you should contact me directly using the Bug Report Form and provide your system details, screenshots, logs, etc. and I’ll take a look!

  6. Steve J July 15, 2012 at 4:58 am #

    Justin,

    Would it be possible to modify the script so the URL from Evernote is conserved in the DT document which is created. As is, the script copies the EN link in to DT. When copying over web-clippings from EN it would be great to have their original URL conserved.

    Thx.

    Steve J

    • Justin Lancy July 16, 2012 at 12:56 am #

      Hi Steve,

      It’s possible – and if enough people request it, I’ll look at how best to implement it into a future revision!

      If you don’t want to wait, I think it would be a pretty easy change to do yourself. There are several scripts in the Library and on the internet which will give you examples of how to get and use the “source URL” to do what you want.

      If you do it, feel free to post your code here!

      • Steve J July 16, 2012 at 7:58 am #

        Justin,

        Thx for response. Will give it a go.

        Steve J

  7. Dellu October 20, 2012 at 12:03 pm #

    Thank you for the script. you saved my day! I downgraded evernote to 3.2 and get all my notes into Devonthink…amazing!

  8. ChiaLynn November 1, 2012 at 4:07 pm #

    I just installed the Evernote 5.0 beta, and the script now works perfectly. I’m very excited.

  9. Rich Miller February 2, 2013 at 7:59 pm #

    While the script does fire up and ask me to which DTPO data base and folder I want to save to, after hitting the ‘save’ button, the Evernote icon bounces and nothing happens in DEVONThink.

    Checking the Evernote log, there seems to be a problem creating or writing to a temporary folder:
    2013-02-02 16:53:15 main [ENNoteHTMLExporter] INFO: error: Error Domain=NSCocoaErrorDomain Code=513 “You don’t have permission to save the file “1” in the folder “Temp Export From Evernote”.” UserInfo=0x8d750e0 {NSFilePath=/Users/xxxx/Desktop/Temp Export From Evernote/1, NSUnderlyingError=0xcac2510 “The operation couldn’t be completed. Operation not permitted”}

    The Temp Export from Evernote folder is created on the desktop, but…

    Any ideas?

    • Justin Lancy February 13, 2013 at 8:17 pm #

      Hi Rich,

      I been traveling quite a bit, but I hope to get to updating the script soon… Check back or follow on Twitter for the latest updates!

  10. korm March 3, 2013 at 5:09 pm #

    Justin, I’m not having any joy with this over here. Tracing through v1.7 in Script Debugger, I get to this statement

    tell application "Finder" to make new folder at theLocation with properties {name:"Temp Export From Evernote"}

    inside the

    on f_exists(the_path)

    subroutine. That statement appears to execute (no error is thrown) but then execution stops. The location that Finder is told to create is not created. Is this a sandboxing problem on 10.8? (I’m also using Evernote 5.0.6, but the Evernote portions of the code so far seem OK.)

    • Justin Lancy March 10, 2013 at 7:23 am #

      Update:
      Anyone having a similar issue should try the 1.72 build and let me know if that resolves the problem!

  11. Jeff MM March 22, 2013 at 11:13 am #

    Justin, many thanks for the continued updates. I installed 1.72 today and it solved earlier problem I was having.

    But new one: when I run the script (either from within Evernote using global scripts, or from within DT — I’ve installed it both places for testing), the note is created in DT in the folder I targeted, but then it immediately moves from there to the “Home” storage location in my DT database (not in any folder).

    • Justin Lancy March 22, 2013 at 12:26 pm #

      Haven’t been able to replicate this… anyone else have this issue?

      • Jeff MM March 22, 2013 at 1:50 pm #

        I’ve also posted to DT to see if they have seen it as a DT problem.

      • korm March 22, 2013 at 3:48 pm #

        I don’t see how it’s possible for this to happen in the script. On the DT side, I do extensive scripting and generally use “display group selector” to choose destinations — I’ve never seen DEVONthink fail to honor the selected group, or jump to the root of a database, etc. Be interested if anyone finds a way to reliably reproduce the reported observation.