Как перебирать ключи .NET HashTable из VBA - PullRequest
0 голосов
/ 20 сентября 2018

Среда выполнения .net доступна для VBA (и других COM-клиентов) через mscorlib.dll.Теоретически, VBA может использовать .net HashTables.На практике я застрял.Я закомментировал строки, которые сами по себе не работают.Простой вариант использования заключается в переборе ключей, как и для Scripting.Dictionary

Function GenerateSampleHashTable() As Object
    Dim ht As Object
    Set ht = CreateObject("System.Collections.HashTable")
    ht.Add "Foo", "Bar"
    ht.Add "Red", "FF0000"
    ht.Add "Green", "00FF00"
    ht.Add "Blue", "0000FF"
    Set GenerateSampleHashTable = ht
End Function

Sub TestHashTable()
    Dim ht As Object
    '*** PRETEND THIS CAME OUT OF A C# COMPONENT ***
    Set ht = GenerateSampleHashTable

    Debug.Print ht.ContainsKey("Foo")

    Dim oKeys As Object
    Set oKeys = CreateObject("System.Collections.ArrayList")
    oKeys.Capacity = ht.Count

    Dim vKeys() As Variant
    vKeys() = oKeys.ToArray()



    Dim col As mscorlib.ICollection
    Set col = ht.Keys()
    'col.CopyTo oKeys, 0   'Runtime error: Type mismatch
    'col.CopyTo vKeys(), 0  'Compile Error: Type mismatch

    Dim vKeyLoop As Variant
    For Each vKeyLoop In vKeys()

        Debug.Print vKeyLoop, ht.Item(vKeyLoop)
    Next
End Sub

1 Ответ

0 голосов
/ 20 сентября 2018

Я не удивлен, что передача массива VBA в метод .NET, который ожидает System.Array (например, CopyTo(System.Array, Integer)), вызывает несовместимость.

Я не достиг большого успеха в прямом использовании возвращенной коллекциииз .Keys, поэтому копирование его в ArrayList кажется полезным обходным путем.

HashTable.Keys возвращает ICollection, и ArrayList может принять ICollection в своем AddRange(), так что это должно работать:

Dim ht As Object
Set ht = GenerateSampleHashTable()

Dim oKeys As Object
Set oKeys = CreateObject("System.Collections.ArrayList")
oKeys.AddRange ht.Keys()

Полученный oKeys может быть перечислен напрямую:

Dim i As Long
For i = 0 To oKeys.Count - 1
    Debug.Print oKeys.Item(i)
Next

Или может быть перечислен с For Each с помощью оболочкикласс, описанный в Обертка .Net ArrayList с пользовательским классом VBA get итератор (куда идут все кредиты):

Dim wr As ThatCollectionWrapperClass
Set wr = New ThatCollectionWrapperClass
wr.Init oKeys  'Poor man's constructor - add that method to the class and remove its Class_Initialize

Dim k As Variant
For Each k In wr
    Debug.Print k
Next
...