OK, I’m at my wits’ end. I’ve fought with this all day and I am throwing in the towel. If anyone can offer some insight, an alternate way of doing this, or just wants to send me a virutal beer to cry in, here’s the problem:
I have an app I’m working on, part of which involves importing addresses from the Address Book. That part works fine, and the datasource works fine, too. For reasons I won’t go into, I have a copy of the data in a property (the same property that was originally appended to the datasource) that I wish to write out to a text file.
Now, the code works peachy in Script Editor. Here’s the Script Editor version:
property addressbookData : {}
property addressbookRecord : {|name|:"", company:"", phone:"", fax:"", email:"", street:"", city:"", state:"", zip:""}
tell application "Address Book"
repeat with myperson in (every person whose first name is greater than " ")
set |name| of addressbookRecord to name of myperson
set tempValue to (value of (every phone whose label is "work") of myperson)
if the length of tempValue is 0 then
set tempValue to (value of (every phone whose label is "home") of myperson)
end if
if the (count of tempValue) is 0 then
set |phone| of addressbookRecord to ""
else
set |phone| of addressbookRecord to first item of tempValue
end if
set tempValue to (value of (every phone whose label is "fax") of myperson)
if the length of tempValue is 0 then
set tempValue to (value of (every phone whose label contains "fax") of myperson)
end if
if the (count of tempValue) is 0 then
set fax of addressbookRecord to ""
else
set fax of addressbookRecord to first item of tempValue
end if
set |street| of addressbookRecord to street of address of myperson as string
set |city| of addressbookRecord to city of address of myperson as string
set |state| of addressbookRecord to state of address of myperson as string
set |zip| of addressbookRecord to zip of address of myperson as string
set tempValue to (value of (every email whose label is "work") of myperson)
if the length of tempValue is 0 then
set tempValue to (value of (every email whose label is "home") of myperson)
end if
if the (count of tempValue) is 0 then
set |email| of addressbookRecord to ""
else
set |email| of addressbookRecord to first item of tempValue
end if
set end of addressbookData to contents of addressbookRecord
end repeat
end tell
set myPath to choose file name with prompt "Export Clients" default name "clients.txt"
saveText(addressbookData, myPath)
display dialog "Done writing file."
on saveText(theData, theFilepath)
set theFileID to open for access theFilepath with write permission
set AppleScript's text item delimiters to {tab}
repeat with myRecord in theData
set newRecord to {}
set end of newRecord to |name| of myRecord
set end of newRecord to company of myRecord
set end of newRecord to phone of myRecord
set end of newRecord to fax of myRecord
set end of newRecord to email of myRecord
set end of newRecord to street of myRecord
set end of newRecord to city of myRecord
set end of newRecord to state of myRecord
set end of newRecord to zip of myRecord
write (newRecord as text) & return to theFileID
end repeat
set AppleScript's text item delimiters to {""}
close access theFileID
end saveText
And here’s the relevant handlers from the app, along with the property declarations:
--address globals
property addressbookData : {}
property addressbookRecord : {|name|:"", company:"", phone:"", fax:"", email:"", street:"", city:"", |state|:"", zip:""}
on importAddresses()
display window "importPanel" attached to window "invoiceWindow"
tell application "Address Book" to set theCount to count of (every person whose name is not "")
tell progress indicator "importProgress" of window "importPanel"
set uses threaded animation to true
set indeterminate to true
start
end tell
set addressbookData to {}
tell application "Address Book"
repeat with myperson in (every person whose first name is greater than " ")
set |name| of addressbookRecord to name of myperson
set tempValue to (value of (every phone whose label is "work") of myperson)
if the length of tempValue is 0 then
set tempValue to (value of (every phone whose label is "home") of myperson)
end if
if the (count of tempValue) is 0 then
set |phone| of addressbookRecord to ""
else
set |phone| of addressbookRecord to first item of tempValue
end if
set tempValue to (value of (every phone whose label is "fax") of myperson)
if the length of tempValue is 0 then
set tempValue to (value of (every phone whose label contains "fax") of myperson)
end if
if the (count of tempValue) is 0 then
set fax of addressbookRecord to ""
else
set fax of addressbookRecord to first item of tempValue
end if
set |street| of addressbookRecord to street of address of myperson as string
set |city| of addressbookRecord to city of address of myperson as string
set |state| of addressbookRecord to state of address of myperson as string
set |zip| of addressbookRecord to zip of address of myperson as string
set tempValue to (value of (every email whose label is "work") of myperson)
if the length of tempValue is 0 then
set tempValue to (value of (every email whose label is "home") of myperson)
end if
if the (count of tempValue) is 0 then
set |email| of addressbookRecord to ""
else
set |email| of addressbookRecord to first item of tempValue
end if
set end of addressbookData to contents of addressbookRecord
end repeat
end tell
append addressbookDataSource with addressbookData
close panel window "importPanel" with result 0
end importAddresses
on choose menu item theObject
(*Menu selection handler*)
if name of theObject is "exportMenu" then
set theResult to display save panel for file types {"txt"} in directory "~/Desktop" with file name "contacts.txt"
if theResult = 1 then
exportClients(path name of save panel)
end if
end if
end choose menu item
on exportClients(theFilePath)
set theFileID to open for access theFilePath with write permission
set AppleScript's text item delimiters to {tab}
repeat with myRecord in addressbookData
set newRecord to {}
set end of newRecord to |name| of myRecord
set end of newRecord to company of myRecord
set end of newRecord to phone of myRecord
set end of newRecord to fax of myRecord
set end of newRecord to email of myRecord
set end of newRecord to street of myRecord
set end of newRecord to city of myRecord
set end of newRecord to |state| of myRecord
set end of newRecord to zip of myRecord
write ((newRecord as text) & return) to theFileID
end repeat
set AppleScript's text item delimiters to {""}
close access theFileID
end exportClients
If you look carefully, you’ll see that the export handler is copied verbatim with the exception of I had to put vertical bars around the word “state” because it’s also a recognized term in the application environment. The import handler is similarly copied to the Script Editor app (or vice versa).
When I run this in the debugger, it steps through the repeat of the export handler all the way to the last record, supposedly writing the whole time to the file, yet when I get done, there is no file. AAAARRRRGGHHHH! :mad:
Also in the debugger, I see that I am getting a nice pathname for the file, the file opens and gives up a file ID ok, and the data is being transcribed ok from the addresbookData to newRecord. I can see newRecord in the variable viewer as well, and it looks like a nice little list of text items.
I’m on the verge of hysteria. If anyone can help, please do. In fact, if you want to have the app, I’ll send you the files along with the keys to my car, my cat and all her toys, and my copy of Bob Dylan’s greatest hits (ok, just kidding about the cat…)