Search code examples
vbams-wordstyles

Running macro to specific style


Below code is trying to convert words in lowercase in to uppercase. However I only need to run it only in a specific word style ("Normal"). I tried to set doc to ActiveDocument.Styles("Normal") but i keep on getting error. Any help would be most helpful. Thank you in advance.

Option Explicit

   Public Sub TitleCaseDocument()
   Dim doc As Document: Set doc = ActiveDocument.Styles("Normal")
   Dim wrd As Range

   For Each wrd In doc.Words
       If wrd.Text <> UCase$(wrd.Text) Then wrd.Case = wdTitleWord
Next
End Sub

Solution

  • The solution provided by @eaazel falls into the default member trap.

    The code

    wrd.Style
    

    is in reality using the default member of the style object, which is 'NameLocal'. Thus the code implied by the code above is in reality

    wrd.Style.NameLocal
    

    Normally this would not be a problem, however, the level of granularity that is being used to extract the style object means that, on occasion, words with no style will be encountered (e.g. a ToC field). In such a case the style object returned is nothing and this generates a surprising error because you cannot call the NameLocal method on an an object that is nothing.

    Therefore a more correct approach is to use a word unit that is guaranteed to have a style object (e.g. paragraphs) and to test for the style on this object before testing each word.

    Option Explicit
    
    Public Sub TitleCaseDocument()
        Dim myDoc As Document: Set myDoc = ActiveDocument
    
        Dim myPara As Range
        For Each myPara In myDoc.StoryRanges.Item(wdMainTextStory).Paragraphs
    
            If myPara.Style.NameLocal = "Normal" Then
    
                TitleParagraph myPara
    
           End If
    
        Next
    
    End Sub
    
    Public Sub TitleParagraph(ByVal ipRange As Word.Range)
    
        Dim myText As Range
        For Each myText In ipRange.Words
    
            If Not UCase$(myText.Text) = myText.Text Then
    
                myText.Words.Item(1).Case = wdTitleWord
    
            End If
    
        Next
    
    End Sub
    

    Update 2020-Apr-16 Revised code below which has been proved to work on a Word document.

    Option Explicit

    Public Sub TitleCaseDocument()
        Dim myDoc As Document: Set myDoc = ActiveDocument
    
        Dim myPara As Word.Paragraph
        For Each myPara In myDoc.StoryRanges.Item(wdMainTextStory).Paragraphs
    
            If myPara.Style.NameLocal = "Normal" Then
    
                TitleParagraph myPara
    
           End If
    
        Next
    
    End Sub
    
    Public Sub TitleParagraph(ByVal ipPara As Word.Paragraph)
    
        Dim myText As Range
        For Each myText In ipPara.Range.Words
    
            If Not UCase$(myText.Text) = myText.Text Then
    
                myText.Words.Item(1).Case = wdTitleWord
    
            End If
    
        Next
    
    End Sub