我在 VB.NET 中创建了一个 .NET 库,并且有一个返回 .NET 对象的函数HashTable。
我一直在寻找如何在 Excel VBA 中访问 HashTable 对象中的元素,但找不到解决方案。我是 VBA 新手,请原谅我。我已经寻找过,但找不到出路。
例如,在发生这样的事情之后,我不知道如何访问数据。
Dim hashData As Object
Set hashData = obj.getHashData
Run Code Online (Sandbox Code Playgroud)
请帮忙
Run Code Online (Sandbox Code Playgroud)Dim hashData As Object Set hashData = obj.getHashData
如果getHashData返回 a HashTable,则hashData是 后期绑定HashTable,您可以调用其成员,包括其Item属性:
Dim value As Variant
value = hashData.Item("key")
Run Code Online (Sandbox Code Playgroud)
您不会对针对 的后期绑定成员调用进行编译时验证Object,因此您需要特别小心打字错误,因为Option Explicit在涉及后期绑定时无法拯救您。请参阅HashTable上面链接的文档,了解您可以调用哪些成员。
添加对的引用mscorlib.tlb(您可以在 下找到它C:\Windows\Microsoft.NET\Framework\v4.0.30319,或者如果您的 Excel 是 64 位,则引用等效项\Framework64- 库的位数需要与主机应用程序的位数相匹配)通常会允许早期绑定,但是虽然此库是 COM 可见的,它旨在从托管 (.net) 代码中使用,因此您可以从接口访问这些对象 - 具体类型不会直接公开任何成员:

知道Hashtable实现了该IDictionary接口,我们可以使用早期绑定并获得编译时验证和IntelliSense,如果我们声明hashData As IDictionary:
Dim hashData As mscorlib.IDictionary
Set hashData = New mscorlib.Hashtable
hashData.Add "foo", 42
Debug.Print hashData.Item("foo") 'prints 42
Run Code Online (Sandbox Code Playgroud)
请注意,该Item属性作为默认成员公开:

这意味着您可以Item隐式调用成员,就像对任何标准 VBA 集合对象所做的那样:
Dim hashData As mscorlib.IDictionary
Set hashData = New mscorlib.Hashtable
hashData.Add "foo", 42
Debug.Print hashData("foo") 'prints 42
Run Code Online (Sandbox Code Playgroud)
早期绑定的代码更容易编写,尤其是当您不熟悉所涉及的类型时。但是,如果项目引用 64 位框架并且您的宏需要在 32 位 Excel 上运行,则您需要坚持使用后期绑定以避免绑定问题。
另请注意,使用循环迭代Hashtable对象For Each是行不通的,因为枚举器在 VBA 中的工作方式与在 .NET 中的工作方式不同;theKeys和Valuescollections 是实现该ICollection接口的对象,因此迭代它们也将是不平凡的:For Each循环不起作用,并且虽然您可以设置 a For i = 0 To hashData.Keys.Count - 1,但无法i从 中获取索引处的项目ICollection。
但我们知道ICollection继承IEnumerable, 并IEnumerable 与一起工作For Each,因此我们可以将集合强制转换Keys为IEnumerable, 并迭代所有键和值,如下所示:
Dim hashData As mscorlib.IDictionary
Set hashData = obj.getHashData
Dim hashKeys As mscorlib.IEnumerable
Set hashKeys = hashData.Keys
Dim k As Variant
For Each k In hashKeys
Debug.Print k, hashData(k) 'outputs the key and its associated value
Next
Run Code Online (Sandbox Code Playgroud)
问题是,您无法使用后期绑定代码或不引用 来进行转换,并且后期绑定以某种方式看不到该成员,因此这会引发错误 438:IEnumerablemscorlib.tlbGetEnumerator
Dim hashKeys As Object
Set hashKeys = hashData.Keys
Dim k As Variant
For Each k In hashKeys ' error 438, hashKeys isn't exposing the enumerator
Debug.Print k, hashData(k)
Next
Run Code Online (Sandbox Code Playgroud)
结论:如果您需要 VBA 代码在 32 位和 64 位主机上运行,您将不得不跳过重重困难才能使后期绑定代码正常工作。如果您使用的是 64 位主机,我建议您尽早绑定 64 位框架,并为 32 位主机分发引用 32 位框架的宏的单独副本。分发有点痛苦,但比让后期绑定的代码工作更痛苦。