我认为访问所有 OLE 对象是一项重要任务,因此我以模块化方式创建了以下代码并在一些示例对象上进行了测试:
Option Explicit
Public Sub Example()
Dim colOleObjects As Collection: Set colOleObjects = CollectOleObjectsOnWorksheet(ActiveSheet)
Dim colCheckboxesAndOptionboxes As Collection: Set colCheckboxesAndOptionboxes = FilterOleObjectsByType(colOleObjects, Array("Forms.CheckBox.1", "Forms.OptionButton.1"))
Dim varItem As Variant: For Each varItem In colCheckboxesAndOptionboxes
Dim shpItem As Shape: Set shpItem = varItem
Debug.Print shpItem.Name
Next varItem
End Sub
Public Function FilterOleObjectsByType(colSource As Collection, varTypes As Variant) As Collection
Dim colDestination As Collection: Set colDestination = New Collection
Dim varElement As Variant: For Each varElement In colSource
Dim shpElement As Shape: Set shpElement = varElement
Dim i As Long: For i = LBound(varTypes) To UBound(varTypes)
If shpElement.OLEFormat.progID = varTypes(i) Then
colDestination.Add shpElement
Exit For
End If
Next i
Next varElement
Set FilterOleObjectsByType = colDestination
End Function
Public Function CollectOleObjectsOnWorksheet(ewsTarget As Worksheet) As Collection
Dim colResult As Collection: Set colResult = New Collection
Dim varChild As Variant: For Each varChild In ewsTarget.Shapes
Dim shpChild As Shape: Set shpChild = varChild
Dim colChild As Collection: Set colChild = CollectOleObjectsOfShape(shpChild)
CollectionAddElements colResult, colChild
Next varChild
Set CollectOleObjectsOnWorksheet = colResult
End Function
Public Function CollectOleObjectsOfShape(shpTarget As Shape) As Collection
Dim colResult As Collection: Set colResult = New Collection
Select Case shpTarget.Type
Case MsoShapeType.msoEmbeddedOLEObject, MsoShapeType.msoOLEControlObject
colResult.Add shpTarget
Case MsoShapeType.msoGroup
Dim varChild As Variant: For Each varChild In shpTarget.GroupItems
Dim shpChild As Shape: Set shpChild = varChild
Dim colChild As Collection: Set colChild = CollectOleObjectsOfShape(shpChild)
CollectionAddElements colResult, colChild
Next varChild
End Select
Set CollectOleObjectsOfShape = colResult
End Function
Public Sub CollectionAddElements(colTarget As Collection, colSource As Collection)
Dim varElement As Variant: For Each varElement In colSource
colTarget.Add varElement
Next varElement
End Sub
基本上,CollectOleObjectsOnWorksheet 返回工作表上所有 OleObjects 的集合,作为建立在 CollectOleObjectsOfShape 提供的递归枚举 OleObjects 功能的参数。 CollectionAddElements 只是一个辅助函数,用于创建两个集合的联合。在我的代码中,Example 检索 ActiveSheet 上的 OleObjects 集合,通过调用 FilterOleObjectsByType 将其过滤为仅包含 CheckBoxes 和 OptionBoxes,然后打印每个名称。然而,一旦你有了这个收藏,你就可以用它做任何事情。
我认为我的解决方案的优点是对象的枚举与您想要对它们执行的实际任务分离。您只需在代码中的某处包含这三个函数,然后从您的代码部分调用 CollectOleObjectsOnWorksheet。
更新:
我修改了代码:(1) OleObjects 可能有 msoOLEControlObject,(2) 我添加了一个 Function 来过滤检索到的对象,这样它们就只包含 CheckBoxes 和 OptionBoxes。
我不建议对形状进行分组和取消分组,因为您可以使用我的代码访问这些对象,而无需修改原始文档。但是,如果您需要这样做,您可以调用 Shape 的 .Ungroup 方法将它们取消组合,或者调用 ShapeRange 的 .Group 方法。后者有点棘手,因为您必须在 Worksheet.Shapes.Range(Array("ShapeName1", "ShapeName2")) 或 Shape.GroupItems.Range(Array("ShapeName1", "ShapeName2")) 返回的对象上调用它。