Leo
Leo

Reputation: 3116

How to identify which shapes have text when HasTextFrame is unreliable?

I'm trying to change text in a SmartArt. Specifically this type: List with pictures

I can replicate the Minimum Working Example below on two machines.

This code enters the .HasText = msoTrue branch even though the debugger says that .HasText = 0. This causes shi.TextFrame.TextRange.Text to fail.

Sub enumerate_subshapes(shi As Shape, Optional depth As Integer = 0)
    'If True Then
    If shi.HasTextFrame Then
        If shi.TextFrame.HasText Then
            Debug.Print depth & " YES: ", shi.Type, shi.HasTextFrame, shi.TextFrame.HasText, shi.TextFrame.TextRange.Text
        Else
            Debug.Print depth & " NO: ", shi.Type, shi.HasTextFrame, shi.TextFrame.HasText
        End If
    End If
    Select Case shi.Type
        Case msoSmartArt
            For i = 1 To shi.GroupItems.Count
                enumerate_subshapes shi.GroupItems.Item(i), depth + 1
            Next i
    End Select

End Sub

Sub vba_bug_mwe()
    Dim shi As Shape
    For Each shi In ActivePresentation.Slides(1).Shapes
        Debug.Print "############### " & shi.Name
        enumerate_subshapes shi
    Next
End Sub

If you uncomment the If true then line and comment the If shi.HasTextFrame Then line, then you get the expected result, i.e., the inner test works correctly.

It looks like a bug to me, TBH, in which case it doesn't really belong here. But maybe there is some VBA subtlety I'm missing.

Upvotes: 0

Views: 530

Answers (1)

John Korchok
John Korchok

Reputation: 4913

A piece of SmartArt is a nested group of shapes. You need to drill down to individual subshapes to get any useful information. You haven't stated your overall goal with this, but here's how to get the text from each node:

Sub GetSmartArtNodeText()
    Dim oShape As Shape
    Dim oNode As SmartArtNode
    For Each oShape In ActivePresentation.Slides(1).Shapes
        If oShape.HasSmartArt = True Then
            For Each oNode In oShape.SmartArt.Nodes
                MsgBox oNode.TextFrame2.TextRange.Text
            Next oNode
        End If
    Next oShape
End Sub

Upvotes: 1

Related Questions