如何从 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
.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