panther addressbook scripting nonsense!!!

Can someone please tell me WHY this script does not work in panther, yet works fine in Tiger???

Everything works fine except for the “if companyinfo is true” section… It says “No Result was returned from some part of this expression”… and if I change the syntax to read:

if (first name of theNames) as string ≠missing value then
set firstname to (first name of theNames)
set hasfirstname to true
else
set firstname to “”
set hasfirstname to false
end if

then I get “firstname is not defined” !!!

Both of these ways work perfectly fine in tiger… someone please help me with this nonsense!

[code]set emaildata to {}
set groupdata to {}
set compilationList to “”
set totalskip to 0
set thebook to {}
set totalcount to 0
set theNames to “”
set thebook to getpeople()
set totalcount to (count thebook)
set successful to 0
repeat with theNames in thebook
my gatherdata(theNames, compilationList, totalskip, successful)
set {compilationList, totalskip, successful} to the result
end repeat

display dialog “converted " & successful & " email addresses and skipped " & totalskip & " items” & " out of " & totalcount
set docName to choose file with prompt “Choose pine addressbook file” default location (path to home folder) with invisibles
set docPointer to (open for access docName with write permission)
set eof of docPointer to 0
write compilationList to docPointer as «class utf8»
close access docPointer

display dialog “complete!”

on getpeople()
tell application “Address Book”
activate
return every person as list
end tell
end getpeople

on gatherdata(theNames, compilationList, totalskip, successful)
set emaildata to {}
set groupdata to {}

tell application "Address Book"
	set theEmails to {}
	set thegroups to {}
	set finalemail to "("
	set finalgroup to ""
	set currentemail to 0
	set currentgroup to 0
	set commentfield to ""
	set nickfield to ""
	set fcc to ""
	set companyinfo to the (company of theNames)
	set namefield to the (name of theNames)
	set emaildata to the (email of theNames)
	set companydata to the (organization of theNames)
	set companydatat to the (organization of theNames) as string
	set groupdata to the (group of theNames)
	set notedata to the (note of theNames)
	set notedatat to notedata as string
	if companyinfo is true then
		set namefield to ""
		if suffix of theNames is not missing value then
			set suffixname to (suffix of theNames)
			set hassuffix to true
		else
			set suffixname to ""
			set hassuffix to false
		end if
		if first name of theNames is not missing value then
			set firstname to (first name of theNames)
			set hasfirstname to true
		else
			set firstname to ""
			set hasfirstname to false
		end if
		if middle name of theNames is not missing value then
			set middlename to (middle name of theNames)
			set hasmiddlename to true
		else
			set middlename to ""
			set hasmiddlename to false
		end if
		if last name of theNames is not missing value then
			set lastname to (last name of theNames)
			set haslastname to true
		else
			set lastname to ""
			set haslastname to false
		end if
		(* prefix = company on company check
		set prefix to namefield
		if hasprefix and hasfirstname then
			set namefield to namefield & space
		end if
		*)
		set namefield to namefield & firstname
		
		if hasfirstname and hasmiddlename then
			set namefield to namefield & space
		end if
		set namefield to namefield & middlename
		if hasmiddlename and haslastname then
			set namefield to namefield & space
		end if
		set namefield to namefield & lastname
		if haslastname and hassuffix then
			set namefield to namefield & space
		end if
		set namefield to namefield & suffixname
		
	end if
	
	if notedata is not missing value then
		set AppleScript's text item delimiters to "

"
set temp to text items of notedata
set AppleScript’s text item delimiters to space
set notedata to temp’s text items as string
set AppleScript’s text item delimiters to “”
set commentfield to notedata
end if
if companydata is not missing value then
set AppleScript’s text item delimiters to " "
set temp to text items of companydata
set AppleScript’s text item delimiters to “_”
set companydata to temp’s text items as string
set AppleScript’s text item delimiters to “”
set nickfield to companydata
end if

	if emaildata ≠ {} then
		repeat with thisEmailRecord in emaildata
			copy the value of thisEmailRecord to the end of theEmails
		end repeat
		set emailnumbers to count theEmails
		if emailnumbers > 1 then
			repeat emailnumbers times
				set currentemail to currentemail + 1
				set finalemail to (finalemail & item currentemail of theEmails as string)
				if currentemail ≠ emailnumbers then
					set finalemail to finalemail & ","
				end if
			end repeat
			set finalemail to finalemail & ")"
		else
			set finalemail to theEmails as string
		end if
		-- pine .addressbook format = nick, name, email, fcc, comment
		set pineline to nickfield & tab & namefield & tab & finalemail & tab & fcc & tab & commentfield
		set compilationList to compilationList & pineline & "

"
set successful to successful + 1

	else
		set totalskip to totalskip + 1
	end if
end tell
return {compilationList, totalskip, successful}

end gatherdata[/code]

Reviewing the A/S dictionary for Address Book in Panther, I do not find a “class” companyinfo.

I suggest that this may be why the Script if failing.

:o

Model: Mac Mirror Doors (G4)
AppleScript: AppleScript 1.9.3
Browser: Safari 312.3
Operating System: Mac OS X (10.3.9)

companyinfo is a variable that I set in my script…

it states:

		set companyinfo to the (company of theNames)

further, I tested this out on thoroughly in panther by modifying the section:

if suffix of theNames is not missing value then set suffixname to (suffix of theNames) set hassuffix to true else set suffixname to "" set hassuffix to false end if
I deleted everything except this if statement (of the if companyinfo statement section) and modified SUFFIX to last name, middle name, and first name.

Last name, Middle Name, and Suffix all work fine… But as soon as I change it to first name it gives me “No result was returned on some part of this expression”… Makes NO sense and is driving me insane.

-patrick

‘companyinfo’ is set to each person’s ‘company’ property. This property doesn’t exist in the Jaguar AddressBook. Maybe it’s the same in Panther?

I can’t see why you’re getting that particular error, but ‘(first name of theNames) as string’ will never equal ‘missing value’, since the latter isn’t a string.

Looking into it further on my Jaguar machine (I don’t have Panther), I’m OK with ‘last name’, ‘middle name’, and ‘first name’, but not with ‘suffix’! What does work (here) is to get the ‘properties’ of the person and then get the information from the result:

tell application "Address Book"
	set props to properties of theNames
end tell

if suffix of theProps is not missing value then
	-- blah blah blah

end if

It might be worth trying something like that in your script. I don’t know if it’ll work in Panther too ” or why. The problem seems to be a bug in earlier versions of address book.

But… are you not even making it to that section of the script because companyinfo is never getting defined since that company property doesn’t exist in Jaguar?

Well, no. Obviously I’m writing my own mini scripts to test specific aspects of the code. :slight_smile:

tell application "Address Book"
	set theBook to first person as list
	set theNames to a reference to item 1 of theBook
	--> item 1 of {person id "blah-blah-blah-blah-blah:ABPerson" of application "Address Book}
	
	-- Add these lines one by one, running the script each time and noting the results.
	first name of theNames
	--> "Nigel"
	suffix of theNames
	--> (no result)
	set props to properties of theNames
	--> {birth date:missing value, organization:"-", class:person, modification date:date "Tuesday 28 June 2005 10:31:40", job title:missing value, title:missing value, phonetic first name:missing value, nickname:missing value, id:"blah-blah-blah-blah-blah:ABPerson", home page:missing value, middle name:missing value, first name:"Nigel", name:"Nigel Garvey", maiden name:missing value, note:missing value, suffix:missing value, last name:"Garvey", creation date:date "Wednesday 19 February 2003 21:25:57", phonetic last name:missing value}
	suffix of props
	--> missing value
end tell

-- Not working outside the 'tell' block this morning. Apologies for last night's misinformation.
suffix of props

Or were you asking me to confirm that the script stops on the ‘set companyinfo’ line? The answer to that is “yes”.

In Jaguar, ‘company’ compiles as a variable, and so ‘(company of theNames)’ is nonsense to the running script, which stops with a “CannotCreateScriptCommandError” error.

If I compile the script on my Tiger machine and transfer the file to the Jaguar one, ‘company’ appears as ‘«class az51»’ when I open the file in Script Editor and the script stops at the same point with the same error.

If that’s what happens with Panther, you might consider putting the ‘set companyinfo’ line immediately above ‘if companyinfo is true’ (or just ‘if companyinfo’), in a ‘try’ block.

(tell app "Address Book")
	try
		set companyinfo to (company of theNames)
		if companyinfo then
			-- Do relevant stuff.
		end if
	on error
		-- Do nothing or do something else.
	end try
(end tell)

By the way, ‘group’ and ‘email’ are elements of a person rather than properties, so my ‘properties’ idea won’t work with them. ‘(email of theNames)’ works OK in Jaguar, as does ‘(emails of theNames)’. But ‘(group of theNames)’ and ‘(every group of theNames)’ error and ‘(groups of theNames)’ returns no result at all. :frowning:

Patrick, I’ve just been trying a modified version of your script here which aims to do pretty much the same as your original.

My address book structure may not contain sufficient detail to highlight any potential problems (and I’m not able to test in Panther), but my version returns (almost) exactly the same results as yours - without relying on the ‘company’ property, or analysing discrete name properties. (In fact, the only difference is that the file produced by your script ends with an extra LF character, due to the concatenation method that you used.)

Not sure if this alternative approach might help in any way. But since it’s slightly more handler-based, it might be a bit easier to introduce error traps where required…

Anyway, FWIW:

on listToText from l between d
	set text item delimiters to d
	tell l to beginning & ({""} & rest)
end listToText

to getOrganization(o)
	if o is missing value then return ""
	set text item delimiters to space
	listToText from o's text items between "_"
end getOrganization

to getEmail(e)
	if (count e) is 1 then return e's item 1
	tell e to my (listToText from {"(" & beginning} & rest between ",") & ")"
end getEmail

to getNote(n)
	if n is missing value then return ""
	listToText from n's paragraphs between space
end getNote

to makeEntry from {o, p, e, n}
	listToText from {getOrganization(o), p, getEmail(e), "", getNote(n)} between tab
end makeEntry

to gatherdata()
	set compilationList to {}
	set tid to text item delimiters
	tell application "Address Book" to tell people
		repeat with thisPerson in it
			tell thisPerson to if (count emails) > 0 then set compilationList's end to my ¬
				(makeEntry from its {organization, name, email's value, note})
		end repeat
		set totalcount to count
	end tell
	set successful to count compilationList
	set compilationList to listToText from compilationList between (ASCII character 10)
	set text item delimiters to tid
	{compilationList, successful, totalcount - successful, totalcount}
end gatherdata

set {compilationList, successful, totalskip, totalcount} to gatherdata()
display dialog "Converted " & successful & " email addresses and skipped " & totalskip & " items" & " out of " & totalcount & "."
set docName to choose file with prompt "Choose pine addressbook file" default location (path to home folder)
set docPointer to (open for access docName with write permission)
set eof docPointer to 0
write compilationList to docPointer as «class utf8»
close access docPointer
display dialog "Complete!"

Thanks for the replies on this… I hadn’t checked this post for a while— Im still not quite sure what im going to do about this.

My script has grown quite extensively since I last wrote-- This is an app im using XCODE to build, and it’s integrated with various windows-- preference options, etc… so it’s quite complicated now…

And I have to be honest, your method of scripting is SOOO different than mine, I read yours and im a little confused with how it works and what it’s actually doing…

[code]on listToText from l between d
set text item delimiters to d
tell l to beginning & ({“”} & rest)
end listToText

to getOrganization(o)
if o is missing value then return “”
set text item delimiters to space
listToText from o’s text items between “_”
end getOrganization

to getEmail(e)
if (count e) is 1 then return e’s item 1
tell e to my (listToText from {“(” & beginning} & rest between “,”) & “)”
end getEmail[/code]
could you possibly explain what exactly is going on here in the listToText? I’ve never seen a “tell L to beginning & (({”“] & rest)” before, so I don’t even know what that is doing!

Sure, Patrick - I’ll have a go (but please forgive me if I cover stuff with which you’re already familiar).

First, just in case there’s any doubt, let’s look at what the handler does. It’s intended to simply convert a text list (l) to text - with each text item separated by the specified delimiter (d). So it should return the following results:

The handler should also preserve any text encoding. (In other words, if fed a list of Unicode text, the text it returns is Unicode text. With a list of strings, it returns a string.)

You could, of course, achieve similar results with a more regular form of syntax:

on listToText from l between d
	set text item delimiters to d
	if class of l's item 1 is Unicode text then
		return l as Unicode text
	else
		return l as string
	end if
end listToText

However, rather than using an explicit list-to-string coercion, my original handler uses AppleScript’s concatenation rules. (If the left-hand operand is a string, the result is always a string - and AppleScript tries to coerce the value of the right-hand operand to match that of the left.)

So if we concatenate a string and a list, the list is coerced to a string - subject to the current value of AppleScript’s text item delimiters:

set text item delimiters to space
"one" & {"two", "three", "four"}
--> "onetwo three four"

Note that AppleScript’s current text item delimiter is inserted only between the list’s items, and not between the initial string and the list (hence the joined “onetwo”). To insert the delimiter between the string and the list, we can add an extra item (an empty string) to the beginning of the list:

set text item delimiters to space
"one" & {"", "two", "three", "four"}
--> "one two three four"

If the list already exists (perhaps in the form of a variable or property), then the additional item could be added to that using list concatenation:

set theList to {"two", "three", "four"}
{""} & theList
--> {"", "two", "three", "four"}

So, putting all that together, we get something like:

set theString to "one"
set theList to {"two", "three", "four"}
set text item delimiters to space
theString & ({""} & theList)
--> "one two three four"

Now - to perform this kind of operation on an entire incoming list, we need to split it into its first item (to act as the initial string) and all remaining items (a list). So we could do something like this:

Or this:

(The latter method is faster and avoids an error if ‘incomingList’ is a single-item list.)

To perform the concatenation operations described earlier (assuming that AppleScript’s text item delimiters are still set to a space character), we can now use:

However, since attributing values to variables can take slightly longer than using them direct, we could omit those operations and do this instead:

To avoid referring to ‘incomingList’ more than once, we can make it the target of a tell statement:

In this particular case, the ‘its’ aren’t strictly necessary and, if the statement appears at the end of a handler, neither is the explicit ‘return’:

Finally, if you’re unfamiliar with the ‘tell something-other-than-an-application’ approach, here are a few simple one-liners to play with:

Apologies for the length of this reply - but I hope it helps a little to clarify the syntax used in the handler. :slight_smile:

Wow… Thank you so much for that explanation… I don’t supposed you live in Southern California, do you?? Because I would love to get a real applescript lesson from you in person.

Delighted to hear it helped, Patrick. :slight_smile:

As to location, I’m usually to be found on the other side of the pond (southern England, to be more precise). However, next time I find myself golden-state-bound, I’d be happy to give you a shout. In the meantime, of course, we can all continue to enjoy the shared knowledge, experience and resources of this excellent web-site… :smiley:

Kai,

There is one other question I have about your method— You used “to” rather than “on” in the subroutines-- What does this signify? Also, what is the difference between saying:

tell namefield to my (listToText from pineline between tab)

and

set namefield to my (listToText from namefield between tab)

?

thank you in advance.