VBA как получить доступ к элементам словаря Ключи напрямую - PullRequest
2 голосов
/ 25 марта 2019

контекст

В VBA вы можете создать и заполнить словарь, например:

    Dim oDict As Object
    Set oDict = CreateObject("Scripting.Dictionary")
    oDict("key 1") = "value 1"
    oDict("key 2") = "value 2"
    oDict("key 3") = "value 3"

С помощью метода Keys вы можете получить ключи в виде массива:

Возвращает массив, содержащий все существующие ключи в объекте Dictionary.

    Dim aKeys() As Variant
    aKeys = oDict.Keys
    Debug.Print VarType(aKeys)       ' prints "8204"
    Debug.Print VarType(oDict.Keys)  ' prints "8204"

проблема

Но когда я получаю доступ к одному из ключей напрямую, он выдает это загадочное сообщение об ошибке:

    Debug.Print aKeys(2)       ' prints "key 3"
    Debug.Print oDict.Keys(2)  ' Run-time error '451':
                               ' Property let procedure not defined 
                               ' and property get procedure did not 
                               ' return an object

неудачных попыток решить

Хотя описанное выше является основным поведением, я не понял ниже полный список попыток обработать oDict.Keys как массив:

Option Explicit

Public Function ArrayGet(ByRef aArray() As Variant, i As Integer) As Variant
    ArrayGet = aArray(i)
End Function

Public Function ArrayWrap(ByRef aArray() As Variant) As Variant()
    ArrayWrap = aArray
End Function

Public Sub TEST()

    Dim oDict As Object
    Set oDict = CreateObject("Scripting.Dictionary")
    oDict("key 1") = "value 1"
    oDict("key 2") = "value 2"
    oDict("key 3") = "value 3"

    Dim aKeys() As Variant
    aKeys = oDict.Keys

    Debug.Print VarType(aKeys)           ' prints "8204"
    Debug.Print VarType(oDict.Keys)      ' prints "8204"

    Debug.Print aKeys(2)                 ' prints "key 3"
    'Debug.Print oDict.Keys(2)            ' Run-time error '451': Property let procedure not defined and property get procedure did not return an object
    'Debug.Print oDict.Keys.Get(2)        ' Run-time error '424': Object required
    'Debug.Print oDict.Keys.Item(2)       ' Run-time error '424': Object required

    Debug.Print ArrayGet(aKeys, 2)       ' prints "key 3"
    'Debug.Print ArrayGet(oDict.Keys, 2)  ' Compile error : Type mismatch: array or user-defined type expected

    'Debug.Print Array(aKeys)(2)          ' Run-time error '9'  : Subscript out of range
    'Debug.Print Array(oDict.Keys)(2)     ' Run-time error '9'  : Subscript out of range

    Debug.Print ArrayWrap(aKeys)(2)      ' prints "key 3"
    'Debug.Print ArrayWrap(oDict.Keys)(2) ' Compile error : Type mismatch: array or user-defined type expected

    Dim key As Variant

    For Each key In aKeys
        Debug.Print key                  ' prints "key 1", "key 2" and "key 3"
    Next key

    For Each key In oDict.Keys
        Debug.Print key                  ' prints "key 1", "key 2" and "key 3"
    Next key

End Sub

Ответы [ 2 ]

3 голосов
/ 25 марта 2019

Если вы не добавляете ссылку на Microsoft Scripting Runtime, вам нужно использовать позднюю привязку, чтобы использовать объект словаря. При позднем связывании вы теряете некоторую функциональность.

Если вы попытаетесь получить доступ к ключам словаря по индексу, вы получите ошибку времени выполнения 451.

Ошибка времени выполнения '451':
Процедура разрешения свойства не определена, а процедура получения свойства не вернула объект.

enter image description here

Если вы добавите ссылку на библиотеку Microsoft Scripting Runtime в проект с помощью Инструментов VBE, Ссылки, теперь вы можете получить доступ к ключам словаря непосредственно через его порядковый номер индекса.

enter image description here

Sub test3()

    Dim i As Long, dict As New Scripting.dictionary

    dict.Add Key:="key1", Item:="item1"
    dict.Add Key:="key2", Item:="item2"
    dict.Add Key:="key3", Item:="item3"

    For i = LBound(dict.Keys) To UBound(dict.Keys)
        Debug.Print dict.Keys(i)
    Next i

End Sub

'results
key1
key2
key3
3 голосов
/ 25 марта 2019

что не так

    Debug.Print oDict.Keys(2)  ' Run-time error '451':
                               ' Property let procedure not defined 
                               ' and property get procedure did not 
                               ' return an object

Слово Keys является методом. Хотя VBA позволяет вам убрать круглые скобки, если не предоставлены аргументы, это все же метод. Если вы укажете круглые скобки за ним, содержимое будет передано методу. Метод Keys не принимает целочисленный аргумент.

как исправить

Путем явного указания скобок метода Keys (например, Keys()) мы можем напрямую применять / следовать скобками для доступа к элементу массива.

В соответствии с примером в вопросе: следующие две альтернативы эквивалентны:

    Debug.Print aKeys(2)         ' prints "key 3"
    Debug.Print oDict.Keys()(2)  ' prints "key 3"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...