如何从 VBA 迭代 .NET 哈希表的键

How to Iterate over Keys of a .NET HashTable from VBA

.net 运行时通过 mscorlib.dll 公开给 VBA(和其他 COM 客户端)。理论上,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

将 VBA 数组传递给需要 System.Array(例如 CopyTo(System.Array, Integer))的 .NET 方法会导致不兼容,我并不感到惊讶。

我在直接使用从 .Keys 返回的集合方面没有取得多大成功,因此将其复制到 ArrayList 似乎是一个有用的解决方法。

HashTable.Keys returns 一个 ICollection,并且 ArrayList 可以在其 AddRange() 中接受一个 ICollection,所以这应该有效:

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

或者它可以在 Wrap .Net ArrayList with custom VBA class get iterator 中描述的包装器 class 的帮助下用 For Each 枚举(所有学分都在此处):

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