excel 在VBA中使用.NET哈希表返回类型

rvpgvaaj  于 2023-08-08  发布在  .NET
关注(0)|答案(2)|浏览(97)

我在VB.NET中创建了一个.NET库,其中有一个函数返回HashTable对象。
我一直在寻找如何在Excel VBA中访问HashTable对象中的元素,但找不到解决方案。我是新来的VBA所以请原谅我。我已经找过了,但找不到出路。
例如,在这样的事情之后,我不知道如何访问数据。

Dim hashData As Object
   Set hashData = obj.getHashData

字符串
请帮帮忙

fdx2calv

fdx2calv1#

Dim hashData As Object
Set hashData = obj.getHashData

字符串
如果getHashData返回一个HashTable,那么hashData是一个后期绑定的HashTable,你可以调用它的成员,包括它的Item属性:

Dim value As Variant
value = hashData.Item("key")


对于Object的后期绑定成员调用,您不会得到编译时验证,因此您需要特别小心打字错误,因为当涉及后期绑定时,Option Explicit无法保存您。有关可以调用的成员,请参阅上面链接的HashTable文档。
添加对mscorlib.tlb的引用(您可以在C:\Windows\Microsoft.NET\Framework\v4.0.30319下找到它,或者如果您的Excel是64位的,则引用\Framework64中的等效内容-库的位数需要与主机应用程序的位数相匹配)通常允许早期绑定,但尽管此库是COM可见的,但它旨在从托管(.net)代码中使用,因此您将从接口访问这些对象-具体类型不会直接公开任何成员:
x1c 0d1x的数据
知道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


请注意,Item属性公开为 *default成员 *:



这意味着您可以隐式调用Item成员,就像您可以对任何标准VBA集合对象执行的操作一样:

Dim hashData As mscorlib.IDictionary
Set hashData = New mscorlib.Hashtable
hashData.Add "foo", 42
Debug.Print hashData("foo") 'prints 42


早期绑定的代码更容易编写,特别是当您不熟悉所涉及的类型时。但是,如果项目引用的是64位框架,并且您的宏需要在32位Excel上运行,则需要坚持后期绑定以避免绑定问题。
还要注意,使用For Each循环迭代Hashtable对象是不起作用的,因为枚举器在VBA中的工作方式与在.NET中的工作方式不同; KeysValues集合是实现ICollection接口的对象,因此迭代它们也是非常重要的:For Each循环将不起作用,虽然您可以设置For i = 0 To hashData.Keys.Count - 1,但您无法从ICollection中获取索引为i的项。
但是我们知道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


问题是,你不能使用后期绑定代码或不引用mscorlib.tlb而 * 强制转换 * 到IEnumerable,后期绑定不知何故不会看到GetEnumerator成员,所以这会引发错误438:

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


结论:如果您需要VBA代码在32位和64位主机上都能运行,那么您将不得不通过各种方式来使后期绑定的代码正常工作。如果您使用的是64位主机,我建议您使用64位框架的早期绑定,并为32位主机分发引用32位框架的宏的单独副本。分发代码有点麻烦,但比让后期绑定的代码工作要轻松。

pgx2nnw8

pgx2nnw82#

我知道自从这个问题被问到/回答以来已经过去了很多时间,但请允许我回答,为了像我这样试图找到一种方法来迭代HashTable的键(在VBA的VBIDE中)的其他人。
通过阅读Mathieu Guindon的答案(非常棒)和this以及this,我想提出我的2美分,我们可以做到这一点,而不必添加引用和后期绑定(也可以在VBA的即时窗口内工作)。
如所附的屏幕截图所示,我们只需要使用ArrayList的.AddRange方法将Hashtable的键添加到ArrayList中,如:

ArrayList.AddRange HashTable.Keys

字符串
这一点也被提及。
由于Hashtable的Keys属性是一个 ICollection,而ArrayList的AddRange方法也可以使用 ICollection,它们就像是天作之合,瞧,现在我们可以迭代Hashtable的键,尽管是以一种迂回的方式作为ArrayList。
我从这里提到的使用Queue的Enqueue向ArrayList添加一系列值中得到了这个想法。但是,该方法不允许在VBA中使用For Each进行迭代,而是将添加的键视为单个对象而不是可迭代对象。
我只是希望以后在某个地方的某个人会发现这很有用。谢谢大家。
x1c 0d1x的数据

相关问题