How to prevent the built-in BrowseNext and RepeatFind commands from creating bad karma for wildcard searches
Article contributed by Claudio Faria, Klaus Linke, Dave Rado and Bill Coan
The following bug is easy to reproduce in Word versions 97 through 2002:
1. |
Using Edit + Find, perform a Find operation of any kind. |
2. |
Use Shift+F4 or Ctrl+PgDn or the Browse button to repeat the last find operation. Continue until you reach the end of the document, but click No when asked if you want to continue at the start of the document. |
3. |
Do a wildcard search of any kind from VBA. The search will fail. |
Workaround 1: Intercepting the RepeatFind, BrowseNext and BrowsePrev commands
Put the following code into an add-in (or of it's only for your own personal use, you could put it into Normal.dot, if you prefer).
It automatically intercepts the built-in RepeatFind (Shift+F4), BrowseNext (Ctrl+PgDn) and BrowsePrev (Ctrl+PgUp) commands, and prevents the bug from ever rearing its ugly head.
Sub BrowseNext()
Select Case Application.Browser.Target
Case wdBrowseFind
With
Selection.Find
.Forward =
True
.Execute
Wrap:=wdFindAsk
End With
Case Else
Application.Browser.Next
End Select
End Sub
Sub BrowsePrev()
Select Case Application.Browser.Target
Case wdBrowseFind
With
Selection.Find
.Forward =
False
.Execute
Wrap:=wdFindAsk
End With
Case Else
Application.Browser.Previous
End Select
End Sub
Sub RepeatFind()
Select Case Application.Browser.Target
Case wdBrowseFind
Selection.Find.Execute
Wrap:=wdFindAsk
Case Else
WordBasic.ToolsMacro
Name:="RepeatFind", Run:=1, Show:=2
End Select
End Sub
In Word 2000+, if the browse mode is set to Find, the BrowseNext and BrowsePrev commands themselves invoke the RepeatFind command; so strictly speaking, in those versions of Word, it is only necessary to intercept RepeatFind. But if you want compatibility with Word 97, you need to intercept all three commands, as shown above.
See also:
Flush bad karma from Word's find facility after an
unsuccessful wildcard search
Workaround 2: Executing the Find & Replace dialog to clear the bug
The following workaround is included mainly for the sake of completeness (and for those who, for whatever reason, don't want to intercept Word commands). Workaround 1 is far more elegant.
Sub Test()
Application.ScreenUpdating = False
'Call a routine that removes any previous settings from the find dialog
Call ClearFindAndReplaceParameters
'Now call the fix
Call FixWildcardBug
'Call it a second time just in case (because the SendKeys statement is notoriously flaky)
Call FixWildcardBug
'Now it's safe to do your wildcard search, e.g.:
With Selection.Find
.Text = "(" & ChrW( 8220 ) & ")(*)(" & ChrW( 8221 ) & ")"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
.Execute
End With
Call ClearFindAndReplaceParameters
Application.ScreenUpdating = True
End Sub
Sub FixWildcardBug()
With Selection.Find
.Execute MatchWildcards:= True , FindText:= "?"
Selection.Collapse Direction:=wdCollapseStart
If Not .Found Then
'Call and execute the Replace dialog - not using the wdDialog constant, _
' which is buggy, but by executing the command button instead
CommandBars.FindControl(ID:= 313 ).Execute
SendKeys String:= "{ENTER}" , Wait:= True
SendKeys String:= "{ESC}" , Wait:= True
End If
Selection.Collapse Direction:=wdCollapseStart
.MatchWildcards = False
.Text = ""
End With
End Sub
Sub ClearFindAndReplaceParameters()
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
End Sub
Notes regarding Workaround 2
|
Unfortunately, this fix requires you to display the Find and Replace dialog momentarily; and there is no way around this. It only flashes up for an instant and is gone, but Workaround 1 doesn't suffer from this drawback, and also has the major adavantage that you don't need to run a macro every time you do a wildcard Find & Replace!
|
||||
|
To get the ID of any CommandBar control, you can use code such as the following: MsgBox CommandBars("Menu Bar"). Controls("&Edit").Controls("R&eplace...").ID Executing a CommandBar control using the FindControl method: CommandBars.FindControl(ID:=313).Execute ... has two advantages over referring to it by name as in: CommandBars("Menu Bar").Controls("&Edit").Controls("R&eplace...").Execute
|
||||
|
Note for advanced users: Unfortunately, you cannot run the FixWildcardBug macro using the Application.Run method. If you do, the SendKeys statement doesn't work properly, and the Edit + Replace dialog remains open until the user cancels it. So if you want to store the FixWildcardBug macro in an add-in and call it from a different project, you have to set a reference to the add-in in your other project and call your macro, rather than using Application.Run. Similarly, if you have an add-in containing another procedure that, in turn, calls the FixWildcardBug macro, then you can't run that other procedure from a different project using Application.Run either; instead, you have to set a reference to the add-in and call the other procedure.. |
||||
|
Apart from the problem with Application.Run, in English versions of Word this fix works reliably in all situations (as far as we can tell from extensive tests); but apparently, in some other language versions of Word it may not work reliably if you assign your macro to Alt+Ctrl+Anything. So if using non-English versions of Word and if assigning it to a keyboard shortcut, avoid assigning it to Alt+Ctrl. Or just use Method 1! |
See also:
Flush bad karma from Word's find facility after an unsuccessful wildcard search