VBA Как получить доступ ко всем элементам управления ActiveX на листе, даже внутри групп - PullRequest
0 голосов
/ 01 марта 2019

Я хотел бы получить доступ ко всем флажкам ActiveX CheckBox и OptionButtons на рабочем листе.Я попытался сделать цикл для этого, но мой цикл не может получить их все.

После проверки имен тех, которые я не могу получить, я обнаружил, что они сгруппированы (выбравих, щелкните правой кнопкой мыши, группа).Как получить доступ ко всем моим элементам управления на листе, даже если они сгруппированы?

Вот код, который я использую сейчас, и который позволяет мне получить элементы управления, которые находятся непосредственно на листе, не сгруппированы, но этоне позволяю мне получать группированные элементы управления.

Я читаю листы, заполненные пользователями, и некоторые пользователи сгруппировали элементы управления, а другие нет, поэтому я не могу заранее знать, если элементы управленияСгруппировано или нет, поэтому мне нужно получить доступ ко всем из них на текущем листе, который читает мой код.

'ws is my worksheet

Dim obj As OLEObject

For Each obj In ws.OLEObjects
  Debug.Print obj.Name
Next obj
End If

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Я думаю, что это важная задача для достижения всех 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на рабочем листе, представленном как параметр, основанный на функциональности рекурсивного перечисления объектов OleObject, предоставляемых CollectOleObjectsOfShape.CollectionAddElements - это просто вспомогательная функция для создания объединения двух коллекций.В моем коде Пример извлекает коллекцию OleObjects в ActiveSheet, фильтрует ее, чтобы включить только CheckBoxes и OptionBoxes, вызывая FilterOleObjectsByType, а затем печатает имя каждого из них.Однако, получив эту коллекцию, вы можете делать с ней все, что угодно.

Я думаю, что преимущество моего решения состоит в том, что перечисление объектов отделено от фактической задачи, которую вы хотите с ними выполнить.Вам просто нужно включить три функции где-нибудь в коде и вызвать CollectOleObjectsOnWorksheet из вашей части кода.

Обновление:

Я изменил код: (1)OleObjects может иметь msoOLEControlObject, (2) я добавил функцию для фильтрации извлеченных объектов, чтобы они включали только CheckBoxes и OptionBoxes.

Я бы не рекомендовал группировать и разгруппировать Shapes, потому что вы можете получить доступ к этим объектам с помощьюмой код без изменения исходного документа.Однако, если вам нужно это сделать, вы можете вызвать метод ShapeRange .Ungroup Shape, чтобы разгруппировать их, или метод ShapeRange .Group.Последнее немного сложнее, потому что вы должны вызывать его для объекта, возвращаемого Worksheet.Shapes.Range(Array("ShapeName1", "ShapeName2")) или Shape.GroupItems.Range(Array("ShapeName1", "ShapeName2")).

0 голосов
/ 01 марта 2019

Чтобы получить все объекты ActiveX, даже если они помещены в группу, начните с использования Shapes -Collection, а не OLEObjects -Collection.

Вы можете проверить на Type = msoOLEControlObject (12)формы, так что вы перечисляете только OLEObjects.Группы имеют тип msoGroup (6) и имеют коллекцию GroupItems, которая содержит все фигуры в этой группе.

Вы можете написать рекурсивную подпрограмму.См. Следующий код для записи всех OLEObjects.

Обновление : теперь код создает словарь, содержащий все CheckBoxex и RadioButton, а также их значение.Обратите внимание, что вам нужна ссылка на библиотеку сценариев.

Sub ListAllObjects()
    Dim ListOfOptions as Dictionary
    Set ListOfOptions = New Dictionary

    ListObjects ActiveSheet.Shapes, ListOfOptions
End Sub


Sub ListObjects(objArr, ListOfOptions)
    Dim sh As Shape
    For Each sh In objArr
        If sh.Type = msoOLEControlObject Then
            ' Debug.Print sh.Name; sh.Type; TypeName(sh.OLEFormat.Object.Object)
            ' Found OptionButton or CheckBox: Add it to Dictionary.
            If TypeName(sh.OLEFormat.Object.Object) = "OptionButton" Or TypeName(sh.OLEFormat.Object.Object) = "CheckBox" Then
                ListOfOptions.Add sh.Name, sh.OLEFormat.Object.Object.Value
            End If
        End If

        If sh.Type = msoGroup Then
            ListObjects sh.GroupItems, ListOfOptions
        End If
    Next sh
End Sub

К Разгруппировать :

Dim sh As Shape
For Each sh In ActiveSheet.Shapes
    If sh.Type = msoGroup Then sh.Ungroup
Next sh
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...