在活动演示文稿中获取*所有*形状(包括嵌套组)

Get *all* shapes (including nested groups) in active presentation

我的问题来自需要将所有文本字体更改为特定字体 A。我知道 PowerPoint 中有一个 "Change font..." 选项,但它迫使我选择 "from font" 和一个"to font"。在我的例子中,有几种不同的字体应该更改为字体 "X"。因此我写了下面的 VBA 宏。

Private Sub Set_Font_Of_All_TextFrames(oShp As Shape, font As String)
' Go through all shapes on all slides. This is a recurisve function. First call needs to pass "Nothing" to oShp.
' Any font in every textframe that is not "font" will be set to "font".
' The recursion is necessary in order to go through groups.
' BUG/TODO: Text in Master is not included so far!

    Dim sld As Slide
    Dim shp As Shape
    Dim i As Integer

    If oShp Is Nothing Then ' first subroutine call
        For Each sld In ActivePresentation.Slides
            For Each shp In sld.Shapes
                If shp.Type = msoGroup Then
                    Set_Font_Of_All_TextFrames shp, font ' recursive call in case of group
                Else
                    Set_Font shp, font ' else change font
                End If
            Next shp
        Next sld
    ' in case of recursive calls:
    ElseIf oShp.Type = msoGroup Then
        For i = 1 To oShp.GroupItems.Count()
            Set shp = oShp.GroupItems.Item(i)
            Set_Font_Of_All_TextFrames shp, font ' another recursive call in case of group; will repeat this branch in case of subgroup
        Next
    Else
        Set shp = oShp
        Set_Font shp, font   ' else change font
    End If
End Sub

'Set_Font(shp as Shape, font as String)'子程序只是为了避免冗余。它只是检查给定的 shp 是否包含 font 以外的任何其他字体的文本并更改它。在某个地方, Set_Font_Of_All_TextFrames Nothing "X" 被调用。它按预期工作,但出现以下问题:

1) 除了更改字体之外,我如何才能使此功能可用于其他操作?我真的必须复制粘贴所有这些吗?

2) 我能否像在我的函数中那样使用一个函数来遍历所有形状和组,而不是调用 set_font 子例程,而是填充一个包含对它能找到的所有形状的引用的列表?我可以将此列表传递给例如set_font 子程序(以及任何其他应该对所有形状执行操作的子程序)?

3) 为什么母版上的形状被排除在我的功能之外?

感谢评论,我发现这或多或少是要走的路。我 post 这里我 "ulitity function" 生成所有形状的集合(包括任意嵌套子组中的所有形状),可以在任何其他函数或子例程中使用和迭代。

贯穿当前演示文稿中所有幻灯片的简单版本(它还清楚地显示了该功能的运作方式):

Function Get_All_Shapes(oShp As Shape, oColl As Collection)
' Go through all shapes on all slides. This is a recursive function. First call needs to pass "Nothing" to oShp and oColl.
' The collection oColl will be populated with all shapes (including all shapes in all groups) in the presentation.
' The return parameter will be the gradually populated collection.
' The recursion is necessary in order to go through groups.

    Dim sld As Slide
    Dim shp As Shape
    Dim i As Integer

    If oShp Is Nothing And oColl Is Nothing Then ' first function call
        Set oColl = New Collection
        For Each sld In ActivePresentation.Slides
            For Each shp In sld.Shapes
                If shp.Type = msoGroup Then
                    Set oColl = Get_All_Shapes(shp, oColl)  ' recursive call in case of group
                Else
                    oColl.Add shp ' else add shape to collection
                End If
            Next shp
        Next sld
    ' in case of recursive calls:
    ElseIf oShp.Type = msoGroup Then
        For i = 1 To oShp.GroupItems.Count()
            Set shp = oShp.GroupItems.Item(i)
            Set oColl = Get_All_Shapes(shp, oColl) ' another recursive call in case of group; will repeat this branch in case of subgroup
        Next
    Else
        oColl.Add oShp ' else add shape to collection
    End If
    Set Get_All_Shapes = oColl ' set populated collection as function return parameter
End Function

这是一个更精致的版本,您可以选择是否仅使用选定的形状(和嵌套的子组)填充集合,以及是否应将带有自定义布局的母版幻灯片包含在集合中:

Function Get_All_Shapes_WIP(oShp As Shape, oColl As Collection, Optional onlySelected As Boolean = False, Optional includeMaster As Boolean = False)
' Go through all shapes on all slides. This is a recursive function. First call needs to pass "Nothing" to oShp and oColl.
' The collection oColl will be populated with all shapes (including all shapes in all groups) in the presentation.
' The return parameter will be the gradually populated collection.
' The recursion is necessary in order to go through groups.
' If onlySelected is True, only the selected shapes will be added to the collection.
' If includeMaster is True, shapes on the master slide and all custom layouts will be added to the collection. This behavior is not affected by the value of onlySelected.

    Dim sld As Slide
    Dim shp As Shape
    Dim i As Integer

    ' first function call (main loops)
    If oShp Is Nothing And oColl Is Nothing Then
        Set oColl = New Collection

        ' presentation loops
        If onlySelected = False Then ' all shapes on all slides
            For Each sld In ActivePresentation.Slides
                For Each shp In sld.Shapes
                    If shp.Type = msoGroup Then
                        Set oColl = Get_All_Shapes_WIP(shp, oColl, onlySelected, includeMaster) ' recursive call in case of group
                    Else
                        oColl.Add shp ' else add shape to collection
                    End If
                Next shp
            Next sld

        Else ' onlySelected = True
            For Each shp In ActiveWindow.selection.ShapeRange
                If shp.Type = msoGroup Then
                    Set oColl = Get_All_Shapes_WIP(shp, oColl, onlySelected, includeMaster) ' recursive call in case of group
                Else
                    oColl.Add shp ' else add shape to collection
                End If
            Next shp
        End If

        ' master loops
        If includeMaster = True Then ' add also slide master shapes to the collection
            ' master shapes
            For Each shp In ActivePresentation.SlideMaster.Shapes
                If shp.Type = msoGroup Then
                    Set oColl = Get_All_Shapes_WIP(shp, oColl, onlySelected, includeMaster) ' recursive call in case of group
                Else
                    oColl.Add shp ' else add shape to collection
                End If
            Next shp
            ' custom layouts shapes
            For i = 1 To ActivePresentation.SlideMaster.CustomLayouts.Count()
                For Each shp In ActivePresentation.SlideMaster.CustomLayouts.Item(i).Shapes
                If shp.Type = msoGroup Then
                    Set oColl = Get_All_Shapes_WIP(shp, oColl, onlySelected, includeMaster) ' recursive call in case of group
                Else
                    oColl.Add shp ' else add shape to collection
                End If
                Next shp
            Next
        End If

    ' recursive calls:
    ElseIf oShp.Type = msoGroup Then
        For i = 1 To oShp.GroupItems.Count()
            Set shp = oShp.GroupItems.Item(i)
            Set oColl = Get_All_Shapes_WIP(shp, oColl, onlySelected, includeMaster) ' another recursive call in case of group; will repeat this branch in case of subgroup
        Next
    Else
        oColl.Add oShp ' else add shape to collection
    End If

    Set Get_All_Shapes_WIP = oColl ' set (partially) populated collection as function return parameter in every call
End Function

用法示例:

Sub Set_All_Fonts_To_Calibri()
' Sets the font of all text in all shapes in the presentation to "Calibri".

    Dim coll As Collection: Set coll = Get_All_Shapes_WIP(Nothing, Nothing, onlySelected:=False, includeMaster:=True)
    Dim shp As Shape

    For Each shp In coll
        Set_Font shp, "Calibri"
    Next shp
End Sub