Pages: set properties to multiple items (here: words)

Hello,

I am trying to assign properties to multiple items (words) in Pages 4.3 (aka Pages 2009) with the following instruction:

set properties of {word 1, word 2, word 4} of last paragraph to {font name:"Menlo", font size:12, color:{32896, 0, 0}}

The whole Script:

tell application "Pages"
	
	activate
	try
		set the templateNames to templates

		-- prompt user to pick a template
		set thisTemplateName to (choose from list templateNames with prompt "Choose a template:")
		
		if thisTemplateName is false then
			error number -128
		end if
		
		set thisTemplateName to thisTemplateName as string
		
		-- Choose a template by dialog, create a new document and resize it
		set newDoc to make new document at front with properties {template name:thisTemplateName}
		set the bounds of the front window to {1, 22, 600, 596}
		
		tell newDoc
			make new paragraph at end of the body text with data "\"new word\" at \"end\" of \"body text\""
			set properties of words 1 thru 2 of body text to {font name:"DaxPro", font size:12, color:{32896, 0, 0}}
			set properties of word 4 of body text to {font name:"DaxPro", font size:12, color:{32896, 0, 0}}
			set the color of words 6 thru 7 of last paragraph to {0, 32896, 65535}
			
			
			make new paragraph at end of the body text with data "\"new bold paragraph\" at \"end\" of \"Body Text\" with data \"FOO\""
			set properties of last paragraph to {font name:"DINPro", font size:14}
			set properties of last word of last paragraph to {font name:"Menlo", color:{0, 32896, 65535}} 
			set properties of word 2 of last paragraph to {bold:true}
			
			-- The following instruction doesn't work; even more, it prevents the next two instructions from execution
			set properties of {word 1, word 2, word 4} of last paragraph to {font name:"Menlo", font size:12, color:{32896, 0, 0}}

			-- These two lines are prevented from execution due to the previous command		
			make new paragraph at end of the body text with data "111111"
			set (the last paragraph of the body text) to "\"last paragraph\" of  \"Body Text\"" & return 
		end tell


	end try
end tell

During one script execution (can’t reproduce it) AppleScript was able to realize the items to alter (words 1 thru 2, word 4) properly, as it was giving the output error:

Any ideas what might be wrong and how to apply properties to multiple items?

Cheers,

B.

As far as I remember, AppleScript is unable to set the properties of a list of words as you try to do.

You may do the job using :

repeat with indx in {1, 2, 4}
	set properties of word indx of last paragraph to {font name:"Menlo", font size:12, color:{32896, 0, 0}}
end repeat

I often use this alternate syntax :

tell last paragraph
	repeat with idx in {1, 2, 4}
		set properties of word idx to {font name:"Menlo", font size:12, color:{32896, 0, 0}}
	end repeat
end tell

But I’m not sure that it’s more efficient.

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) dimanche 6 mars 2016 11:53:14

I see, as Pages or AS can not set properties on multiple items the trick (workaround) is to iterate over a loop.

Regarding your concern about efficiency: For sure, its not a big deal with a few words, but the workaround is really helpful changing settings for many words in a paragraph or body text.

Therefore, many thanks again Yvan!

Hi.

This phrasing works:

set newProps to {font name:"Menlo", font size:12, color:{32896, 0, 0}}
tell last paragraph to set {properties of word 1, properties of word 2, properties of word 4} to {newProps, newProps, newProps}

Or of course you can set the properties of words 1 thru 4 to the new value and then reset the properties of word 3 to those you used when creating the paragraph.

I know you’re just trying things out here, but in case you didn’t realise, it’s possible to use ‘with data’ and ‘with properties’ in the same ‘make’ statement:

make new paragraph at end of the body text with data "\"new bold paragraph\" at \"end\" of \"Body Text\" with data \"FOO\"" with properties {font name:"DINPro", font size:14}

Hello Nigel

As I’m curious I run my two versions and yours.
When I looked in the events log I discovered that they were exactly reported the same way :

set properties of word 1 of last paragraph of document 1 to {font name:"Menlo", font size:12, color:{32896, 0, 0}}
set properties of word 2 of last paragraph of document 1 to {font name:"Menlo", font size:12, color:{32896, 0, 0}}
set properties of word 4 of last paragraph of document 1 to {font name:"Menlo", font size:12, color:{32896, 0, 0}}

I used Shane’s timer upon a loop repeating the job 100 times and got :

Yvan1 “That took 23,871233999729 seconds.”

Yvan2 “That took 23,7547929883 seconds.”

Nigel “That took 23,773276984692 seconds.”

The differences are so small that I’m not sure that they are meaningful.

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) dimanche 6 mars 2016 15:49:13

Hi Yvan.

You’re right, of course. Any method which sets the properties of non-consecutive objects is going to have to perform separate settings. It doesn’t make much difference if the overhead’s a repeat loop or a setting-by-list. It’s the individual property settings which take most of the time. I was only trying to demonstrate a successful setting-by-list syntax.

The other method I described, but didn’t illustrate, might turn out to be slightly faster (although I haven’t timed it), since it only involves two ‘set’ commands to Pages. But the user probably wouldn’t notice any difference.

-- Assumed to be in a 'tell' statement to a Pages document.
make new paragraph at end of the body text with data "\"new bold paragraph\" at \"end\" of \"Body Text\" with data \"FOO\"" with properties {font name:"DINPro", font size:14}

-- Change the properties of ALL the first four words in one go, then revert those of the third to the originals.
set properties of words 1 thru 4 of last paragraph to {font name:"Menlo", font size:12, color:{32896, 0, 0}}
set properties of word 3 of last paragraph to {font name:"DINPro", font size:14}

This could also be done by list, of course: :wink:

make new paragraph at end of the body text with data "\"new bold paragraph\" at \"end\" of \"Body Text\" with data \"FOO\"" with properties {font name:"DINPro", font size:14}

tell last paragraph to set {properties of words 1 thru 4, properties of word 3} to {{font name:"Menlo", font size:12, color:{32896, 0, 0}}, {font name:"DINPro", font size:14}}

. although it might be more sensible in this case to just change the properties of ‘words 1 thru 2’ and then of ‘word 4’:

make new paragraph at end of the body text with data "\"new bold paragraph\" at \"end\" of \"Body Text\" with data \"FOO\"" with properties {font name:"DINPro", font size:14}

tell last paragraph to set {properties of words 1 thru 2, properties of word 4} to {{font name:"Menlo", font size:12, color:{32896, 0, 0}}, {font name:"Menlo", font size:12, color:{32896, 0, 0}}}

But, again, this only shows what’s possible. The actual choice of code will depend on the overall business of the script.

Hello Nigel

I was hoping that, starting with tel last paragraph, the script will not have to “search for this paragraph” three times.
Given what appear in the log I’m not sure that I was right.

An other point puzzled me too.
When I ask for the properties of a selection in Pages I get something like :
(class:text, text indent:0.0, collapsed:false, underline color:missing value, strikethrough color:missing value, paragraph style:paragraph style Format libre of document id 24032772, color:19532, 20046, 20046, number label tiered:false, prevent widows and orphans:true, subscript:false, character style:missing value, list style:list style Aucun of document id 24032772, superscript:false, label type:none, space before:0.0, remove hyphenation:false, line spacing:1.0, baseline shift:0.0, shadow:false, label indent:0.0, contents:username/Documents/tempo/, label baseline shift:0.0, scale with text:true, italic:false, first line indent:0.0, shadow offset:missing value, shadow color:missing value, following paragraph style:missing value, font size:12.0, capitalization type:normal capitalization, space after:0.0, label size:1.0, left indent:0.0, length:27, character background color:missing value, indent level:1, label image data:missing value, right indent:0.0, shadow angle:missing value, number label style:number paren zero, paragraph background color:missing value, text label string:missing value, keep with next paragraph:false, underline type:none, bold:false, alignment:left, shadow opacity:missing value, character offset:668, shadow blur:missing value, start new page:false, line spacing type:relative, ligatures:none, outline:false, hidden:false, keep lines together:false, font name:Verdana, strikethrough type:none, containing page:page 1 of document id 24032772, tracking:0.0)

So I hoped that I would be able to change the font size or the font name. Alas, I was wrong.
I got : error “Erreur dans Pages 09 : Il est impossible de régler font size of selection of document 1 à 24.0.” number -10006 from font size of selection of document 1

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) dimanche 6 mars 2016 19:46:18

Hi Yvan.

It works for me if I ‘get’ the selection and then set those properties of the result.

Thanks Nigel.

I’m just an ass to fail to try that which is a widely spread behavior.

I was able to run :

tell application "Pages 09" to tell document 1
	tell (get the selection)
		set {font size, font name, its color} to {16, "Menlo", {32896, 0, 0}}
	end tell
end tell

It’s a new case to add to the list of apps where it’s sometime required to prefix properties whose name appears in italic blue by “its”. Without it, changing the color property is silently ignored.

In fact it would be more efficient to code :

tell application "Pages 09" to tell document 1
	set curSel to  the selection
	set properties of curSel to {font size:14, font name:"Palatino", color:{32896, 0, 0}}
end tell

Annoying detail, by hand we may define a selection containing separated words.
I found no way to do that by script.
Not too boring because the discontinuous selection isn’t available in Pages 5.x

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) dimanche 6 mars 2016 21:10:03

Hmmm. Well it appears that in Pages 4.3, multiple selections can be set by list. Thus:

tell application "Pages"
	tell body text of document 1
		select {text from character 239 to character 247, text from word 1 to word 2, words 7 thru 8, paragraph 12}
	end tell
end tell

The elements and ranges specified have to exist, of course.

Unfortunately, it seems that everything in the list has to be specified in relation to the same parent. For instance, these all work:

tell application "Pages"
	tell body text of document 1 to select {word 1, word 3}
	
	tell body text of document 1 to select {word 1 of paragraph 1, character 14 of paragraph 1}
	
	tell paragraph 1 of body text of document 1 to select {word 1, character 14}
end tell

But this errors:

tell application "Pages"
	tell body text of document 1 to select {word 1 of paragraph 1, word 1 of paragraph 2}
end tell

A trick to get round this is to select each item in turn, get its ‘character’ reference from the ‘selection’, then select a list of all the references so obtained. This has only been tested with ‘body text’:

tell application "Pages"
	tell body text of document 1
		set objectsToSelect to {a reference to word 1 of paragraph 1, a reference to word 1 of paragraph 2, a reference to paragraph 5, a reference to character 3 of word 2 of paragraph 7}
		my multiSelect(objectsToSelect)
	end tell
end tell

on multiSelect(objectRefs)
	tell application "Pages"
		repeat with thisObject in objectRefs
			-- Select the object using the passed reference.
			select thisObject
			-- Replace the passed reference with the 'character' reference returned for the selection.
			set thisObject's contents to selection
		end repeat
		-- Select the list of character references, all relating to the body text of document 1.
		select objectRefs
	end tell
end multiSelect