Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

old appleworks files

I have got loads of files from about 10+ years ago or so. When I try to open them it says old version of appleworks can't open. Is there any software that can extract the text, I'm not bothered about formating or anything else, just the raw text.

Posted on Oct 17, 2013 8:00 AM

Reply
Question marked as Best reply

Posted on Oct 17, 2013 8:40 AM

It sounds as if you have AppleWorks 5 documents. Pages can open AppleWorks 6 Word Processing documents, but not AppleWorks 5, and the same is true of LibreOffice.


Panergy Software's docXConverter v3.2 ($19.95) can convert Appleworks 5 and 6 Word Processing documents to RTF (though it has been reported that it can only handle documents which contain only text, not those which include images or frames). This may well be your only option.


All this applies to Word Processing documents. Nothing will open AW Database documents.


If you have upgraded to Lion/Mountain Lion then you should be able to install Snow Leopard on an external hard disk and start from that (provided that the Mac did not come with anything higher than Snow Leopard originally installed); and success has been reported in running Snow Leopard under emulation in Parallels - the method is described here: it seems complex; however Snow Leopard Server is available in the Apple Store (by telephone) at a reduced price (at the time of writing) and this makes the process a lot easier. I haven't tried either method: use at your own discretion. You can then install and run AppleWorks 6 as an emergency measure if you have the install disks for it - this will open v5 documents and save them as AW6 ones, which Pages can open.

61 replies

Jan 3, 2014 1:32 AM in response to Hiroto

And here's a script to convert AppleWorks 6 spreadsheet documents to iWork'09 Numbers v2 files.


Good luck,

H


--save_AW6_SS_as_Numbers2.applescript
(*
    Convert AppleWorks v6 SS (spreadsheet) files to iWork'09's Numbers v2 files
    v0.1
    
    * Tested with Numbers 2.0.5 under OS X 10.6.8.
    * Specify property in_place in script as necessary.
    * Specify property inherit_dates in script as necessary.
    * A log file with time-stamp in name is created on desktop.
    * Original file name is always preserved except that name extension ".numbers" is added
        Note that original name extension (.cwk) is NOT removed and thus, e.g., abc.cwk will be converted to abc.cwk.numbers
        This is to avoid possible data loss in case there're file names, e.g., abc and abc.cwk in a source directory.
*)
_main()
on _main()
    script o
        property in_place : true
        (*
            true : convert files in place, i.e. converted files are saved in original directories, 
                where original source directory is archived in zip file with time-stamp in name in advance;
            false : converted files are saved under destination directory which is specified in a dialogue in script
        *)
        property inherit_dates : true
        (*
            true : destination file inherits creation date and modification date of source file
            false : destination file has creation date and modification date at the time of conversion
        *)
        property ext : ".numbers"
        property logfile : (path to desktop)'s POSIX path & (do shell script "date +'save_AW6_SS_as_Numbers4.log_%Y%m%dT%H%M%S.txt'")
        property pp : {}
        
        -- accept source directory (and destination direcotry if in_place is false)
        set srcd to (choose folder with prompt "Choose source directory where source files reside.")'s POSIX path
        if srcd ends with "/" and (count srcd) > 1 then set srcd to srcd's text 1 thru -2
        if not in_place then
            repeat
                set dstd to (choose folder with prompt "Choose destination directory where to save converted files.")'s POSIX path
                if dstd ends with "/" and (count dstd) > 1 then set dstd to dstd's text 1 thru -2
                if srcd ≠ dstd then exit repeat
                display dialog "Source and destination directories cannot be the same!" with icon stop
            end repeat
        end if
        log_printf(logfile, "conversion started in operation mode: in_place = %s, inherit_dates = %s.\\n", {in_place, inherit_dates})
        
        -- retrieve target files
        log_printf(logfile, "scanning files under %s\\n", srcd)
        set pp to _match(my is_AW_v6_SS, scan_AW_files(srcd))
        log_printf(logfile, "found %d file(s) to process.\\n", count my pp)
        
        -- process target files
        if (count my pp) > 0 then
            if in_place then
                -- archive the source directory first (zip file name = srcd_YYYY-MM-DDTHH.MM.SS.zip)
                set dst to do shell script "src=" & srcd's quoted form & "
dst=\"${src}_$(date +'%FT%H.%M.%S').zip\"
ditto -ck --keepParent --sequesterRsrc \"$src\" \"$dst\"
echo \"$dst\""
                log_printf(logfile, "archived source directory in %s\\n", dst)
                repeat with p in my pp
                    set p to p's contents
                    set q to p & ext
                    save_AW6SS_as_Numbers2(p, q, {inherit_dates:inherit_dates})
                    --do shell script "rm -f " & p's quoted form -- delete the source file [1]
                    log_printf(logfile, "converted %s  =>  %s\\n", {p, q})
                end repeat
            else
                set slen to count srcd
                repeat with p in my pp
                    set p to p's contents
                    set q to dstd & (p's text (slen + 1) thru -1) & ext
                    save_AW6SS_as_Numbers2(p, q, {inherit_dates:inherit_dates})
                    log_printf(logfile, "converted %s  =>  %s\\n", {p, q})
                end repeat
            end if
        end if
        
        -- completion notice
        log_printf(logfile, "process completed for total of %d file(s).\\n", count my pp)
        tell me
            activate
            display dialog "Done " & (count my pp) & " file(s)." giving up after 5 with icon note
        end tell
        
        (*
            [1] NOT recommended because conversion is not necessarily complete.
        *)
    end script
    tell o to run
end _main

on scan_AW_files(d)
    (*
        string d : POSIX path of source directory where to start scanning
        return list : list of POSIX paths of found files
        
        * query condition is (file name extension = "cwk") OR (file creator type = "BOBO")
    *)
    script o
        property pp : {}
        property qq : {}
        property rr : {}
        
        tell application "System Events"
            tell disk item d
                set pp to every folder's POSIX path
                repeat with p in my pp
                    set qq to my scan_AW_files(p's contents)
                    repeat with q in my qq
                        set end of my rr to q's contents
                    end repeat
                end repeat
                --set qq to every file's POSIX path whose name extension = "cwk" or (creator type = "BOBO" and file type = "CWSS")
                set qq to every file's POSIX path whose name extension = "cwk" or creator type = "BOBO"
                repeat with q in my qq
                    set end of my rr to q's contents
                end repeat
            end tell
        end tell
        return my rr's contents
    end script
    tell o to run
end scan_AW_files

on is_AW_v6_SS(f)
    (*
        string f : POSIX path of source file
        return boolean : true if f is AW version 6 WP file, false otherwise
    *)
    (*
        byte[1] = version
        byte[5..8] = BOBO
        byte[279] (when byte[1] = 0x06) = 
            0 => draw
            1 => word processing
            2 => spreadsheet
            3 => database
            4 => paint
            5 => presentation
        * byte index is 0-based
    *)
    set f to f as POSIX file
    (* -- 10.5 or later only
    return (read f from 5 for 4)'s id = {66, 79, 66, 79} and ¬
        (read f for 1)'s id = 6 and ¬
        (read f from 279 for 1)'s id = 1
    *)
    considering case
        return (read f from 5 for 4) = "BOBO" and ¬
            (ASCII number (read f for 1)) = 6 and ¬
            (ASCII number (read f from 279 for 1)) = 2
    end considering
end is_AW_v6_SS

on save_AW6SS_as_Numbers2(src, dst, {inherit_dates:inherit_dates})
    (*
        string src : POSIX path of source file
        string dst : POSIX path of destination file
        boolean inherit_dates: true for dst to inherit creation and modification dates of src, false otherwise.
        
        * src may equate to dst, in which case src is overwritten
        * intermeditate directories in dst will be created as needed if not present
    *)
    -- get source and destination file
    set srcf to src as POSIX file
    set dstf to dst as POSIX file
    
    -- open srca in Pages v4 and save it in dstf
    tell application "Numbers"
        --activate
        set k to count documents
        open srcf
        repeat until (count documents) > k
            delay 0.2
        end repeat
        tell document 1
            close saving in dstf
        end tell
    end tell
    -- wait for dst to come into existence
    wait_file_exist(dst)
    
    -- set label of destination file to label of source file -- [1]
    repeat 3 times -- max retry
        try -- [2]
            tell application "Finder"
                set lbl to item (srcf as alias)'s label index
                tell item (dstf as alias)
                    update
                    set its label index to lbl
                end tell
            end tell
            exit repeat -- exit if no error
            delay 0.5 -- wait some time before retry
        end try
    end repeat
    
    -- inherit creation and modication dates from src to tmp
    if inherit_dates then inherit_file_dates(src, dst)
    
    (*
        [1] This is required because Pages does not preserve the original label when saving file.
        [2] Finder is such an unreliable beast that it may fail even after the file indeed has come into existence.
    *)
end save_AW6SS_as_Numbers2

on wait_file_exist(f)
    (*
        string f : POSIX path of file
        
        * wait until f comes into existence
    *)
    do shell script "f=" & f's quoted form & "
until [[ -e \"$f\" ]]; do sleep 0.3; done"
end wait_file_exist

on _match(pat, aa)
    (*
        handler pat : handler to test elements in aa
        list aa : source list
        return list : list of every element a of list aa whose pat(a) = true
    *)
    script o
        property |::xx| : aa's contents
        property |::yy| : {}
        property |::f| : pat
        repeat with x in my |::xx|
            set x to x's contents
            if my |::f|(x) then set end of my |::yy| to x
        end repeat
        return my |::yy|'s contents
    end script
    tell o to run
end _match

on log_printf(f, fmt, lst)
    (*
        string f : POSIX path of log file
        string fmt : printf format string
        list lst : list of values (if lst is one item list {x}, lst may be x)
        
        * %-26s time-stamp in format %F %T%z is added to the beginning of each entry
    *)
    local args
    set args to "'%-26s'" & fmt's quoted form & " \"$(date +'%F %T%z')\" "
    repeat with a in {} & lst
        set args to args & (a as string)'s quoted form & space
    end repeat
    do shell script "printf " & args & " >> " & f's quoted form
end log_printf

on inherit_file_dates(src, dst)
    (*
        string src : POSIX path of source file
        string dst : POSIX path of destination file
        
        * If creation date of src is older than or equal to that of dst,
            this will set both creation date and modification date of dst to those of src.
        * If creation date of src is newer than that of dst,
            this will set only modification date of dst to that of src.
    *)
    do shell script "src=" & src's quoted form & "; dst=" & dst's quoted form & "
ct=$(stat -f '%SB' -t '%Y%m%d%H%M.%S' \"$src\")
mt=$(stat -f '%Sm' -t '%Y%m%d%H%M.%S' \"$src\")
touch -t $ct \"$dst\"    # set creation date (<= current creation date)
touch -mt $mt \"$dst\"    # set modification date (>= creation date)"
end inherit_file_dates

Jan 3, 2014 6:29 PM in response to Hiroto

Hiroto,

I can’t thank you enough for your help. You were correct in your guess as to why I was getting 0 files converted. All the cwk files turned out to be AW6. Despite the early dates they all must have been converted up to AW6 before the files were moved to Mountain Lion.

Your scripts to convert AW6 to Pages and AW6 to Numbers worked perfectly. All files were converted retaining their original creation and modification dates as well as their names with no truncation.

I highly recommend all the Applescripts your posted here to anyone facing a cwk conversion problem.

Thanks again for your help.

Regards,

Russ

Jan 4, 2014 2:05 AM in response to rrobelen

Hello


My pleasure! Glad to hear they served you well. 🙂


Just for future reference. I've noticed in my testing that the creation date cannot be preserved if the destination volume is formatted as FAT or ExFAT which could be the case in USB Flash drive. So it is advised to run the scripts on files stored in volume formatted as HFS+.


I've also found an incorrect comment in is_AW_v6_WP() and is_AW_v6_SS() handlers in the last two scripts, that is -


        * byte index is 0-based


should have been:


        * byte index is 1-based


I am often surprised to see my hands can type exactly as opposed to my mind...


All the best,

Hiroto

Jan 4, 2014 1:25 PM in response to Hiroto

Hiroto,

Thanks for your last reply. The converted files reside for now on the Snow Leopard Mac. To be safe I will be sure to format the flash drive as Mac-OS-Extended (Journaled) for their trip back to the Mountain Lion Mac. I think once created to the hard drive they will retain the dates.

Now that my project is finished I want to make a few observations. If I could be so bold, perhaps even a suggestion.

First – if you read my posting you saw that the two step semi-manual process I went through with all the cwk files was totally unnecessary as all the file were already AW6. I should have realized this when AW6 always wanted to save any I opened as Appleworks (not Appleworks 5.0 or ClarisWorks 4.0). A lack of knowledge of AW6 is my only defense. Your scriptlet scan_AW_files would have saved me this embarrassment.

Second – the script to convert AW6 to Pages worked flawlessly for me. All the files were converted on the first pass.

Third – the script to convert AW6 to Numbers did fail on a file. Your script stopped with error message “Applescript Error - Numbers got an error: Connection is invalid.” The script editor shows the same error with “number -609” added. Shortly after the big window from Apple with the message “Quit unexpectedly while using SFCompatibility plugin”. The Apple message was very very long but, unless I missed it, never gave the name of the offending file. Your report showed all the files converted up to the failure. As a user I was left on my own to find the problem file. With a folder structure with many subfolders many levels deep it was hard to determine which file was the problem. I eventually put all the files in one folder (no subfolders) and ran your script and found the file after the last one converted.

I don’t know if this is possible but If your log report was able to be report the name of the file about to be converted followed by “==> converted to …….” when the conversion finished, the log would give the name of the problem file at the end.

One problem file I was able to convert manually but never with your script. Two others sometimes failed in the same way described above but when the script was run on them again it succeeded. I attribute all this to some bug in iWorks 09 and not your script. These were minor problems to work around.

Again I say – Anyone facing a cwk conversion project would be well advised to use your scripts.

Thanks again for taking time with me to get me through my project.

Regards,

Russ

PS – I too suffer from hands in opposition to my mind.

Jan 5, 2014 3:12 AM in response to rrobelen

Hello Russ,


Thank you for valuable feedback. You're right that the logging should be refined. I chose the simplest fix to put logging statement before the conversion. The fix is minimum but for convenience, I repost the entire code of revised version of three scripts – save_AW6_WP_as_Pages4.applescript, save_AW6_SS_as_Numbers2.applescript and save_AW_as_v6.applescript.


As for the error -609 connectionInvalid, it is a sign AppleScript runtime received when target application, in this case Numbers.app, has died. It is Numbers.app's problem that I have no control. Although it is possible to terminate the script more gracefully when this sort of error raised, I'm too lazy to clean up the mess caused by a poorly written application and thus let it die as it does. 😝


By the way,

... AW6 always wanted to save any I opened as Appleworks (not Appleworks 5.0 or ClarisWorks 4.0). ...


might indicate that those AW files were of older version. If it were already AW6 file, AW6 would not present save dialogue when you're closing the file without edit. Only when it is pre-AW6 file, AW6 asks to save the opened document even without edit because the opened document is indeed a new document converted in memory. So I'd rather think your semi-manual conversions of AW/CW to AW6 had worked as expected and not at all in vain.


FWIW, there's more direct way to determine the old version files, that is to check the following option in AW6 preferences setting and open the file in question which should present an alert dialogue box for old version file.


AppleWorks > Preferences… > General > Files > Open Documents > Old Version Alert


I assumed that this option is NOT checked and indeed it should NOT be checked for the save_AW_as_v6.applescript to work correctly.


Any way, all's well that ends well.


Best wishes from Japan,

Hiroto




--save_AW6_WP_as_Pages4.applescript
(*
    Convert AppleWorks v6 WP (word processing) files to iWork'09's Pages v4 files
    v0.2
    
    v0.2 -
        changed the logging scheme from post-conversion log:
            converted x  =>  y
        to pre-conversion log:
            converting x  =>  y
        so that it can help to identify the last file which had caused the applicaton / script to crash.

    v0.1 -
        initial version
    
    * Tested with Pages 4.0.5 under OS X 10.6.8.
    * Specify property in_place in script as necessary.
    * Specify property inherit_dates in script as necessary.
    * A log file with time-stamp in name is created on desktop.
    * Original file name is always preserved except that name extension ".pages" is added
        Note that original name extension (.cwk) is NOT removed and thus, e.g., abc.cwk will be converted to abc.cwk.pages
        This is to avoid possible data loss in case there're file names, e.g., abc and abc.cwk in a source directory.
*)
_main()
on _main()
    script o
        property in_place : true
        (*
            true : convert files in place, i.e. converted files are saved in original directories, 
                where original source directory is archived in zip file with time-stamp in name in advance;
            false : converted files are saved under destination directory which is specified in a dialogue in script
        *)
        property inherit_dates : true
        (*
            true : destination file inherits creation date and modification date of source file
            false : destination file has creation date and modification date at the time of conversion
        *)
        property ext : ".pages"
        property logfile : (path to desktop)'s POSIX path & (do shell script "date +'save_AW6_WP_as_Pages4.log_%Y%m%dT%H%M%S.txt'")
        property pp : {}
        
        -- accept source directory (and destination direcotry if in_place is false)
        set srcd to (choose folder with prompt "Choose source directory where source files reside.")'s POSIX path
        if srcd ends with "/" and (count srcd) > 1 then set srcd to srcd's text 1 thru -2
        if not in_place then
            repeat
                set dstd to (choose folder with prompt "Choose destination directory where to save converted files.")'s POSIX path
                if dstd ends with "/" and (count dstd) > 1 then set dstd to dstd's text 1 thru -2
                if srcd ≠ dstd then exit repeat
                display dialog "Source and destination directories cannot be the same!" with icon stop
            end repeat
        end if
        log_printf(logfile, "conversion started in operation mode: in_place = %s, inherit_dates = %s.\\n", {in_place, inherit_dates})
        
        -- retrieve target files
        log_printf(logfile, "scanning files under %s\\n", srcd)
        set pp to _match(my is_AW_v6_WP, scan_AW_files(srcd))
        log_printf(logfile, "found %d file(s) to process.\\n", count my pp)
        
        -- process target files
        if (count my pp) > 0 then
            if in_place then
                -- archive the source directory first (zip file name = srcd_YYYY-MM-DDTHH.MM.SS.zip)
                set dst to do shell script "src=" & srcd's quoted form & "
dst=\"${src}_$(date +'%FT%H.%M.%S').zip\"
ditto -ck --keepParent --sequesterRsrc \"$src\" \"$dst\"
echo \"$dst\""
                log_printf(logfile, "archived source directory in %s\\n", dst)
                repeat with p in my pp
                    set p to p's contents
                    set q to p & ext
                    log_printf(logfile, "converting %s  =>  %s\\n", {p, q})
                    save_AW6WP_as_Pages4(p, q, {inherit_dates:inherit_dates})
                    --do shell script "rm -f " & p's quoted form -- delete the source file [1]
                end repeat
            else
                set slen to count srcd
                repeat with p in my pp
                    set p to p's contents
                    set q to dstd & (p's text (slen + 1) thru -1) & ext
                    log_printf(logfile, "converting %s  =>  %s\\n", {p, q})
                    save_AW6WP_as_Pages4(p, q, {inherit_dates:inherit_dates})
                end repeat
            end if
        end if
        
        -- completion notice
        log_printf(logfile, "process completed for total of %d file(s).\\n", count my pp)
        tell me
            activate
            display dialog "Done " & (count my pp) & " file(s)." giving up after 5 with icon note
        end tell
        
        (*
            [1] NOT recommended because conversion is not necessarily complete.
        *)
    end script
    tell o to run
end _main

on scan_AW_files(d)
    (*
        string d : POSIX path of source directory where to start scanning
        return list : list of POSIX paths of found files
        
        * query condition is (file name extension = "cwk") OR (file creator type = "BOBO")
    *)
    script o
        property pp : {}
        property qq : {}
        property rr : {}
        
        tell application "System Events"
            tell disk item d
                set pp to every folder's POSIX path
                repeat with p in my pp
                    set qq to my scan_AW_files(p's contents)
                    repeat with q in my qq
                        set end of my rr to q's contents
                    end repeat
                end repeat
                --set qq to every file's POSIX path whose name extension = "cwk" or (creator type = "BOBO" and file type = "CWWP")
                set qq to every file's POSIX path whose name extension = "cwk" or creator type = "BOBO"
                repeat with q in my qq
                    set end of my rr to q's contents
                end repeat
            end tell
        end tell
        return my rr's contents
    end script
    tell o to run
end scan_AW_files

on is_AW_v6_WP(f)
    (*
        string f : POSIX path of source file
        return boolean : true if f is AW version 6 WP file, false otherwise
    *)
    (*
        byte[1] = version
        byte[5..8] = BOBO
        byte[279] (when byte[1] = 0x06) = 
            0 => draw
            1 => word processing
            2 => spreadsheet
            3 => database
            4 => paint
            5 => presentation
        * byte index is 1-based
    *)
    set f to f as POSIX file
    (* -- 10.5 or later only
    return (read f from 5 for 4)'s id = {66, 79, 66, 79} and ¬
        (read f for 1)'s id = 6 and ¬
        (read f from 279 for 1)'s id = 1
    *)
    considering case
        return (read f from 5 for 4) = "BOBO" and ¬
            (ASCII number (read f for 1)) = 6 and ¬
            (ASCII number (read f from 279 for 1)) = 1
    end considering
end is_AW_v6_WP

on save_AW6WP_as_Pages4(src, dst, {inherit_dates:inherit_dates})
    (*
        string src : POSIX path of source file
        string dst : POSIX path of destination file
        boolean inherit_dates: true for dst to inherit creation and modification dates of src, false otherwise.
        
        * src may equate to dst, in which case src is overwritten
        * intermeditate directories in dst will be created as needed if not present
    *)
    -- get source and destination file
    set srcf to src as POSIX file
    set dstf to dst as POSIX file
    
    -- open srca in Pages v4 and save it in dstf
    tell application "Pages"
        --activate
        set k to count documents
        open srcf
        repeat until (count documents) > k
            delay 0.2
        end repeat
        tell document 1
            close saving in dstf
        end tell
    end tell
    -- wait for dst to come into existence
    wait_file_exist(dst)
    
    -- set label of destination file to label of source file -- [1]
    repeat 3 times -- max retry
        try -- [2]
            tell application "Finder"
                set lbl to item (srcf as alias)'s label index
                tell item (dstf as alias)
                    update
                    set its label index to lbl
                end tell
            end tell
            exit repeat -- exit if no error
            delay 0.5 -- wait some time before retry
        end try
    end repeat
    
    -- inherit creation and modication dates from src to tmp
    if inherit_dates then inherit_file_dates(src, dst)
    
    (*
        [1] This is required because Pages does not preserve the original label when saving file.
        [2] Finder is such an unreliable beast that it may fail even after the file indeed has come into existence.
    *)
end save_AW6WP_as_Pages4

on wait_file_exist(f)
    (*
        string f : POSIX path of file
        
        * wait until f comes into existence
    *)
    do shell script "f=" & f's quoted form & "
until [[ -e \"$f\" ]]; do sleep 0.3; done"
end wait_file_exist

on _match(pat, aa)
    (*
        handler pat : handler to test elements in aa
        list aa : source list
        return list : list of every element a of list aa whose pat(a) = true
    *)
    script o
        property |::xx| : aa's contents
        property |::yy| : {}
        property |::f| : pat
        repeat with x in my |::xx|
            set x to x's contents
            if my |::f|(x) then set end of my |::yy| to x
        end repeat
        return my |::yy|'s contents
    end script
    tell o to run
end _match

on log_printf(f, fmt, lst)
    (*
        string f : POSIX path of log file
        string fmt : printf format string
        list lst : list of values (if lst is one item list {x}, lst may be x)
        
        * %-26s time-stamp in format %F %T%z is added to the beginning of each entry
    *)
    local args
    set args to "'%-26s'" & fmt's quoted form & " \"$(date +'%F %T%z')\" "
    repeat with a in {} & lst
        set args to args & (a as string)'s quoted form & space
    end repeat
    do shell script "printf " & args & " >> " & f's quoted form
end log_printf

on inherit_file_dates(src, dst)
    (*
        string src : POSIX path of source file
        string dst : POSIX path of destination file
        
        * If creation date of src is older than or equal to that of dst,
            this will set both creation date and modification date of dst to those of src.
        * If creation date of src is newer than that of dst,
            this will set only modification date of dst to that of src.
    *)
    do shell script "src=" & src's quoted form & "; dst=" & dst's quoted form & "
ct=$(stat -f '%SB' -t '%Y%m%d%H%M.%S' \"$src\")
mt=$(stat -f '%Sm' -t '%Y%m%d%H%M.%S' \"$src\")
touch -t $ct \"$dst\"    # set creation date (<= current creation date)
touch -mt $mt \"$dst\"    # set modification date (>= creation date)"
end inherit_file_dates



-----------------------------------------------



--save_AW6_SS_as_Numbers2.applescript
(*
    Convert AppleWorks v6 SS (spreadsheet) files to iWork'09's Numbers v2 files
    v0.2
    
    v0.2 -
        changed the logging scheme from post-conversion log:
            converted x  =>  y
        to pre-conversion log:
            converting x  =>  y
        so that it can help to identify the last file which had caused the applicaton / script to crash.

    v0.1 -
        initial version
    
    * Tested with Numbers 2.0.5 under OS X 10.6.8.
    * Specify property in_place in script as necessary.
    * Specify property inherit_dates in script as necessary.
    * A log file with time-stamp in name is created on desktop.
    * Original file name is always preserved except that name extension ".numbers" is added
        Note that original name extension (.cwk) is NOT removed and thus, e.g., abc.cwk will be converted to abc.cwk.numbers
        This is to avoid possible data loss in case there're file names, e.g., abc and abc.cwk in a source directory.
*)
_main()
on _main()
    script o
        property in_place : true
        (*
            true : convert files in place, i.e. converted files are saved in original directories, 
                where original source directory is archived in zip file with time-stamp in name in advance;
            false : converted files are saved under destination directory which is specified in a dialogue in script
        *)
        property inherit_dates : true
        (*
            true : destination file inherits creation date and modification date of source file
            false : destination file has creation date and modification date at the time of conversion
        *)
        property ext : ".numbers"
        property logfile : (path to desktop)'s POSIX path & (do shell script "date +'save_AW6_SS_as_Numbers4.log_%Y%m%dT%H%M%S.txt'")
        property pp : {}
        
        -- accept source directory (and destination direcotry if in_place is false)
        set srcd to (choose folder with prompt "Choose source directory where source files reside.")'s POSIX path
        if srcd ends with "/" and (count srcd) > 1 then set srcd to srcd's text 1 thru -2
        if not in_place then
            repeat
                set dstd to (choose folder with prompt "Choose destination directory where to save converted files.")'s POSIX path
                if dstd ends with "/" and (count dstd) > 1 then set dstd to dstd's text 1 thru -2
                if srcd ≠ dstd then exit repeat
                display dialog "Source and destination directories cannot be the same!" with icon stop
            end repeat
        end if
        log_printf(logfile, "conversion started in operation mode: in_place = %s, inherit_dates = %s.\\n", {in_place, inherit_dates})
        
        -- retrieve target files
        log_printf(logfile, "scanning files under %s\\n", srcd)
        set pp to _match(my is_AW_v6_SS, scan_AW_files(srcd))
        log_printf(logfile, "found %d file(s) to process.\\n", count my pp)
        
        -- process target files
        if (count my pp) > 0 then
            if in_place then
                -- archive the source directory first (zip file name = srcd_YYYY-MM-DDTHH.MM.SS.zip)
                set dst to do shell script "src=" & srcd's quoted form & "
dst=\"${src}_$(date +'%FT%H.%M.%S').zip\"
ditto -ck --keepParent --sequesterRsrc \"$src\" \"$dst\"
echo \"$dst\""
                log_printf(logfile, "archived source directory in %s\\n", dst)
                repeat with p in my pp
                    set p to p's contents
                    set q to p & ext
                    log_printf(logfile, "converting %s  =>  %s\\n", {p, q})
                    save_AW6SS_as_Numbers2(p, q, {inherit_dates:inherit_dates})
                    --do shell script "rm -f " & p's quoted form -- delete the source file [1]
                end repeat
            else
                set slen to count srcd
                repeat with p in my pp
                    set p to p's contents
                    set q to dstd & (p's text (slen + 1) thru -1) & ext
                    log_printf(logfile, "converting %s  =>  %s\\n", {p, q})
                    save_AW6SS_as_Numbers2(p, q, {inherit_dates:inherit_dates})
                end repeat
            end if
        end if
        
        -- completion notice
        log_printf(logfile, "process completed for total of %d file(s).\\n", count my pp)
        tell me
            activate
            display dialog "Done " & (count my pp) & " file(s)." giving up after 5 with icon note
        end tell
        
        (*
            [1] NOT recommended because conversion is not necessarily complete.
        *)
    end script
    tell o to run
end _main

on scan_AW_files(d)
    (*
        string d : POSIX path of source directory where to start scanning
        return list : list of POSIX paths of found files
        
        * query condition is (file name extension = "cwk") OR (file creator type = "BOBO")
    *)
    script o
        property pp : {}
        property qq : {}
        property rr : {}
        
        tell application "System Events"
            tell disk item d
                set pp to every folder's POSIX path
                repeat with p in my pp
                    set qq to my scan_AW_files(p's contents)
                    repeat with q in my qq
                        set end of my rr to q's contents
                    end repeat
                end repeat
                --set qq to every file's POSIX path whose name extension = "cwk" or (creator type = "BOBO" and file type = "CWSS")
                set qq to every file's POSIX path whose name extension = "cwk" or creator type = "BOBO"
                repeat with q in my qq
                    set end of my rr to q's contents
                end repeat
            end tell
        end tell
        return my rr's contents
    end script
    tell o to run
end scan_AW_files

on is_AW_v6_SS(f)
    (*
        string f : POSIX path of source file
        return boolean : true if f is AW version 6 WP file, false otherwise
    *)
    (*
        byte[1] = version
        byte[5..8] = BOBO
        byte[279] (when byte[1] = 0x06) = 
            0 => draw
            1 => word processing
            2 => spreadsheet
            3 => database
            4 => paint
            5 => presentation
        * byte index is 1-based
    *)
    set f to f as POSIX file
    (* -- 10.5 or later only
    return (read f from 5 for 4)'s id = {66, 79, 66, 79} and ¬
        (read f for 1)'s id = 6 and ¬
        (read f from 279 for 1)'s id = 1
    *)
    considering case
        return (read f from 5 for 4) = "BOBO" and ¬
            (ASCII number (read f for 1)) = 6 and ¬
            (ASCII number (read f from 279 for 1)) = 2
    end considering
end is_AW_v6_SS

on save_AW6SS_as_Numbers2(src, dst, {inherit_dates:inherit_dates})
    (*
        string src : POSIX path of source file
        string dst : POSIX path of destination file
        boolean inherit_dates: true for dst to inherit creation and modification dates of src, false otherwise.
        
        * src may equate to dst, in which case src is overwritten
        * intermeditate directories in dst will be created as needed if not present
    *)
    -- get source and destination file
    set srcf to src as POSIX file
    set dstf to dst as POSIX file
    
    -- open srca in Pages v4 and save it in dstf
    tell application "Numbers"
        --activate
        set k to count documents
        open srcf
        repeat until (count documents) > k
            delay 0.2
        end repeat
        tell document 1
            close saving in dstf
        end tell
    end tell
    -- wait for dst to come into existence
    wait_file_exist(dst)
    
    -- set label of destination file to label of source file -- [1]
    repeat 3 times -- max retry
        try -- [2]
            tell application "Finder"
                set lbl to item (srcf as alias)'s label index
                tell item (dstf as alias)
                    update
                    set its label index to lbl
                end tell
            end tell
            exit repeat -- exit if no error
            delay 0.5 -- wait some time before retry
        end try
    end repeat
    
    -- inherit creation and modication dates from src to tmp
    if inherit_dates then inherit_file_dates(src, dst)
    
    (*
        [1] This is required because Pages does not preserve the original label when saving file.
        [2] Finder is such an unreliable beast that it may fail even after the file indeed has come into existence.
    *)
end save_AW6SS_as_Numbers2

on wait_file_exist(f)
    (*
        string f : POSIX path of file
        
        * wait until f comes into existence
    *)
    do shell script "f=" & f's quoted form & "
until [[ -e \"$f\" ]]; do sleep 0.3; done"
end wait_file_exist

on _match(pat, aa)
    (*
        handler pat : handler to test elements in aa
        list aa : source list
        return list : list of every element a of list aa whose pat(a) = true
    *)
    script o
        property |::xx| : aa's contents
        property |::yy| : {}
        property |::f| : pat
        repeat with x in my |::xx|
            set x to x's contents
            if my |::f|(x) then set end of my |::yy| to x
        end repeat
        return my |::yy|'s contents
    end script
    tell o to run
end _match

on log_printf(f, fmt, lst)
    (*
        string f : POSIX path of log file
        string fmt : printf format string
        list lst : list of values (if lst is one item list {x}, lst may be x)
        
        * %-26s time-stamp in format %F %T%z is added to the beginning of each entry
    *)
    local args
    set args to "'%-26s'" & fmt's quoted form & " \"$(date +'%F %T%z')\" "
    repeat with a in {} & lst
        set args to args & (a as string)'s quoted form & space
    end repeat
    do shell script "printf " & args & " >> " & f's quoted form
end log_printf

on inherit_file_dates(src, dst)
    (*
        string src : POSIX path of source file
        string dst : POSIX path of destination file
        
        * If creation date of src is older than or equal to that of dst,
            this will set both creation date and modification date of dst to those of src.
        * If creation date of src is newer than that of dst,
            this will set only modification date of dst to that of src.
    *)
    do shell script "src=" & src's quoted form & "; dst=" & dst's quoted form & "
ct=$(stat -f '%SB' -t '%Y%m%d%H%M.%S' \"$src\")
mt=$(stat -f '%Sm' -t '%Y%m%d%H%M.%S' \"$src\")
touch -t $ct \"$dst\"    # set creation date (<= current creation date)
touch -mt $mt \"$dst\"    # set modification date (>= creation date)"
end inherit_file_dates



-----------------------------------------------



--save_AW_as_v6.applescript
(*
    Convert files of AppleWorks / ClarisWorks prior to version 6 to AppleWorks 6 files.
    v0.3
    
    v0.3 -
        changed the logging scheme from post-conversion log:
            converted x  =>  y
        to pre-conversion log:
            converting x  =>  y
        so that it can help to identify the last file which had caused the applicaton / script to crash.
    
    v0.2 -
        added optional function to inherit creation and modification dates of source files
    
    v0.1 -
        initial version
    
    * Tested with AppleWorks 6.2.4 under OS X 10.6.8.
    * AppleWorks 6.2.9 may fail to open old ClarisWorks files, in which case use older version such as AppleWorks 6.2.4.
    * Specify property in_place in script as necessary.
    * Specify property inherit_dates in script as necessary.
    * A log file with time-stamp in name is created on desktop.
    * Original file name is always preserved.
        Name extension ".cwk" is not added in destination file if it is missing in source file.
        This is to avoid possible data loss in case there're file names, e.g., abc and abc.cwk in a source directory.
*)
_main()
on _main()
    script o
        property in_place : true
        (*
            true : convert files in place, i.e. files are overwritten, 
                where original source directory is archived in zip file with time-stamp in name in advance;
            false : converted files are saved under destination directory which is specified in a dialogue in script
        *)
        property inherit_dates : true
        (*
            true : destination file inherits creation date and modification date of source file
            false : destination file has creation date and modification date at the time of conversion
        *)
        property logfile : (path to desktop)'s POSIX path & (do shell script "date +'save_AW_as_v6.log_%Y%m%dT%H%M%S.txt'")
        property pp : {}
        
        -- accept source directory (and destination direcotry if in_place is false)
        set srcd to (choose folder with prompt "Choose source directory where source files reside.")'s POSIX path
        if srcd ends with "/" and (count srcd) > 1 then set srcd to srcd's text 1 thru -2
        if not in_place then
            repeat
                set dstd to (choose folder with prompt "Choose destination directory where to save converted files.")'s POSIX path
                if dstd ends with "/" and (count dstd) > 1 then set dstd to dstd's text 1 thru -2
                if srcd ≠ dstd then exit repeat
                display dialog "Source and destination directories cannot be the same!" with icon stop
            end repeat
        end if
        log_printf(logfile, "conversion started in operation mode: in_place = %s, inherit_dates = %s.\\n", {in_place, inherit_dates})
        
        -- retrieve target files
        log_printf(logfile, "scanning files under %s\\n", srcd)
        set pp to _match(my is_AW_but_v6, scan_AW_files(srcd))
        log_printf(logfile, "found %d file(s) to process.\\n", count my pp)
        
        -- process target files
        if (count my pp) > 0 then
            if in_place then
                -- archive the source directory first (zip file name = srcd_YYYY-MM-DDTHH.MM.SS.zip)
                set dst to do shell script "src=" & srcd's quoted form & "
dst=\"${src}_$(date +'%FT%H.%M.%S').zip\"
ditto -ck --keepParent --sequesterRsrc \"$src\" \"$dst\"
echo \"$dst\""
                log_printf(logfile, "archived source directory in %s\\n", dst)
                repeat with p in my pp
                    set p to p's contents
                    log_printf(logfile, "converting %s\\n", p)
                    save_AW_as_v6(p, p, {inherit_dates:inherit_dates})
                end repeat
            else
                set slen to count srcd
                repeat with p in my pp
                    set p to p's contents
                    set q to dstd & (p's text (slen + 1) thru -1)
                    log_printf(logfile, "converting %s  =>  %s\\n", {p, q})
                    save_AW_as_v6(p, q, {inherit_dates:inherit_dates})
                end repeat
            end if
        end if
        
        -- completion notice
        log_printf(logfile, "process completed for total of %d file(s).\\n", count my pp)
        tell me
            activate
            display dialog "Done " & (count my pp) & " file(s)." giving up after 5 with icon note
        end tell
    end script
    tell o to run
end _main

on scan_AW_files(d)
    (*
        string d : POSIX path of source directory where to start scanning
        return list : list of POSIX paths of found files
        
        * query condition is (file name extension = "cwk") OR (file creator type = "BOBO")
    *)
    script o
        property pp : {}
        property qq : {}
        property rr : {}
        
        tell application "System Events"
            tell disk item d
                set pp to every folder's POSIX path
                repeat with p in my pp
                    set qq to my scan_AW_files(p's contents)
                    repeat with q in my qq
                        set end of my rr to q's contents
                    end repeat
                end repeat
                set qq to every file's POSIX path whose name extension = "cwk" or creator type = "BOBO"
                repeat with q in my qq
                    set end of my rr to q's contents
                end repeat
            end tell
        end tell
        return my rr's contents
    end script
    tell o to run
end scan_AW_files

on is_AW_but_v6(f)
    (*
        string f : POSIX path of source file
        return boolean : true if f is AW/CW file of version prior to 6, false otherwise
        
        * matching codition is (byte 1 < 0x06) AND (bytes 5..8 = 'BOBO')
    *)
    set f to f as POSIX file --as alias
    --return (read f from 5 for 4)'s id = {66, 79, 66, 79} and (read f for 1)'s id < 6 -- for 10.5 or later only
    considering case
        return (read f from 5 for 4) = "BOBO" and (ASCII number (read f for 1)) < 6
    end considering
end is_AW_but_v6

on save_AW_as_v6(src, dst, {inherit_dates:inherit_dates})
    (*
        string src : POSIX path of source file, typically file of AW5 or CW4 etc
        string dst : POSIX path of destination file
        boolean inherit_dates: true for dst to inherit creation and modification dates of src, false otherwise.
        
        * src may equate to dst, in which case src is overwritten
        * intermeditate directories in dst will be created as needed if not present
    *)
    -- get source alias
    set srca to src as POSIX file as alias
    
    -- create temp file
    set tmp to do shell script "mktemp /tmp/save_AW_as_v6.XXXXXXXX"
    set tmpa to tmp as POSIX file as alias
    
    -- convert to AW6 and save in temp file
    tell application "AppleWorks 6"
        --activate
        set k to count documents
        open srca
        repeat until (count documents) > k
            delay 0.2
        end repeat
        tell document 1
            close saving in tmpa
        end tell
    end tell
    
    -- wait for the temp file is closed
    wait_file_close(tmp)
    
    -- set label of temp file to label of source file -- [1]
    repeat 3 times -- max retry
        try -- [2]
            tell application "Finder"
                set lbl to item srca's label index
                tell item tmpa
                    update
                    set its label index to lbl
                end tell
            end tell
            exit repeat -- exit if no error
            delay 0.5 -- wait some time before retry
        end try
    end repeat
    
    -- inherit creation and modication dates from src to tmp
    if inherit_dates then inherit_file_dates(src, tmp)
    
    -- move temp file to destination file (destination directory tree is created as necessary)
    do shell script "tmp=" & tmp's quoted form & "; dst=" & dst's quoted form & "
d=${dst%/*}; [[ -d \"$d\" ]] || mkdir -p \"$d\"
mv -f \"$tmp\" \"$dst\""
    
    (*
        [1] This is required because AW6 does not preserve the original label when saving file.
        [2] Finder is such an unreliable beast that it may fail even after the file is indeed closed.
    *)
end save_AW_as_v6

on wait_file_close(f)
    (*
        string f : POSIX path of file
        
        * wait until f is no longer opened by AppleWorks
    *)
    do shell script "f=" & f's quoted form & "
while [[ $(lsof -Fc \"$f\") =~ 'AppleWorks' ]]; do sleep 0.3; done"
end wait_file_close

on _match(pat, aa)
    (*
        handler pat : handler to test elements in aa
        list aa : source list
        return list : list of every element a of list aa whose pat(a) = true
    *)
    script o
        property |::xx| : aa's contents
        property |::yy| : {}
        property |::f| : pat
        repeat with x in my |::xx|
            set x to x's contents
            if my |::f|(x) then set end of my |::yy| to x
        end repeat
        return my |::yy|'s contents
    end script
    tell o to run
end _match

on log_printf(f, fmt, lst)
    (*
        string f : POSIX path of log file
        string fmt : printf format string
        list lst : list of values (if lst is one item list {x}, lst may be x)
        
        * %-26s time-stamp in format %F %T%z is added to the beginning of each entry
    *)
    local args
    set args to "'%-26s'" & fmt's quoted form & " \"$(date +'%F %T%z')\" "
    repeat with a in {} & lst
        set args to args & (a as string)'s quoted form & space
    end repeat
    do shell script "printf " & args & " >> " & f's quoted form
end log_printf

on inherit_file_dates(src, dst)
    (*
        string src : POSIX path of source file
        string dst : POSIX path of destination file
        
        * If creation date of src is older than or equal to that of dst,
            this will set both creation date and modification date of dst to those of src.
        * If creation date of src is newer than that of dst,
            this will set only modification date of dst to that of src.
    *)
    do shell script "src=" & src's quoted form & "; dst=" & dst's quoted form & "
ct=$(stat -f '%SB' -t '%Y%m%d%H%M.%S' \"$src\")
mt=$(stat -f '%Sm' -t '%Y%m%d%H%M.%S' \"$src\")
touch -t $ct \"$dst\"    # set creation date (<= current creation date)
touch -mt $mt \"$dst\"    # set modification date (>= creation date)"
end inherit_file_dates

Jan 6, 2014 1:33 PM in response to Hiroto

Hello Hiroto,

In addition to your considerable skills with Applescript I have discovered that you are also a magician. How do I know this you may ask?

I decided to go back to square one and redo the whole project starting with the original set of AW and CW files in a folder with multiple subfolders. First I ran your revised ‘save_AW_as_v6.applescript’ on the set. It ran to completion indicating that all the files were indeed AW6 files. Next I ran your revised ‘save_AW6_WP_as_Pages4.applescript’ on the set. All the text documents were converted to Pages files in one pass. Next I ran your ‘save_AW6_SS_as_Numbers2.applescript’ on the same set and all the remaining files were converted to Numbers files in ONE pass. The earlier problem I encountered with a few files failing to convert due to problems with Numbers, magically disappeared.

Ah to have such powers.

In addition to my thanks from San Diego, California by brother also extends his thanks from Stuart, Florida.

I hope the original poster in this thread reads all this and awards you points for ‘Problem Solved’.

With Best Regards,

Russ

Jun 28, 2014 6:38 PM in response to Hiroto

Hello Hitoto,


I ran your script on an old file a friend sent to me. He said he thought the file was a text file from about 1992, maybe ClarisWorks.


The script first asked me to locate AppleWorks. I skipped that and then located the folder with the file to convert. The script returned this:


2014-06-28 11:57:17-0700 conversion started in operation mode: in_place = true, inherit_dates = true.

2014-06-28 11:57:17-0700 scanning files under /Users/bob/Desktop/Tibet

2014-06-28 11:57:17-0700 found 0 file(s) to process.

2014-06-28 11:57:17-0700 process completed for total of 0 file(s).


So, I guess the file is hopeless, huh?

Jun 28, 2014 10:59 PM in response to Bob Faulkner

Hello


I presume you're trying to use save_AW_as_v6.applescript.


First of all, in order to use that script, it is required that you have AppleWorks 6 for OS X and OS X that can run AppleWorks 6 which is a PowerPC application. If you're using 10.7 or later, you'd need to run 10.6.8 in virtual machine of your choice such as VirtualBox, Parallels Desktop or VMWare Fusion.


When these requirements are met, you should be able to choose AppleWorks 6 application when asked by AppleScript Editor.



If the script reports there's no files to process even when the files are ClarisWorks files, it could be because they have neither name exetension ".cwk" nor file creator code "BOBO". When files are transfered inappropriately via FAT formatted disk etc, creator code can be lost. If such is the case, you may simply add .cwk extension to the file manually before running the script.


Of course it is possible that these files are not ClarisWorks files and cannot be opened by AppleWorks 6. (As stated in script comment, you should be aware that AppleWorks 6.2.9 may fail to open some old ClarisWorks files and you'd need AppleWorks 6.2.4.)


By the way, if the file is MacWrite II file, you'd need AppleWorks 5 or earlier to open it, that means you need Classic environment and the script won't help.


Last but not least, if you don't have required environment and programms, you may try LibreOffice which is reportedly able to open old ClarisWorks files (as well as MacWrite II, WriteNow etc).



Good luck,

H


PS. Some resources.


https://www.virtualbox.org/

http://www.parallels.com/products/desktop/

http://www.vmware.com/products/fusion/


http://www.libreoffice.org/

https://wiki.documentfoundation.org/ReleaseNotes/4.1

http://sourceforge.net/p/libmwaw/wiki/Home/

Jun 29, 2014 1:48 AM in response to Hiroto

Hello,

Last but not least, if you don't have required environment and programms, you may try LibreOffice which is reportedly able to open old ClarisWorks files (as well as MacWrite II, WriteNow etc).

if you want to test with LibreOffice, you may want to try the latest version: i.e. LibreOffice 4.2 or even 4.3 RC1 ( which try to add more old formats)...

Feb 17, 2015 9:24 AM in response to Hiroto

THank you for these scripts. They will be a lifesaver,BUT!! Dumb question,

how do i use them??? I havent used scripts before, and have 2000 files to convert for a client today!

I Pasted cwk- aw6 in script editor, and clicked compile, and it finds things like extra spaces, etc.

do i just paste and run it, and not compile?

I feel like a complete ditz, so complete instructions would be most appreciated...

thanks!

Jul 5, 2016 1:50 AM in response to nicholas eve

Sorry to resurrect an old thread, but the grand irony of this is that there is no problem opening these .cwk files in Word for Windows if you are running Conversions Plus which comes bundled with MacDrive.


It seems negligent of Apple to leave long-time Mac users with nothing to open their old files. Fine, I can open them at work with Conversions Plus but at home on my Mac there's no easy option.

Jul 6, 2016 6:08 AM in response to matthewn5

Apple provided Pages '09 and Numbers '09 for opening respective AppleWorks v6 documents. Not so much if those documents included other AppleWork's features. We also recommend the latest LibreOffice as it can pry open ClarisWorks v5 and AppleWorks v6 documents with some ability and limitations.


One can continue using AppleWorks in either a hardware platform that supports native booting of Snow Leopard, or a Parallel's Desktop virtual machine with Snow Leopard Server installed with AppleWorks. Do not however, expect Apple to suddenly have a pang of conscience and write a conversion tool for a product that has been dead for 9 years. Even DataViz has axed Conversion Plus.

old appleworks files

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.