How to find out, using VBA, how many replacements Word made during a Find & Replace All
Or: How to find out how many occurrences there are of a particular word in a document
Article contributed by Bart Verbeek and Dave Rado
When you click Replace All in the Find & Replace dialog, Word shows the number of replacements on the Status bar after the operation is completed. To the regret of many it is impossible to query this number in VBA. But that does not mean you cannot determine the number of replacements if you want to. The following VBA code sample does just that. (If you are not familiar with using functions with arguments, see How to cut out repetition and write much less code, by using subroutines and functions that take arguments).
Function CountNoOfReplaces(StrFind
As String, StrReplace As
String)
Dim NumCharsBefore As Long,
NumCharsAfter As Long, LengthsAreEqual
As Boolean
Application.ScreenUpdating = False
'Check whether the length of the Find
and Replace strings are the same; _
if they are, prefix the replace string with a hash (#)
If Len(StrFind) =
Len(StrReplace) Then
LengthsAreEqual =
True
StrReplace = "#" & StrReplace
End If
'Get the number of chars in the doc
BEFORE doing Find & Replace
NumCharsBefore = ActiveDocument.Characters.Count
'Do the Find and Replace
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = StrFind
.Replacement.Text = StrReplace
.Forward =
True
.Wrap = wdFindContinue
.Format =
False
.MatchCase =
False
.MatchWholeWord =
True
.MatchWildcards =
False
.MatchSoundsLike =
False
.MatchAllWordForms =
False
.Execute Replace:=wdReplaceAll
End With
'Get the number of chars AFTER doing
Find & Replace
NumCharsAfter = ActiveDocument.Characters.Count
'Calculate of the number of replacements,
'and put the result into the function name variable
CountNoOfReplaces = (NumCharsBefore - NumCharsAfter) / _
(Len(StrFind)
- Len(StrReplace))
'If the lengths of the find & replace
strings were equal at the start, _
do another replace to strip out the #
If LengthsAreEqual
Then
StrFind = StrReplace
'Strip off the
hash
StrReplace = Mid$(StrReplace, 2)
With Selection.Find
.Text =
StrFind
.Replacement.Text = StrReplace
.Execute
Replace:=wdReplaceAll
End With
End If
Application.ScreenUpdating = True
'Free up memory
ActiveDocument.UndoClear
End Function
You could call it like this:
Sub Test()
MsgBox "Number of replacements: " & CountNoOfReplaces _
(StrFind:="Big", StrReplace:="Bigger"), vbInformation
End Sub
This will work regardless of which string is the longest, and even if the strings do not differ in length.
You could take the same principle further, to count the number of occurrences of a particular word in a document:
Function CountWord(WordToCount As
String)
Dim NumCharsBefore As Long,
NumCharsAfter As Long
Application.ScreenUpdating =
False
'Get the number of chars in the doc
BEFORE doing Find & Replace
NumCharsBefore = ActiveDocument.Characters.Count
'Do the Find and Replace
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = WordToCount
.Replacement.Text = "#" &
WordToCount
.Forward =
True
.Wrap = wdFindContinue
.Format =
False
.MatchCase =
False
.MatchWholeWord =
True
.MatchWildcards =
False
.MatchSoundsLike =
False
.MatchAllWordForms =
False
.Execute Replace:=wdReplaceAll
End With
'Get the number of chars AFTER doing
Find & Replace
NumCharsAfter = ActiveDocument.Characters.Count
'Calculate of the number of replacements,
'and put the result into the function name variable
CountWord = NumCharsAfter - NumCharsBefore
'Undo the replace
ActiveDocument.Undo
'Free up memory
ActiveDocument.UndoClear
Application.ScreenUpdating =
False
End Function
You could call it like this:
Sub Test()
Dim Response As String
Response = InputBox("Type a word you want to count", _
"Get number
of occurrences of this word")
MsgBox "There are " & CountWord(Response) & _
"
occurrences of the word '" & Response & _
"' in
this document", vbInformation
End Sub
Note: although it is possible to achieve the same ends by using a counter while you do multiple Finds (or multiple Find & Replaces) one at a time, until nothing more is found, that method is much slower than doing a ReplaceAll as illustrated above.