Working with a selection in AppleScript

G

GuyVerville

I have some scripts to prepare a Word document for a migration to Dreamweaver. I prefer coding a clean text instead of relying of the way Word saves HTML files.

I would like to work on a particular selection of text (replacing some text with another text). Here is the script:

=======================

tell application "Microsoft Word"
set myRange to text object of selection
my remplacerLI(myRange)

end tell

on remplacerLI(myRange)
my Remplacer("<p>", "<li>", myRange)
my Remplacer("</p>", "</li>", myRange)
end remplacerLI

on Remplacer(findText, replaceText, myRange)
tell application "Microsoft Word"
set theRange to myRange
my ReplaceInRange(findText, replaceText, theRange)
end tell
end Remplacer

on ReplaceInRange(findText, replaceText, theRange)
tell application "Microsoft Word"
set findObject to find object of theRange
tell findObject
set format to false
set content to findText
set content of its replacement to replaceText
set wrap to find stop
set match case to true
end tell
execute find findObject replace replace all
end tell
end ReplaceInRange

========================

After the first pass (the first call of remplacerLI function), the selection vanishes. I thought setting a range of text before calling it might resolve the problem, but this doesn't seem to work and the second call of the function remplacerLI applies to all the active document. I'm a little lost.
 
P

Paul Berkowitz

Your problem is due to the fact that you are trying to do TWO
find-and-replace operations on the original selection, but are not
re-selecting the part of the document you want between searches.

The natural result of any find (in the UI as well, please note) is to
redefine the selection to the found item. If you are doing a Replace All,
then nothing is selected. When nothing is selected (in the UI as well) the
Find will operate on the entire document.

The other thing you may not be aware of is that, in Word AppleScript,
virtually all commands and properties work on a dynamic reference, unless
they return primitive values like strings or integers. So setting a variable
to 'text object of selection' means the script will always go get the
*current* selection every time that variable is called! Even though you
thought you set myRange to a fixed range (the text object of whatever was
selected at the beginning of the script), the next time you access it for
the second run through Remplacer, it goes to get the text object of the
*current* selection - which is now just an insertion point after the first
'replace all' - so the second 'replace all' acts on the entire document.

We can work around that by hard-coding a new range, via 'create range' whose
determinants are the start and end points as derived from the range of the
original selection. The trouble with this method is that later references
again will use the hard-coded position numbers for the range. But in the
meantime, you've made several replacement of 3-character strings "<p>" with
4-character replacements "<li>". So the end point will no longer be at the
end of the last "</p>" but a few characters earlier. You can do a
rough-and-ready workaround for that by replacing the </p> end-points first,
before you do the <p> start-points. You'd have to have an enormous number of
replacements, and/or a tiny text between each <p>...text...</p> , for that
to fail

You also need to set 'match wildcards to false' in the find or you'll end up
with doubled << >>, since < and > can act as wildcards.

You've also introduced an entirely superfluous subroutine "Remplacer". You
can call ReplaceInRange directly from remplacerLI.

This works:



tell application "Microsoft Word"
set origRange to create range active document start (selection start of
selection) end (selection end of selection)
my remplacerLI(origRange)
end tell

on remplacerLI(myRange)
my ReplaceInRange("</p>", "</li>", myRange)
my ReplaceInRange("<p>", "<li>", myRange)
end remplacerLI


on ReplaceInRange(findText, replaceText, theRange)
tell application "Microsoft Word"
set findObject to find object of theRange
tell findObject
clear formatting
clear formatting (its replacement)
set format to false
set content to findText
set content of its replacement to replaceText
set wrap to find stop
set match case to true
set match wildcards to false
end tell
execute find findObject replace replace all
end tell
end ReplaceInRange





--
Paul Berkowitz
MVP MacOffice
AppleScripts for Entourage: <http://macscripter.net/scriptbuilders/>

Please "Reply To Newsgroup" to reply to this message. Emails will be
ignored.

PLEASE always state which version of Microsoft Office you are using -
**2004**, X or 2001. It's often impossible to answer your questions
otherwise.
 
G

Guy Verville

Thank you Paul for your thourough explanation. I had already discovered that
the selection was dynamic and did find that I had to create a rangeé. My
goal was also to insert a text before and after this selection. The best way
is to place first the ending text, recreate the range, etc. Thanks for
confirming this and helping me cleaning the script.

My script reads this way now:

tell application "Microsoft Word"
set debut to selection start of selection
set fin to (selection end of selection)
set myFin to create range active document start fin end fin
insert text "</ol>" at myFin
set myRange to create range active document start debut end fin + 4
my remplacerLI(myRange)
set myDebut to create range active document start debut end debut
insert text "<ol>" at myDebut
end tell

on remplacerLI(myRange)
my Remplacer("<p>", "<li>", myRange)
my Remplacer("</p>", "</li>", myRange)
end remplacerLI

on Remplacer(findText, replaceText, theRange)
tell application "Microsoft Word"
set findObject to find object of theRange
tell findObject
clear formatting
clear formatting (its replacement)
set format to false
set content to findText
set content of its replacement to replaceText
set wrap to find stop
set match case to true
set match wildcards to false
end tell
execute find findObject replace replace all
end tell
end Remplacer
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top