Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VBA Word: I would like to find a phrase, select the words before it, and italicise the text

Tags:

ms-word

vba

I'm having trouble with VBA commands to find a certain phrase, then select the 1 or 2 words before it, and then italicize the entire thing.

I'm able to use the Selection.Find, Font.Italicise, and wdExtend commands independently of each other, but when I combine them to perform this task, the macro just crashes. Any help?

Selection.Find.ClearFormatting
 With Selection.Find
     .Text = "Michael"
     .Replacement.Text = "Michael"
     .Forward = True
     .Wrap = wdFindStop
     Do While .Execute() = True
         Selection.TypeParagraph
         Selection.MoveLeft Unit:=wdWord, Count:=2, Extend:=wdExtend
         Selection.Find.Replacement.Font.Italic = True
         Selection.Font.Bold = True
         Selection.Collapse Direction:=wdCollapseEnd
     Loop
 End With
like image 837
Kevin Avatar asked Apr 07 '17 18:04

Kevin


1 Answers

The following code will do what you want. However, I wrote it in such a way as I think will enable you best to understand it.

Private Sub SelFind()
    ' 08 Apr 2017

    Dim Rng As Range
    Dim Fnd As Boolean

    Set Rng = Selection.Range
    With Rng.Find
        .ClearFormatting
        .Execute FindText:="Michael", Forward:=True, _
                 Format:=False, Wrap:=wdFindStop
        Fnd = .Found
    End With

    If Fnd = True Then
        With Rng
            .MoveStart wdWord, -2
            With .Font
                .Italic = True
                .Bold = True
            End With
        End With
    End If
End Sub

Start with imagining all the characters in your document strung into a single line, interspersed with formatting codes which are also treated like characters. This long string of characters is called a range, in code, ActiveDocument.Range.

You can select any part of the document's entire range. That would be the Selection.Range which, like all ranges, has a Start (the first byte) and an End (the last byte. Start and End are properties of the Range represented by numbers, counting from the first byte. My code creates a new Range object which is called Rng. The Selection.Range is assigned to that new object. Rng and Selection.Range are identical at this point, but as you manipulate the Rng object, the Selection.Range will not change.

The code now looks for "Michael" in the Rng object. Your syntax for setting up the search is perfect. I used different syntax because I find it easier to grasp. The .Found property returns True if the search was successful. In that case the search range is changed to include only the found sub-range. Had the search been conducted in the Selection.Range you would see "Michael" highlighted on the screen. But since the search was conducted in memory (on the Rng object) the Selection.Range remains unchanged while the Rng object now contains only the word "Michael".

So, going back to the ActiveDocument.Range, of which Rng is a part, we now move the Start property two words to the left. A positive number would move it 2 words to the right. There is no need for Extend because the command is perfectly clear: "Move Start", meaning the End remains where it is.

Now the Rng object starts 2 word before "Michael" and ends with the word "Michael". You can copy this range or delete it, or modify it as you wish. Bear in mind that your screen still shows the original Selection.Range. MS Word will not allow you to assign Set Selection.Range = Rng, but there is an even easier way to realign the display with what the code has done. By adding the line .Select after modifying the Font (before the outer End With), the modified Rng would become the Selection.

like image 66
Variatus Avatar answered Oct 21 '22 08:10

Variatus