The usual construction is to start with a Range object that covers the
entire document body:
Dim myRange As Range
Set myRange = ActiveDocument.Range
Set the properties of the myRange.Find object (the .Text, .Replacement,
.MatchWildcards, and so forth). It's important to set myRange.Find.Wrap =
wdFindStop so the search stops at each occurrence of the target. Then write
the loop like this:
Do While myRange.Find.Execute
' do your work on myRange here
MyRange.Collapse wdCollapseEnd
Loop
The .Execute method returns True if it found the search target or False if
it didn't find it. That makes the loop stop when there are no more
occurrences between the current position of myRange and the end of the
document (you don't actually have to know whether you've "reached the end").
The .Collapse ensures that, if the target still exists within myRange after
you've worked on it, the next iteration won't find the same occurrence
again.

Signature
Regards,
Jay Freedman
Microsoft Word MVP FAQ: http://word.mvps.org
Email cannot be acknowledged; please post all follow-ups to the newsgroup so
all may benefit.
> I am doing a search on a document and need to perform some actions
> when the search criteria is met. I am having a problem getting the
> loop to stop at the end of the document. It just keeps looping. I
> am very new to Word VBA and would appreciate any help.
>
> Jeff
Jeff Mitteer - 12 Dec 2006 05:50 GMT
> The usual construction is to start with a Range object that covers the
> entire document body:
[quoted text clipped - 20 lines]
> you've worked on it, the next iteration won't find the same occurrence
> again.
Thanks. I think that will work.
Jeff
Greg Maxey - 12 Dec 2006 14:16 GMT
Jay,
I have used a construction similiar to yours many times. That is one
reason I mentioned that the OP should provide his code.
In a new document I type the words "Your text"
and run this code:
Sub Scratchmacro()
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = "Your text"
.Wrap = wdFindStop
While .Execute
oRng.Font.Color = wdColorBlue
Wend
End With
End Sub
In this simple test, it appears that .Wrap = wdFindStop is sufficient
to avoid that dreadful loop that often requires:
oRng.Collapse wdCollapseEnd ;-)
> The usual construction is to start with a Range object that covers the
> entire document body:
[quoted text clipped - 34 lines]
> >
> > Jeff
Jay Freedman - 12 Dec 2006 15:13 GMT
Hi Greg,
Of course, you're correct. I know I've been in situations where the
.Collapse was necessary, but I don't have an example handy. If I come across
one, I'll let you know what's different about it.

Signature
Regards,
Jay Freedman
Microsoft Word MVP FAQ: http://word.mvps.org
Email cannot be acknowledged; please post all follow-ups to the newsgroup so
all may benefit.
> Jay,
>
[quoted text clipped - 61 lines]
>>>
>>> Jeff
Helmut Weber - 12 Dec 2006 18:36 GMT
Hi Jay,
IMHO,
formatting does no harm,
however, replacing text seems to require
additional measures to control the range.

Signature
Greetings from Bavaria, Germany
Helmut Weber, MVP WordVBA
Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
Greg Maxey - 12 Dec 2006 20:17 GMT
Jay/Helmut,
It seems that I have been tripped up before as well with a continous
loop without the .Collapse wdCollapseEnd statement, but despite trying
for the last hour, I had to resort to some non-standard code to produce
the situation. It will occur whenever you expand the found range
within the execute statement while leaving the find.text intact. In
this rather poor example, I am adding quotes to underlined text within
a document. With the .Collapse wdCollapseEnd statement a continous
loop occurs:
Sub ScratchMacro1()
'Adds quotes to underlined text
Dim oRng As Range
Set oRng = ActiveDocument.Content
With oRng.Find
.ClearFormatting
.Text = "<*>"
.Font.Underline = True
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
Do While .Execute
With oRng
.InsertBefore Chr(34)
.InsertAfter Chr(34)
.Characters.Last.Font.Underline = False
.Collapse wdCollapseEnd
End With
Loop
End With
End Sub
For me a more common problem is the job won't complete without that
statement. Take this example where I want to underline text in quotes:
Sub ScratchMacro2()
'Underlines text exclusive of the quotes marks
Dim oRng As Range
Set oRng = ActiveDocument.Content
With oRng.Find
.ClearFormatting
.Text = """<*>"""
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
Do While .Execute
With oRng
.MoveEnd Unit:=wdCharacter, Count:=-1
.MoveStart Unit:=wdCharacter, Count:=1
.Font.Underline = True
.Collapse wdCollapseEnd
End With
Loop
End With
End Sub
Without the collapse statement the code only formats the first found
instance.
I think I have read here somewhere before that the .execute won't find
.find.text that exactly matches the find.range.
So in a new document with Test text Test text
The following code:
Sub ScratchMacro3()
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = "Test text"
.Wrap = wdFindStop
While .Execute
oRng.Text = "Test text"
Wend
End With
MsgBox oRn.Text
End Sub
Finds the first instances, the next .Execute collapses the range and
extends the range forward to the end of the document and finds the next
instance, at this point the oRng.Text and .Find.Text are identical and
.Execute terminates.
Here is another way of attempting to illustrate what I think happes.
You can't find the text of a document in the range of a document:
Sub ScratchMacro4()
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = ActiveDocument.Range.Text
.Execute
If .Found Then
MsgBox "Found"
Else
MsgBox "Not found"
End If
End With
If oRng.Text = ActiveDocument.Range.Text Then
MsgBox "Doesn't is seem odd that Word doesnt' find the" _
& " ActiveDocument.Range.Text in the ActiveDocument.Range?"
End If
End Sub
Tony Jollans - 12 Dec 2006 23:28 GMT
I have just posted (in word.vba.customization) where a collapse was
necessary.
Each Find operation (each execution of the .Execute) is a stand-alone Find
and follows the same set of rules: if the range exactly satisfies the Find
criteria it is presumed to have been the result of a previous Find for the
same thing and searching starts after the range (the range is effectively
automatically collapsed); otherwise the Range is searched and if that
results in a not found condition, further searching depends on the Wrap
value.
If, after a find, you mess with the range - change its size - or its
contents or formatting - you will affect how the next iteration works. If
you have Wrap=Continue you can end up with an infinite loop in cases where
you don't change every found instance.

Signature
Enjoy,
Tony
> Jay/Helmut,
>
[quoted text clipped - 101 lines]
> End If
> End Sub
Greg Maxey - 13 Dec 2006 13:21 GMT
Tony,
Concur with your explanation in the Customization group message. That
is why I said:
"For me a more common problem is the job won't complete without that
statement."
This is a good explanation of what happens with .Execute:
> Each Find operation (each execution of the .Execute) is a stand-alone Find
> and follows the same set of rules: if the range exactly satisfies the Find
[quoted text clipped - 3 lines]
> results in a not found condition, further searching depends on the Wrap
> value.
This might give anyone following this string a good example of how the
collapse statement ensures the code procedes when the range is reduced
and ensures it doesn't get in a continous loop if the range is expanded
in the .Execute portion of the code:
Sub Test1()
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = "<*>"
.MatchWildcards = True
While .Execute
MsgBox oRng.Text
oRng.MoveEnd wdCharacter, -1
oRng.MoveStart wdCharacter, 1
MsgBox oRng.Text
oRng.Collapse wdCollapseEnd
Wend
End With
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = "<*>"
.MatchWildcards = True
While .Execute
MsgBox oRng.Text
oRng.MoveEnd wdCharacter, 1
oRng.MoveStart wdCharacter, -1
oRng.Collapse wdCollapseEnd
MsgBox oRng.Text
Wend
End With
End Sub
> > Jay/Helmut,
> >
[quoted text clipped - 101 lines]
> > End If
> > End Sub
Jeff,
I helps to provide your code.
Try something like:
Sub Scratchmacro()
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = "Your text"
.Wrap = wdFindStop
While .Execute
oRng.Font.Color = wdColorBlue
Wend
End With
End Sub
> I am doing a search on a document and need to perform some actions when the
> search criteria is met. I am having a problem getting the loop to stop at
> the end of the document. It just keeps looping. I am very new to Word VBA
> and would appreciate any help.
>
> Jeff