Creating multiple text boxes in a Quark document

Hello,
I’ve been doing some work with Quark and Applescript, and I’ve found this site to be very useful. Therefore it is only fair to give after receiving so much! I created a little script that creates a number of new text boxes underneath an existing text box, provided that text box is the only one selected on the page.

I’ve not posted this script in a futile attempt to say ‘read my code, and marvel at its elegance’. That would be arrogant, especially as I’ve only been programming in Applescript for two weeks! Rather i’ve posted it on the off-chance that someone else new to Quark and Applescript might find this useful.

Here it is, hope it helps someone.



-- declare our local variables here.
local numSelected, numWanted
local tBoxTotal, pageCount, selectedPage
local selectedTextBox, strValue
local intHeight, intWidth, intX1, intY1, intX2, intY2
local styleList

set styleList to {"Black", "Cyan", "Magenta", "Yellow"} -- this list will hold the names of the styles we can choose from
-- This 'list of lists' holds the styles for a box, it should have the same number of items as the list above.
set setOfStyles to {{font:"Arial", size:10, color:"black"}, {font:"Copperplate", size:14, color:"cyan"}, {font:"Georgia", size:14, color:"magenta"}, {font:"Times New Roman", size:10, color:"yellow"}}

tell application "QuarkXPress"
	tell document 1
		set pageCount to (page count) -- find how many pages we have.
		
		-- Find if any text boxes are selected
		set numSelected to (count of (text boxes where selected is true))
		if (numSelected is not 1) then -- if a text box isn't selected, display this warning, and return.
			display dialog "You must select one text box"
			return
		else -- we have one box selected
			
			(* now we need to find the selected box. 
				We have to do these two loops, because I can't extract the page from the text box's reference *)
			set selectedTextBox to 0 -- initialise this. 
			repeat with pg from 1 to pageCount -- loop through our pages. Quark doesn't say which page a box is on.
				tell page pg
					set tBoxTotal to (text box count) -- Find how many text boxes we have on this page
					
					repeat with tb from 1 to tBoxTotal -- loop through the text boxes on this page
						tell text box tb
							
							if (selected is true) then
								set selectedTextBox to tb -- this is our selected text box
								set selectedPage to pg -- this is the page our selected text box is on.
								
								-- now find these details. We will use them when dropping our new boxes on a page.
								try
									copy (top of bounds of it as real) to intY1
								on error
									set intY1 to 0
								end try
								
								try
									copy (left of bounds of it as real) to intX1
								on error
									set intX1 to 0
								end try
								
								try
									copy (bottom of bounds of it as real) to intY2
								on error
									set intY2 to 0
								end try
								
								try
									copy (right of bounds of it as real) to intX2
								on error
									set intX2 to 0
								end try
								
								try
									copy (height of bounds of it as real) to intHeight
								on error
									set intHeight to 0
								end try
								
								try
									copy (width of bounds of it as real) to intWidth
								on error
									set intWidth to 0
								end try
								
								exit repeat -- exit the loop through the text boxes
							end if
						end tell -- end of working with the text box
					end repeat -- end our loop
					
					if selectedTextBox is greater than 0 then -- if we've found our selected text box
						exit repeat -- exit the loop through the pages
					end if
					
				end tell -- end of working with our pages
			end repeat -- end of our loop through the pages.
			
			(* This is an endless loop until a valid number is entered.
				There is some sparse error checking here. More testing should improve matters. *)
			repeat
				set numWanted to text returned of (display dialog "How many boxes would you like? Please choose a number less than or equal to ten" default answer "5")
				
				try
					set numWanted to coerce numWanted to integer
					if (numWanted is less than or equal to 0) or (numWanted is greater than 10) then error
					exit repeat -- if an error hasn' been thrown our number is valid so we exit the loop
				on error errmsg number errnum
					beep
					display dialog "You must enter a valid number! You entered " & numWanted & "." buttons {"Cancel", "Try Again"} default button "Try Again" with icon caution
					if button returned of result is "Cancel" then error "User canceled." number -128
				end try
			end repeat -- end of our loop
			
			-- tell the page our selected text box is on ...
			tell page selectedPage
				repeat with i from 1 to numWanted -- run through this loop creating the requested number of text boxes
					-- ask which style is wanted for this text box
					set chosenStyle to (choose from list styleList with prompt "Which style?" without multiple selections allowed)
					set chosenStyle to chosenStyle as string
					set chosenItem to my list_position(chosenStyle, styleList) -- call this method to get the appropriate style
					
					(* now make a new text box with adjusted properties based on our selected text box, and set
						the name, story, and properties of the first paragraph *)
					make text box at beginning with properties {bounds:{(intY1 + (intHeight * i)), intX1, (intY2 + (intHeight * i)), intX2}}
					set name of text box 1 to "newTB" & i
					--set color of text box 1 to "Cyan"  -- to set the colour of the text box
					set story 1 of text box 1 to "Newly created box (" & i & ")"
					set properties of paragraph 1 of story 1 of text box 1 to (item chosenItem of setOfStyles)
				end repeat -- end creating our text boxes
			end tell
			
		end if -- end of the check on whether one text box was selected
	end tell -- end of working with the document
	
end tell -- finish working with Quark

-- this method finds the index of the selected value from the list
on list_position(this_item, this_list)
	local intItem, strTestItem
	set intItem to 1 -- Make this our default selection
	repeat with i from 1 to the (count of this_list)
		set strTestItem to item i of this_list
		
		if strTestItem = this_item then
			set intItem to i
			exit repeat
		end if
	end repeat
	return intItem
end list_position