How Can I Search For (and Reformat) Highlighted Text in a Word Document?

How Can I Search For (and Reformat) Highlighted Text in a Word Document?

  • Comments 3
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I find text in a Word document that has been highlighted in a particular color (say, turquoise), and then both remove the highlight and change the font color of that text to something else (say, blue)? I’d be extremely chuffed if you can solve this one!

-- KB

SpacerHey, Scripting Guy! AnswerScript Center

Hey, KB! Blimey! You know, when we first saw your message we thought, “KB’s off her trolley!” But we decided to give it welly, and when we realized that things were tickety-boo we were absolutely gob-smacked; in fact, we said to ourselves, “Guess the lass wasn’t so barmy after all; this should make her bite her arm off!” And then after all that everything ended up luvvly-jubbly. Brill!

Note. No, this is not all codswallop. If you don’t believe us, check out this Web site for more information.

Hmmm … You know, once you start talking like that, it’s hard to stop (blooming hard). So maybe we should just belt up and show you the script (which, as it turns out, was a doddle after all):

Const wdTurquoise = 3
Const wdNoHighlight = 0
Const wdBlue = 2

Set objWord = CreateObject("Word.Application")
objWord.Visible = True

Set objDoc = objWord.Documents.Open("C:\Scripts\Test.doc")
Set objRange = objDoc.Range

objRange.Find.Highlight = True
objRange.Find.Forward = True

Do while objRange.Find.Execute
    If objRange.HighlightColorIndex = wdTurquoise Then
        objRange.HighlightColorIndex = wdNoHighlight
        objRange.Font.ColorIndex = wdBlue
    End If
    intPosition = objRange.End
    objRange.Start = intPosition
Loop

Because we have no desire to drop a clanger, we’ll set aside the British slang for a moment and try to explain how the script works. As you can see, we start out by defining three constants, one that we’ll use to specify the highlight color we’re searching for (wdTurquoise), and two to specify the new highlight and font colors for any text we find (wdNoHighlight and wdBlue, respectively):

Const wdTurquoise = 3
Const wdNoHighlight = 0
Const wdBlue = 2

After that we create an instance of the Word.Application object and set the Visible property to True; that simply gives us a running instance of Microsoft Word that we can see on screen. With Word up and running we use the Open method to open the document C:\Scripts\Test.doc, then use this line of code to create an instance of the Word Range object (which, by default, will be positioned at the beginning of the document:

Set objRange = objDoc.Range

Now we’re ready for action. We won’t discuss finding and replacing text in any detail today; that’s because we do a much more thorough job of that in one of our Office Space columns. However, our next step is to configure two properties of the Find object: we want to find words that have been highlighted (in any color), and we want our search to start at the beginning of the range and then move forward throughout the document. That’s what these two lines of code are for:

objRange.Find.Highlight = True
objRange.Find.Forward = True

Admittedly, the rest is a bit of a bodge; that’s because, while it’s easy enough to search for text that has some kind of highlight, we couldn’t figure out a way to search for text that had a specific color of highlight. Rather than faff around genning up on a way to search for a specific color highlight we decided to use this spot of code instead:

Do While objRange.Find.Execute
    If objRange.HighlightColorIndex = wdTurquoise Then
        objRange.HighlightColorIndex = wdNoHighlight
        objRange.Font.ColorIndex = wdBlue
    End If
    intPosition = objRange.End
    objRange.Start = intPosition
Loop

What we’re doing here is setting up a Do While loop that runs as long as the search command (Find.Execute) runs. When we call the Execute method, the script will start wherever the Range object is positioned and then search for the first item that meets the search criteria. (In this case, of course, our only criterion is that the text be highlighted.) If no items are found then the search automatically ends, which also means that we’ll automatically exit the Do While loop.

That’s how we keep the script from simply searching the document over and over and over again.

If we do find a highlighted item we check to see if the value of the HighlightColorIndex property is turquoise (incidentally, you can find information about all these properties and their allowed values in the Microsoft Word VBA Language Reference):

If objRange.HighlightColorIndex = wdTurquoise Then

If the highlight color is turquoise we execute these two lines of code:

objRange.HighlightColorIndex = wdNoHighlight
objRange.Font.ColorIndex = wdBlue

With the first line, we remove the highlight for the found text; with the second, we change the font color of that text to blue. To tell you the truth, this was a bit jammy, but it ended up working just fine.

And to think that some of you have said that the Scripting Guys are gormless!

Oh: and if text is highlighted but the color is something other than turquoise then we simply leave well enough alone. Quite.

Of course, this only gets us as far as the first highlighted item in the text. To search for any subsequent items that meet our criteria we need to use these two lines of code:

intPosition = objRange.End
objRange.Start = intPosition

Why? Well, until we call these two lines of code our range will consist solely of the text that we just found. That’s not what we want: after all, if we call the Execute method again we’ll end up searching just that little block of text. And because that text is no longer highlighted, the search - and our script - will simply end.

To avoid that, we assign the value of the End property (the last character in the range) to a variable named intPosition; we then set the Start property of the range to intPosition.

So why do we do that? Well, suppose we found a highlight that covers characters 5 through 10; that means our range also covers characters 5 through 10. If we set intPosition to 10 (the last character in the range), and then assign that value to the range’s Start property, that moves the beginning of our range to character position 10. And because we didn’t specify an End value, the range will automatically encompass the remainder of the document. In other words, now when we call Execute we’ll start searching at the point where the first search left off, and we’ll continue searching until either we find a new item or we reach the end of the document.

Which is exactly what we want to happen.

Feeling knackered? We don’t blame you. But even if you don’t fully understand how it works, it’s still a good flutter, especially for a script this smashing.

Come on: would the Scripting Guys tell you porkies?

At any rate, Bob’s your uncle, KB. Cheerio

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Never mind previous comment. If the HighlightColorIndex value is 9999999 (mixed), you can loop through each character to get the HighlightColorIndex value, and act based on that.

    If objRange.HighlightColorIndex = 9999999 Then

        For n = 1 To objRange.Characters.Count

             If objRange.Characters.Item(n).HighlightColorIndex = wdTurquoise Then

                  objRange.HighlightColorIndex = wdNoHighlight

                  objRange.Font.ColorIndex = wdBlue

             End If

        Next n

    Else...

  • thanks. very useful for a beginner like me...

  • thanks