在 powerpoint 中获取形状索引 VBA

Get shape index in powerpoint VBA

我希望这是一个超级简单的问题,但出于某种原因我无法弄清楚。

我需要使用 VBA 删除 powerpoint 幻灯片上所选形状的子集。我可以使用:

ActivePresentation.Slides(1).Shapes.Range(_Index_).Delete

其中 _Index_ 是形状索引(整数)或形状名称(字符串)数组。

由于形状名称不是唯一的(我正在制作这个宏的人有一个讨厌的习惯,即多个形状具有相同的名称)我需要依赖形状索引号。我的问题是我不知道如何获取给定形状的索引号。

我只能看到如何使用以下方法获取形状名称或形状 ID:

ActiveWindow.Selection.ShapeRange(IdNum).Name
ActiveWindow.Selection.ShapeRange(IdNum).ID

所以我的问题是:如何获取所选形状的形状索引?

尝试几行代码,您将立即获得所有形状的名称window(Ctrl+G 立即查看window)

Dim shp As Shape, I As Integer
For Each shp In ActivePresentation.Slides(1).Shapes
I = I + 1
Debug.Print "Index=" & I & " Name= " & shp.Name & " ID= " & shp.Id & " Type= " & shp.Type
Next

当您对选定的形状进行分组时,该组将成为附加到先前 z 顺序位置末尾的新形状。组内的所有单个形状都附加到组形状本身之后的 z 顺序。

我找不到一种方法来确定组中的哪个项目被选中(子选中,我想我们应该说,因为原始父组保持选中状态,这就是 PPT returns 当你查询 ActiveWindow.Selection.ShapeRange(1).

要识别组中当前被选中的项目,您可以以此为起点:

Sub WorkWithSubSelectedShapes()
' Do stuff with sub-selected shapes within a group
' Courtesy of Andy Pope

    Dim oSh As Shape
    Dim oGSh As Shape
    Dim x As Long

    Set oSh = ActiveWindow.Selection.ShapeRange(1)

    ' Do something with each shape in the group:
    For Each oGSh In oSh.GroupItems
        Debug.Print oGSh.TextFrame.TextRange.Text
    Next

    ' Now do something with each SUB-SELECTED
    ' shape within the group
    With ActiveWindow.Selection.ChildShapeRange
        For x = 1 To .Count
            Debug.Print .Item(x).Name
            Debug.Print .Item(x).TextFrame.TextRange.Text
        Next
    End With

End Sub

下面是一些可能有助于处理 shapes/groups 的代码。它考虑到可能存在组内组(组内(组内))...

Sub ProcessShapes()

    Dim oSh As Shape

    For Each oSh In ActivePresentation.Slides(1).Shapes
        If oSh.Type = msoGroup Then
            Debug.Print "GROUP" & vbTab & oSh.Name & vbTab & oSh.ZOrderPosition

            Call DealWithGroup(oSh)
        Else
            Debug.Print oSh.Name & vbTab & oSh.ZOrderPosition
        End If
    Next

End Sub

Sub DealWithGroup(oSh As Shape)
    Dim x As Long
    For x = 1 To oSh.GroupItems.Count
        If oSh.GroupItems(x).Type = msoGroup Then
            Call DealWithGroup(oSh.GroupItems(x))
        Else
            Debug.Print "GROUP ITEM" & vbTab & oSh.GroupItems(x).Name & vbTab & oSh.GroupItems(x).ZOrderPosition
        End If
    Next
End Sub

为了回答 Peter 的进一步(优秀)问题,这应该有效:

Sub TestIndexOf()
    MsgBox IndexOf(ActiveWindow.Selection.ShapeRange(1))
End Sub

Function IndexOf(oSh As Shape) As Long

    Dim x As Long

    With ActiveWindow.Selection.SlideRange.Shapes
        For x = 1 To .Count
            If .Item(x).Name = oSh.Name Then
                ' Found it, report it
                IndexOf = x
            End If
        Next
    End With
End Function