Identify a QuarkXpress text box and then set content

Hi guys,

I have documents in QuarkXpress and need to insert the page number (each document is a spread).

I’m capturing the filename that have the page numbers (eg. 20-21 product.qxp). I have the left folio value in one variable and the right folio in another one.


tell application "QuarkXPress"
	set document_name to name of front document as text
	set left_folio to first word of document_name
	set right_folio to second word of document_name
	set text box "Right Folio" to right_folio
	-- I'm setting this name in QuarkXpress as Component name.
	set text box "Left Folio" to left_folio
end tell

How can I identify the text boxes already created in the document for the folio numbers (one at the bottom left and one at the bottom right), and how can I set that text boxes with the values stores in the variables.

My script gives an error that cannot store the value.

Thank you for your help.

HI! In order to target a box in QuarkXPress via AS, you need to first name it (doable only via AS).
Example:

tell application "QuarkXPress9"
	tell document 1
		set the name of current box to "Yes"
		set color of generic box "Yes" to "Cyan" -- the box that was selected in Quark is all cyan now unless fade is set to 0% :-)
	end tell
end tell

From there, you can fine tune the code in order to first locate a folio text box thanks to its coordinates or whatever via AS.
Second, to placing text in a text box you need to set the story (or the content) of the box. Not the box itself. Does it make sense?
Example:

tell application "QuarkXPress9"
	tell document 1
		set the name of current box to "Yes"
		set story 1 of text box "Yes" to "Cyan" -- provided the box that was seleted in Quark was a text box, its contents is now set "Cyan" as text
	end tell
end tell

Thank you CMYS for your help. I have some more questions.
When you use the sentence “set the name of current box to…” . If I have multiple text boxes in the document, how do you know which text box is the current one ?
How do you set the the name for two boxes? (right and left page).
Thanks!

Hi there jarchscript,

If you select a text box in Quark you can use the script below to set the name:


tell application "QuarkXPress"
	set thisBox to selection
	set name of thisBox to "MyBoxName"
end tell

If you then use this script you can check the name of the box:


tell application "QuarkXPress"
	set thisBox to selection
	set checkNameOfItem to name of thisBox
end tell

This is ok if you can name the folio text boxes prior to creating all the pages. It looks like you already have all the Quark docs so you need a different way to access the relevant folio boxes.
What you could do is create a reference to all the boxes on a page, a bit like this:


tell application "QuarkXPress"
	tell document 1
		tell page 1
			set aListOfTheTextBoxesOnThePage to every text box
		end tell
	end tell

Providing there aren’t too many boxes you can then loop through all the items in the list. You’d check the coordinates of each box to see if it falls within the positional bounds of the folio box. If it does, you’ve probably got the box you want. You’d then set story of that box to the folio number.

HTH

Well the code is actually targeting the selected text or generic box in Quark. If you have no box selected and want to target a specific one, then you’ll want to have your code see what boxes are on your page and then choose the one matching your criterias. Mind the hierarchy of objects in the application: you cannot target some objects unless wrapped into a tell block (for instance, you cannot get properties of a box if you are straight in a tell application block). That might be obvious but we sometimes hit a wall just because of that.

So sth like get bounds of every text box of current page (provided you are on the “right” page) will return the bounds of. every text box of the page you are on. From there -and that’s another story since a couple of OSs- you can read the results and try to see the one you wish (comparing to margins, to box width, to box position, etc.). But this will require a lot more lines of code.

EDIT: What TecNik just said :slight_smile:

TecNik, CMYS, thank you for your input.
I’m seeing that this single step, of identifying and point to a specific text box, it’s not as easy as I thought.
Would you point me to useful information (commands, properties, etc.) to implement that part of what I’m trying to do?
Thank you.

You’ll want to adapt this to your needs:

tell application "QuarkXPress9"
	tell document 1
		tell current page
			set NOB to count of text boxes
			repeat with i from 1 to NOB
				set the_bounds to bounds -- box bounds = {Top, Left, Bottom, Right}
				set the_bounds to (coerce the_bounds to list)
				set {T, L, B, R} to the_bounds
				set T to (coerce (coerce T to millimeter units) to real)
				set L to (coerce (coerce L to millimeter units) to real)
				set B to (coerce (coerce B to millimeter units) to real)
				set R to (coerce (coerce R to millimeter units) to real)
				if (T + B) > 229 then
					set name of text box i to "Folio"
				end if
			end repeat
		end tell
	end tell
end tell

Nice one CMYS.

This is another variation. Is makes certain assumptions, for example the document only contains 2 pages and it’s named in this format: ‘20-21 product.qxp’. Adding a loop round this to open and close each document should give you roughly what you want.


tell application "QuarkXPress"
	
	tell document 1
		
		set nameOfDoc to name
		set {atid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, " product.qxp"}
		set theFolios to text item 1 of nameOfDoc
		set AppleScript's text item delimiters to "-"
		set folioLeft to text item 1 of theFolios
		set folioRight to text item 2 of theFolios
		set AppleScript's text item delimiters to atid
		
		set listOfBoxes to every text box
		
		repeat with thisBox in listOfBoxes
			
			set thisBoxBounds to bounds of thisBox as list
			
			set {T, L, B, R} to {(item 1 of thisBoxBounds coerce to real) as integer, (item 2 of thisBoxBounds coerce to real) as integer, (item 3 of thisBoxBounds coerce to real) as integer, (item 4 of thisBoxBounds coerce to real) as integer, story 1 of thisBox}
			
			if T > 270 and L < 9 then
				set story 1 of thisBox to folioLeft
			else if T > 270 and L > 178 then
				set story 1 of thisBox to folioRight
			end if
			
		end repeat
		
	end tell
	
end tell

HTH

Thank you guys, I adjusted to document measurements and it’s working great except for a small glitch I couldn’t fix. The folioRight is including not only the number but the product name (Eg. folioLeft result is “20”, folioRight result is “21 product name.qxp”).

Another issue. I tried to eliminate leading zeros (in cases file name is like “03-04 product set 4.qxp”) but since those values are text I couldn’t express them as integer.

Sorry about this basic questions, i’m just starting with this programming thing. Thanks!


tell application "QuarkXPress"
	
	tell document 1
		
		set nameOfDoc to name
		set {atid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, " product.qxp"}
		set theFolios to text item 1 of nameOfDoc
		
		set AppleScript's text item delimiters to "-"
		set folioLeft to text item 1 of theFolios
		set folioRight to text item 2 of theFolios
		set AppleScript's text item delimiters to atid
		
		set listOfBoxes to every text box
		repeat with thisBox in listOfBoxes
			set thisBoxBounds to bounds of thisBox as list
			
			set {T, L, B, R} to {(item 1 of thisBoxBounds coerce to real) as integer, (item 2 of thisBoxBounds coerce to real) as integer, (item 3 of thisBoxBounds coerce to real) as integer, (item 4 of thisBoxBounds coerce to real) as integer, story 1 of thisBox}
			display dialog "T:" & T & "  L:" & L & "  B:" & B & "  R:" & R -- check box position
			if T > 223 and L < 8 then
				set story 1 of thisBox to folioLeft
			else if T > 223 and L > 155 then
				set story 1 of thisBox to folioRight
			end if
		end repeat
	end tell
end tell

Hi jarchscript,

No probs with the questions, I know what it’s like when you’re starting out with the programming.

With regard to the folioRight value, does the ‘product’ or ‘product name’ change for every QDoc?
And, is there a space after the folio numbers in the filename?

Thanks

Hi TecHik,

For example for a file name “06-07 clothes1.qxp” , the right folio gets “07 clothes1.qxp”.

The left onegets the correct value “06” (Well, actually I’m trying to get just the value without the leading zero).

This happend with all documents.

In addition I noticed when the document is setted to centimeters, the script can not find the boxes. I’m seeing that CMYS sugested a property to coerce to milimiter units. I’m going to test with it.

Thanks for your help.

Try this:


tell application "QuarkXPress"
	
	tell document 1
		
		set horizontal measure to millimeters
		set vertical measure to millimeters
		
		set nameOfDoc to name
		set {atid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, space}
		set theFolios to text item 1 of nameOfDoc
		
		set AppleScript's text item delimiters to "-"
		set folioLeft to text item 1 of theFolios
		set folioRight to text item 2 of theFolios
		set AppleScript's text item delimiters to atid
		
		set listOfBoxes to every text box
		repeat with thisBox in listOfBoxes
			set thisBoxBounds to bounds of thisBox as list
			
			set {T, L, B, R} to {(item 1 of thisBoxBounds coerce to real) as integer, (item 2 of thisBoxBounds coerce to real) as integer, (item 3 of thisBoxBounds coerce to real) as integer, (item 4 of thisBoxBounds coerce to real) as integer, story 1 of thisBox}
			display dialog "T:" & T & " L:" & L & " B:" & B & " R:" & R -- check box position
			if T > 223 and L < 8 then
				set story 1 of thisBox to folioLeft
			else if T > 223 and L > 155 then
				set story 1 of thisBox to folioRight
			end if
		end repeat
	end tell
end tell

To what I get, if you set text item delimiters to “-”, you’ll get all the the right part of the file name as text item 2 of it. That’s obvious. The space would not delimit the text items (or the words) any more.
From there: or you always have a file name such as “##-## someting.qxp”, then you can just get text 1 thru 2 and then text 4 thru 5; or you always have different file names such as “#-## something.qxp” or “###-### sth else.qxp”, then you can separate “text items” by setting AS text items delimiters.
Don’t know if I’m clear. Say you have a text string (that is text between quotes in AS), you can either get a part of it by getting text 1 thru 3, or text 3 thru -1 (last character of the string); or you can get text items which by default in AS is every character, but by changing AS text item delimiters, you can get words or trunks of strings delimited by the new delimiters. So if you set those to “-”, a string like “06-07 name.qxp” will return only 2 text items: “06” and “07 name.qxp”. Is this clearer?
Call again in case you need more help.

Edit: What you could do -not saying it’s the way you must do it nor it’s an elegant solution- is to first get word 1 of the name, provided there is always a space in that name, so you’d get “06-07” for instance; and then change AS ext item delims and get text item 1 and 2.

This will hopefully get rid of the zero. It’s quick and not totally tested but give it a try.
It assumes there’s a space between the folio numbers and the product.


tell application "QuarkXPress"
	
	tell document 1
		
		set horizontal measure to millimeters
		set vertical measure to millimeters
		
		set nameOfDoc to name
		set {atid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, space}
		set theFolios to text item 1 of nameOfDoc
		
		set AppleScript's text item delimiters to "-"
		set folioLeft to (text item 1 of theFolios) - "0"
		set folioRight to (text item 2 of theFolios) - "0"
		set AppleScript's text item delimiters to atid
		
		set listOfBoxes to every text box
		repeat with thisBox in listOfBoxes
			set thisBoxBounds to bounds of thisBox as list
			
			set {T, L, B, R} to {(item 1 of thisBoxBounds coerce to real) as integer, (item 2 of thisBoxBounds coerce to real) as integer, (item 3 of thisBoxBounds coerce to real) as integer, (item 4 of thisBoxBounds coerce to real) as integer}
			display dialog "T:" & T & " L:" & L & " B:" & B & " R:" & R -- check box position
			if T > 223 and L < 8 then
				set story 1 of thisBox to folioLeft
			else if T > 223 and L > 155 then
				set story 1 of thisBox to folioRight
			end if
		end repeat
	end tell
end tell

Thank you guys, everything is working ok.
The last thing I tried to do is to run the script for all open documents so I tried something like:


repeat with n from 1 to count open documents
	tell document n
		-- run the script for a document
	end tell
end repeat

But I couldn’t find anything like “count of open documents”.
Hope this is my last question!

Try this:


repeat with n from 1 to count of documents
   tell document n
       -- run the script for a document
   end tell
end repeat

You won’t be able to work on closed documents so no need to say open.
Try this:

tell application "QuarkXPress9"
	repeat with i from 1 to count of documents
		beep 1
	end repeat
end tell

Just pay attention about the repeat loops: if you have several loops in your code, you’ll want to have as many variables as loops (so not always repeat from i to sth).

Also note that a document, since a couple of versions, means also project. Some objects will be accessible only via project 1 (such as layout 1). So if you have multi-layouts projects, you’ll need to loop in every layouts of every projects. HTH.

(Forgot to say special hello to TecNik from Publi-Script Forums :slight_smile: )

When I’d been playing around with the code I’d not used projects and layouts and all seemed fine.
I guess it’s not a given.

I did try getting the set listOfBoxes to every text box where bounds = this into one line but haven’t cracked it yet. Can get it very close but then the references seem to fail, especially when you have the coercion and integers stuff in there too.

(Hi CMYS. Yep, from Publi-Script Forums - a while ago now though :slight_smile: )

The big trouble with bounds coerced to integers is that a box set at X:13, Y:45 would return sth like 12,9999 and 44,98999. One can always play with rounding, etc. but I think it’s far easier then to compare to a fixed value and keep > or < as a comparison.

And it’s not obvious from my name here but I am Jean-Marie Schwartz on PSF :slight_smile:

The main script is working great :


tell application "QuarkXPress"
	activate
	tell document 1
		set view scale to fit spread in window
		set horizontal measure to millimeters
		set vertical measure to millimeters
		
		set nameOfDoc to name
		set {atid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, space}
		set theFolios to text item 1 of nameOfDoc
		
		set AppleScript's text item delimiters to "-"
		set folioLeft to (text item 1 of theFolios) - "0"
		set folioRight to (text item 2 of theFolios) - "0"
		set AppleScript's text item delimiters to atid
		
		set listOfBoxes to every text box
		repeat with thisBox in listOfBoxes
			set thisBoxBounds to bounds of thisBox as list
			
			set {T, L, B, R} to {(item 1 of thisBoxBounds coerce to real) as integer, (item 2 of thisBoxBounds coerce to real) as integer, (item 3 of thisBoxBounds coerce to real) as integer, (item 4 of thisBoxBounds coerce to real) as integer, story 1 of thisBox}
			
			-- display dialog "T:" & T & " L:" & L & " B:" & B & " R:" & R -- check box position
			
			if T > 223 and L < 8 then
				show thisBox
				set story 1 of thisBox to folioLeft
			else if T > 223 and L > 155 then
				set story 1 of thisBox to folioRight
			end if
		end repeat
	end tell
end tell

But I having trouble with the loop to repeat the process for all projects (documents). I’m clear that this will work with open documents only, and I’m ok with that.
When I run my code, it jump from one project to another, repeating some of them and leaving untouched another ones.
Here is what i did:


tell application "QuarkXPress"
	activate
	set numberProjects to count of projects
	set i to 0
	set n to 0
	repeat with i from 1 to numberProjects
		set n to n + 1
		-- here goes the original script
		show text box 1 of document n
		select text box 1 of document n
		set x to name of document n
		display dialog "Document " & n & ", Filename " & x
		-- here goes the original script
	end repeat
end tell

What is wrong, or what is missing?
Thanks!