Trouble with Pages Script...

Hi guys,

I’m still somewhat a newbie with AppleScript, and I’m having a hard time with the one I’m currently working on. It runs fine (no errors). But it just runs, and runs, and runs, and never actually does anything it’s supposed to. Where am I going wrong?

tell application “Pages”
set the_doc to document 1
tell the_doc
set num_par to (count of every paragraph)
set the_para_num to 1
set start_point to 1
set stop_point to 1
set counter to 1
repeat until the_para_num is equal to num_par
if the (name of the paragraph style of paragraph the_para_num) contains “Bold Section” then
set start_point to the_para_num
repeat until inner_loop_var is equal to num_par
if the (name of paragraph style of paragraph inner_loop_var) contains “Normal” then
set stop_point to inner_loop_var
set counter to counter + 1
set the_new_doc to make new document with properties {name:(name of document 1) & (counter as text)}
move paragraph (start_point thru end_point) of the_doc to end of the_new_doc
close the_new_doc with saving
end if
end repeat
end if
end repeat
end tell
end tell

Model: Core i3, 27" iMac, OS X Mountain Lion
AppleScript: latest version
Browser: Safari 6
Operating System: Mac OS X (10.8)

Hi.

For a start, your script never changes the values of the loop variables, so the the outer repeat’s looping forever on the first paragraph. And the variable inner_loop_var isn’t initialised anywhere in the script, so if the outer repeat wasn’t already stuck on the first paragraph, you’d get an error when the inner repeat was attempted.

The exit conditions for the repeats are the loop variables becoming equal to num_par, so the iteration involving paragraph ‘num_par’ wouldn’t be executed.

You haven’t said what the script’s supposed to do, but presumably it’s to cycle through the paragraphs of Pages’s currently open front document and save any with “Bold Section” styles to new files with names and locations yet to be specified.

Your repeat structure could possibly be something like in the script below. I haven’t tried the “new document” code, so I don’t know if it works.

tell application "Pages"
	set the_doc to document 1
	tell the_doc
		set num_par to (count paragraphs of body text)
		set the_para_num to 1
		repeat until (the_para_num is greater than num_par)
			if (the (name of the paragraph style of paragraph the_para_num) contains "Bold Section") then
				set start_point to the_para_num
				repeat with inner_loop_var from start_point to num_par
					if (the (name of paragraph style of paragraph inner_loop_var) contains "Normal") or (inner_loop_var is equal to number_par) then
						if (inner_loop_var is equal to number_par) then
							set stop_point to inner_loop_var
						else
							set stop_point to inner_loop_var - 1
						end if
						
						set the_new_doc to make new document with properties {name:(name of document 1) & (counter as text)}
						move paragraph (start_point thru end_point) of the_doc to end of the_new_doc
						close the_new_doc with saving
						
						-- Advance the outer loop variable to the first paragraph after the saved section and leave the inner repeat.
						set the_para_num to stop_point + 2 -- We already know paragraph stop_point + 1 has "Normal" styling.
						exit repeat
					end if
				end repeat
			else -- Not a bold section. Simply advance the outer loop variable.
				set the_para_num to the_para_num + 1
			end if
		end repeat
	end tell
end tell

By the way, MacScripter fora have [applescript] and [/applescript] tags which allow scripts to appear in clickable form as above. You’re encouraged to enclose any scripts you post in these. You can write the tags into your post or there’s a button just above the posting window which will enter them for you. Either click the button and paste your script between the tags which appear, or select your script in the window and then click the button.

Thank you very much! (And thanks for the tip on using the applescript tags.)

I’m still a newbie, as you can tell. You were close with the purpose of the script; but what it’s actually supposed to do is capture all the Normal text between the “Bold Section Title” styled text, including that text itself (as the heading), and then save that text to a new file. I’ve worked on it a little bit, and I’ve gotten a lot further. But now I get the error “AppleEvent handler failed.” Nonetheless, the loops now execute correctly, but then it hits that error (Script Debugger says that it’s occurring on the “set the text” command in the last loop). Any ideas?

Update: It looks as if it is, in fact, actually doing what it’s supposed to – i.e., setting the text of second_doc correctly – but it fails right after that, and Script Debugger merely highlights that particular line as being the point of failure . . . but it didn’t fail, because the text winds up where it’s supposed to. Weird, huh? Also – after this, Pages hangs and I get the spinny beach-ball; the only way to stop it is to Force Quit the app.


tell application "Pages"
	set first_doc to document 1
	set num_of_paras to (count of paragraphs of first_doc)
	set counter to 0
	set start_point to 0
	set end_point to 0
	set paras_list to {}
	tell first_doc
		repeat with index_one from 1 to num_of_paras
			if the name of the paragraph style of paragraph index_one contains "Bold Section" then
				set start_point to index_one
				repeat with index_two from index_one + 1 to num_of_paras
					if the name of paragraph style of paragraph index_two contains "Bold Section" then
						set end_point to index_two - 1
						set end of paras_list to paragraphs start_point thru end_point
					end if
				end repeat
			end if
		end repeat
	end tell
	tell application "Pages"
		repeat with para_num from 1 to (count of items in paras_list)
			set counter to counter + 1
			set second_doc to ""
			set second_doc to (make new document with properties {name:(name of first_doc) & (counter)})
			set the text of the second_doc to (item para_num of paras_list) as text
			save second_doc in path of first_doc
			close second_doc
		end repeat
	end tell
end tell

The way to set the document name seems to be to save it with that name! The following works for me. The repeat iterates through a bulk-fetched list of the paragraphs’ style names, which ought to be a bit faster than getting them from Pages one at a time:

set start_style_name to "Bold Section"

tell application "Pages"
	set first_doc to document 1
	set style_names to name of paragraph style of paragraphs of body text of first_doc
	set base_path to text 1 thru -7 of (get first_doc's path) -- The document's path without ".pages".
end tell

-- Initialise the start_point index to the position of the first instance of the start-style name.
set num_of_paras to (count style_names)
repeat with start_point from 1 to num_of_paras
	if (item start_point of style_names is start_style_name) then exit repeat
end repeat

set traversing_normal to false -- True when traversing a style which isn't the start style.
set counter to 0 -- Derived-document counter.
-- Traverse the rest of the style names and act as necessary.
repeat with i from start_point + 1 to num_of_paras
	-- If we're in a "Normal" section and hit "Bold Section" or the end of the list, export the appropriate text to a new document, set the traversing_normal flag to false, and advance the start_point index;
	-- otherwise if we're in a "Bold Section" and hit anything else, set traversing_normal to true;
	-- otherwise do nothing on this iteration.
	if (traversing_normal) then
		if (item i of style_names is start_style_name) or (i is num_of_paras) then
			if (i is num_of_paras) then
				set end_point to i
			else
				set end_point to i - 1
			end if
			set counter to counter + 1
			
			tell application "Pages"
				set new_doc to (make new document)
				set new_doc's body text to paragraphs start_point thru end_point of first_doc
				save new_doc in (base_path & counter & ".pages")
			end tell
			
			set traversing_normal to false
			set start_point to end_point + 1
		end if
	else if (item i of style_names is not start_style_name) then
		set traversing_normal to true
	end if
end repeat