using subroutines in my script -- please help

Hi… I am working on a version of my script that utilizes interface builder in applescript studio-- but before I can do that, I need to make sure that my script will work using many subroutines rather than how it was previously (in one big tell statement)… Currently, I am unable to get applescript to carry over the information from “theNames” and “theBook” and be able to extract the appropriate information out of them— and I’m not sure if I am going about this the right way or not-- using global??? please help!

The script never seems to make it eto the gatherdata subroutine, as I never get a “i’m here” message…

global thebook
global theNames
global totalskip

set emaildata to {}
set groupdata to {}
set compilationList to ""
set totalskip to 0
set thebook to {}
set totalcount to 0

my getpeople(thebook, totalcount)

repeat with theNames in thebook
	my gatherdata(theNames)
end repeat

my writefile(compilationList, totalskip, totalcount)

on getpeople(thebook, totalcount)
	activate application "Address Book"
	tell application "Address Book"
		set thebook to every person as list
		set totalcount to (count thebook)
	end tell
end getpeople

on writefile(compilationList, totalcount)
	display dialog "converted " & totalcount & " email addresses and skipped " & totalskip & " items"
	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
end writefile

on gatherdata(compilationList, totalcount)
	tell application "Address Book"
		display dialog "im here"
		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 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 notedatat ≠ "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 companydatat ≠ "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 & "
"
		else
			set totalskip to totalskip + 1
		end if
	end tell
end gatherdata

Hi, Patrick.

You need to read up on handlers, locals, and globals.

The use of globals is generally frowned upon and is best avoided unless there’s simply no other way to achieve your aims. Values can usually be passed easily to and from handlers very easily.

The parenthesised parameter list in the first line of a handler definition consists of local variables that are set to the values passed to the handler in the call. Your ‘getpeople()’ handler isn’t doing what you think it is because you’ve specified two parameters called ‘thebook’ and ‘totalcount’. Although one of them has the same name as one of your globals, they’re implicitly local (as parameter variables) to the handler. When you ‘set thebook to every person as list’, you’re setting the local variable, not the global one.

That particular handler doesn’t use either of the values passed to it, so you could simply dispense with the parameters. This would prevent the global declarations being overridden inside the handler and your global ‘thebook’ at least would be set. However, it would be “better practice” to make the handler return a value and to set ‘thebook’ and ‘totalcount’ outside of it:

set thebook to getpeople()
set totalcount to (count thebook)

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

Your gatherdata() and writefile() handlers aren’t working because you’re not passing the right number of parameters. gatherdata() expects two parameters, but is only being passed one. writefile() also expects two parameters, but is being passed three.

I hope this has given you some pointers. :slight_smile:

Ah… ok that makes sense…

but, how can I return multiple values from within a handler?

in this example, y still will equal X… and from my attempts I cannot say return x,y-- I get an error…

set x to 55
set y to 65

my gatherdata(x, y)
set x to the result
set y to the result

on gatherdata(x, y)
	set x to x + 100
	set y to y + 150
	return x
	return y
end gatherdata

Do I need to return a list? Is there another way?

set x to 55
set y to 65

my gatherdata(x, y)
set z to the result
set x to item 1 of z
set y to item 2 of z

on gatherdata(x, y)
	set x to x + 100
	set y to y + 150
	set z to {x, y}
	return z
end gatherdata

Right. As you’ve probably gathered, the ‘return y’ line in the handler is never executed because the ‘return x’ line before it exits the handler with the value of the local x. The external x is then set to this result, and the external y is set to the result of setting the external x ” which is why they end up with the same value.

Records and script objects can also hold multiple values, but a list is probably the least effort (assuming you’re avoiding globals). It all depends what you’re doing at the time. It doesn’t have to involve a large number of lines:

set x to 55
set y to 64

set {x, y} to gatherdata(x, y)

on gatherdata(x, y)
	return {x + 100, y + 150}
end gatherdata

You can also copy them to the end of a list:


global gatherdata_list
set gatherdata_list to {}
on gatherdata(arg1,arg2)
copy arg1 to end of gatherdata_list
copy arg1 to end of gatherdata_list
end gatherdata

then later

my subroutine(Item 1 of gatherdata_list as string, Item 2 of gatherdata_list as string)

you can modify it as needed. As number, integer, real, w/e or even nothing.