If you’ve ever written a Word addin, at some point you’ve probably had to use the Find object. It’s quite powerful, allowing you to find (and replace) text based on wildcards, formatting, etc.
However, it can also be an exercise in frustration getting consistent results from Find, especially when “finding” in the same document across several versions of Word (in my case, Word 2000, XP, 2003, and 2007, surely we can ignore ’97 by now<g>).
The problem comes from at least two places that I know of.
The first is that to really execute the find everywhere, you need to execute it against the range objects of all the storyranges in the document, NOT just the main body.
Fortunately, that’s relatively easy to do:
For each Story in Document.StoryRanges 'Handle the Story here Next
However, that doesn’t quite get you there. This is because you won’t necessarily enumerate through all the ranges for all the headers and footers in the document if you just use the above loop.
To see the section headers and footers, you have to do something like:
For Each Section In Document.Sections For Each Header In Section.Headers 'Handle this Header range Next For Each Footer In Section.Footers 'Handle this Footer range Next Next
And finally, simply enumerating through the headers and footers, you may end up with multiple references to the same header/footer. Gah! How? There’s an unobtrusive little Word feature for headers and footers called “Link to Previous”. Here it is lurking in Word 2007.
When that’s set, a single header or footer might show up in several different sections, causing you to search the same place twice. Just filter those with the “LinkToPrevious” property set and you’re gold.
The bigger problem is that Word has a way of fouling its internal search state such that when your code executes its find, it simply doesn’t work.
This is a much nastier problem because it’s not consistent. Things will work fine at one point, then fail inexplicably later.
Fortunately, I happened to stumble across an article by MVP Bill Coan that addressed this issue directly. The article is about “Flushing the bad karma from Word’s search“, and how he came up with the solution is nothing short of bayou voodoo, but it’s exactly what I needed to get my search consistent across all Word versions.
Essentially, you perform a dummy search to clear out whatever internal state information Word is holding onto. This allows your real search to execute properly.
The dummy search is simply:
WordDocObject.Content.Find.Execute "^p", MatchWildcards:=False
Even better, it doesn’t appear to negatively impact performance of my search to any perceptible degree.
And finally, even though it looks like this article was written for Word 2000 (and maybe XP), I found that it’s still very much valid for the latest SP releases of 2000, XP, and Word 2003.
The good news is that Word 2007 doesn’t appear to be effected by the bug anymore, but using the dummy search doesn’t have any negative impact here either.