How do I write a loop statement to that will stop at the end of the doc?

Discussion in 'Word VBA Beginners' started by Jeff Mitteer, Dec 11, 2006.

  1. Jeff Mitteer

    Jeff Mitteer Guest

    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, Dec 11, 2006
    #1
    1. Advertisements

  2. Jeff Mitteer

    Jay Freedman Guest

    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.

    --
    Regards,
    Jay Freedman
    Microsoft Word MVP
    Email cannot be acknowledged; please post all follow-ups to the newsgroup so
    all may benefit.

    Jeff Mitteer wrote:
    > 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
     
    Jay Freedman, Dec 11, 2006
    #2
    1. Advertisements

  3. Jeff Mitteer

    Greg Maxey Guest

    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

    Jeff Mitteer wrote:
    > 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
     
    Greg Maxey, Dec 11, 2006
    #3
  4. Jeff Mitteer

    Jeff Mitteer Guest

    Re: How do I write a loop statement to that will stop at the endof the doc?

    Jay Freedman wrote:
    > 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.
    >

    Thanks. I think that will work.

    Jeff
     
    Jeff Mitteer, Dec 12, 2006
    #4
  5. Jeff Mitteer

    Greg Maxey Guest

    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 ;-)








    Jay Freedman wrote:
    > 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.
    >
    > --
    > Regards,
    > Jay Freedman
    > Microsoft Word MVP
    > Email cannot be acknowledged; please post all follow-ups to the newsgroup so
    > all may benefit.
    >
    > Jeff Mitteer wrote:
    > > 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
     
    Greg Maxey, Dec 12, 2006
    #5
  6. Jeff Mitteer

    Jay Freedman Guest

    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.

    --
    Regards,
    Jay Freedman
    Microsoft Word MVP
    Email cannot be acknowledged; please post all follow-ups to the newsgroup so
    all may benefit.

    Greg Maxey wrote:
    > 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 ;-)
    >
    >
    >
    >
    >
    >
    >
    >
    > Jay Freedman wrote:
    >> 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.
    >>
    >> --
    >> Regards,
    >> Jay Freedman
    >> Microsoft Word MVP
    >> Email cannot be acknowledged; please post all follow-ups to the
    >> newsgroup so all may benefit.
    >>
    >> Jeff Mitteer wrote:
    >>> 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
     
    Jay Freedman, Dec 12, 2006
    #6
  7. Jeff Mitteer

    Helmut Weber Guest

    Hi Jay,

    IMHO,
    formatting does no harm,
    however, replacing text seems to require
    additional measures to control the range.

    --
    Greetings from Bavaria, Germany

    Helmut Weber, MVP WordVBA

    Win XP, Office 2003
    "red.sys" & Chr$(64) & "t-online.de"
     
    Helmut Weber, Dec 12, 2006
    #7
  8. Jeff Mitteer

    Greg Maxey Guest

    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
     
    Greg Maxey, Dec 12, 2006
    #8
  9. Jeff Mitteer

    Tony Jollans Guest

    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.

    --
    Enjoy,
    Tony

    "Greg Maxey" <> wrote in message
    news:...
    > 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, Dec 12, 2006
    #9
  10. Jeff Mitteer

    Greg Maxey Guest

    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
    > 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.


    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



    > "Greg Maxey" <> wrote in message
    > news:...
    > > 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
    > >
     
    Greg Maxey, Dec 13, 2006
    #10
  11. Jeff Mitteer

    Jazz

    Joined:
    Mar 15, 2017
    Messages:
    1
    Likes Received:
    0
    Hi Jeff,
    I had the same need, more than once. Finally I found a simple way, from word.tips.net. Here it is:

    Selection.HomeKey Unit:=wdStory
    [set up for your search]
    Selection.Find.Execute
    While Selection.Find.Found
    [take some action]
    Selection.Find.Execute
    Wend

    The first line just goes to the beginning of the document. I left that out and went to the beginning manually before starting the macro, and it worked perfectly.

    Jazz
     
    Jazz, Mar 15, 2017
    #11
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.
Similar Threads
  1. Bob Benjamin

    How to delete rows in the With - End With loop

    Bob Benjamin, Nov 15, 2003, in forum: Word VBA Beginners
    Replies:
    1
    Views:
    105
    Doug Robbins - Word MVP
    Nov 15, 2003
  2. pjm

    How to loop until end of document?????

    pjm, Dec 19, 2003, in forum: Word VBA Beginners
    Replies:
    14
    Views:
    5,058
    Doug Robbins - Word MVP - DELETE UPPERCASE CHARACT
    Mar 1, 2004
  3. John Edward

    End of Doc Check

    John Edward, Apr 6, 2004, in forum: Word VBA Beginners
    Replies:
    3
    Views:
    90
    Doug Robbins - Word MVP
    Apr 8, 2004
  4. Chris Moorhead
    Replies:
    7
    Views:
    316
    Chris Moorhead
    Nov 30, 2005
  5. nycdon
    Replies:
    3
    Views:
    121
    Doug Robbins - Word MVP
    Nov 4, 2007
  6. Replies:
    2
    Views:
    222
  7. Jim Houston

    Loop through a document from beginning to end

    Jim Houston, May 2, 2008, in forum: Word VBA Beginners
    Replies:
    3
    Views:
    167
    fumei via OfficeKB.com
    May 2, 2008
  8. AG

    Stop a Find.Execute loop

    AG, Apr 28, 2011, in forum: Word VBA Beginners
    Replies:
    0
    Views:
    352
Loading...