MS Word VBA Find and Loop (NOT Replace)

2019-08-02 14:42发布

问题:

Sorry for the fundamental question but I am a LONGtime Access VBA developer who is getting my butt kicked by Word.

I am building a solution for someone who uses a Legal Case Management System with a specific numbering scheme (aaa-aaa-##-##-###). I need to search a document for hyphens and then grab the whole paragraph where a hyphen is found. I then need to send the text from that paragraph to a separate function which parses out the file number from the paragraph (this function already works).

If that function is successful, it returns the File Number, otherwise it returns "NOT FOUND". So, I need to:

  1. Find all hyphens

  2. Capture the paragraph with a hyphen

  3. Pass that text to the function

  4. GO TO THE NEXT HYPHEN IF function returns "NOT FOUND"

I have tried dozens of options without success. I typically get stuck in an infinite loop (and do not seem to move forward) or I get to the end of the process with a false failure.

I do not know how to move to the NEXT occurrence of a hyphen and repeat the process. I also do not know how to run the process to the end of the document or stop at the end (without starting all over - because the hyphens REMAIN since this is NOT a replace process).

I have tried so many different versions, but I included one below.

Thanks for any guidance. I do appreciate it.

DGP


Public Sub TestFind77()  '
    Selection.HomeKey Unit:=wdStory

    With Selection.Find
        .ClearFormatting
        .Text = "-"
        .Execute Forward:=True

        Do While .Found = True
            .Parent.Expand Unit:=wdParagraph

            Dim strWTF As String
            strWTF = .Parent
            'MsgBox strWTF

            strResult = fnGetFileNumberFromString(strWTF) ' This works
                If strResult <> "NOT FOUND" Then
                GoTo success

            End If
            .Execute Forward:=True

        Loop

    End With

  success:
    MsgBox strResult

End Sub

回答1:

I understand... Good start and you're missing only tiny pieces.

One thing you need is Word's Range object. Best to use that with Find - unlike Selection you can work with multiple Ranges in your code.

Sometimes, when working with Find it's necessary to refer back to the original Range (the entire document, in your case). That doesn't appear to be the case, here, but I've built it in, anyway, on general principle - so you have it if it turns out you need it.

I've found it more reliable to save the result of Find.Execute in a boolean variable, rather than relying on .Found, so I've put that in, as well.

You can pick up the paragraph in which the Range is located using Range.Paragraphs(1). I tried to stick to what you have, but if you want to tighten up your code even more, you could do this as long as you don't need the paragraph for anything else:

strWTF = rngSearch.Paragraphs(1).Range.Text

Good luck!

Public Sub TestFind77()
    Dim rngDoc as Word.Range
    Dim rngSearch as Word.Range
    Dim bFound as boolean
    Dim para as Word.Paragraph

    Set rngDoc = ActiveDocument.Range
    Set rngSearch = rngDoc.Duplicate

    With rngSearch.Find
        .ClearFormatting
        .Text = "-"
        bFound = .Execute(Forward:=True)

        Do While bFound = True
            Set para = rngSearch.Paragraphs(1)

            Dim strWTF As String
            strWTF = para.Range.Text '???.Parent
            'MsgBox strWTF

            strResult = fnGetFileNumberFromString(strWTF) ' This works
                If strResult <> "NOT FOUND" Then
                GoTo success

            End If
            rngSearch.Collapse wdCollapseEnd 'search from after the found to the end of the doc
            bFound = .Execute(Forward:=True)
        Loop   
    End With

 success:
    MsgBox strResult

End Sub


回答2:

Thanks Cindy,

I am still not sure that I understand the Word Object Model well enough to understand why...but your answer got it to work.

I did incorporate your suggestion re strWTF = rngSearch.Paragraphs(1).Range.Text

Here is the final code, including that input:

Public Sub TestFind99()
    Dim rngDoc As Word.Range
    Dim rngSearch As Word.Range
    Dim bFound As Boolean
    Dim strWTF As String

    Set rngDoc = ActiveDocument.Range
    Set rngSearch = rngDoc.Duplicate

    With rngSearch.Find
        .ClearFormatting
        .Text = "-"
        bFound = .Execute(Forward:=True)


        Do While bFound = True

            strWTF = rngSearch.Paragraphs(1).Range.Text
            strResult = fnGetFileNumberFromString(strWTF) ' This works
                If strResult <> "NOT FOUND" Then
                GoTo success

            End If
            rngSearch.Collapse wdCollapseEnd 'search from after the found to the end of the doc
            bFound = .Execute(Forward:=True)

        Loop
    End With

success:
    MsgBox strResult

End Sub