如何从VBA迭代.NET HashTable的键

时间:2018-09-20 19:57:17

标签: .net vba com hashtable com-interop

.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

1 个答案:

答案 0 :(得分:2)

对于将VBA数组传递到期望System.Array(例如CopyTo(System.Array, Integer))的.NET方法引起的不兼容,我并不感到惊讶。

直接使用从.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

或者可以在Wrap .Net ArrayList with custom VBA class get iterator中描述的包装类的帮助下使用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