0
votes

I'm very new to VBA and tying to write a code that would find and replace words in a word document. Here goes the code...

Sub callback(control As IRibbonControl)
stringReplaced = stringReplaced + "string to be searched"
For Each myStoryRange In ActiveDocument.StoryRanges
    With myStoryRange.Find
        ActiveDocument.TrackRevisions = True
        .Text = "wATer"
        .Replacement.Text = "Water"
        .Wrap = wdFindContinue
        .MatchWholeWord = True
        .ClearFormatting
        .Replacement.ClearFormatting
        .Replacement.Highlight = True
        .Execute Replace:=wdReplaceAll
    End With
ActiveDocument.TrackRevisions = False
Next myStoryRange
End Sub

It works fine, however, it also replaces the word "Water" even if it appears rightly in the document. I want the code to ignore the right instances and only concentrate on the incorrect instances. Not sure if the code needs an "If" clause.

In other words, if the document already has a instance of what's specified in "Replacement.Text", the code should ignore it. Please help

2

2 Answers

0
votes

I would probably add .MatchCase = True to the With block and see if it works. It should then only change wATer and not Water.

Code:

Sub callback(control As IRibbonControl)
stringReplaced = stringReplaced + "string to be searched"
For Each myStoryRange In ActiveDocument.StoryRanges
    With myStoryRange.Find
        ActiveDocument.TrackRevisions = True
        .Text = "wATer"
        .Replacement.Text = "Water"
        .Wrap = wdFindContinue
        .MatchWholeWord = True
        .MatchCase = True
        .ClearFormatting
        .Replacement.ClearFormatting
        .Replacement.Highlight = True
        .Execute Replace:=wdReplaceAll
    End With
ActiveDocument.TrackRevisions = False
Next myStoryRange
End Sub
0
votes

If you really need to skip matching on Water (but want to catch all other case possibilities), I'd say you have two reasonable options.

1) Run multiple Replace All searches using wildcards to limit the case possibilities. For instance, the first wildcard search would be "w[Aa][Tt][Ee][Rr]" which would find any version of water that begins with a lowercase w. Then you could do "WA[Tt][Ee][Rr]" and so on. This could get laborious if you have a lot of words, but it would avoid the issue. You could also automate generating the wildcard searches, but that's only worthwhile if you're dealing with variable search text or a large number of words.

2) Don't replace all; rather, loop through all the hits and decide if you want to make the replacement. Something like this:

Sub callback(control As IRibbonControl)
stringReplaced = stringReplaced + "string to be searched"
For Each myStoryRange In ActiveDocument.StoryRanges
    With myStoryRange.Find
        ActiveDocument.TrackRevisions = True
        .Text = "wATer"
        .Replacement.Text = "Water"
        .Wrap = wdFindContinue
        .MatchWholeWord = True
        .ClearFormatting
        .Replacement.ClearFormatting
        .Replacement.Highlight = True
        While .Execute .Forward = True and .Wrap = wdFindStop
            if myStoryRange.Text <> "Water" then myStoryRange.Text = "Water"
            myStoryRange.Collapse wdCollapseEnd
        Wend
    End With
ActiveDocument.TrackRevisions = False
Next myStoryRange
End Sub

Looping through searches can be tricky (see Greg Maxey's exhaustive review of the process here: http://gregmaxey.mvps.org/word_tip_pages/words_fickle_vba_find_property.html

But with a little testing it could be a workable solution. Note of course that this will be slower than ReplaceAll.

(Please test that code before running it on anything real. I don't have Word right now and am working a tiny bit from memory regarding setting up the loop.)