Использование возвращаемого типа .NET HashTable в VBA - PullRequest
1 голос
/ 20 июня 2019

Я создал библиотеку .NET в VB.NET, и есть функция, которая возвращает объект HashTable.

Я искал, как получить доступ к элементам в объекте HashTable в ExcelVBA, но не могу найти решение.Я новичок в VBA, так что извините.Я искал, но не могу найти выход.

Например, после чего-то подобного я не знаю, как получить доступ к данным.

   Dim hashData As Object
   Set hashData = obj.getHashData

Пожалуйста, помогите

1 Ответ

2 голосов
/ 21 июня 2019
Dim hashData As Object
Set hashData = obj.getHashData

Если getHashData возвращает HashTable, то hashData является поздним HashTable, и вы можете вызывать его членов , включая его Item свойство * * 1013

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

Вы не получаете проверку во время компиляции при вызовах участников с поздним связыванием в отношении Object, поэтому вам следует быть особенно осторожным при опечатках, поскольку Option Explicit не может спасти вас, если используется поздняя привязка. Обратитесь к документации HashTable, указанной выше, чтобы узнать, каких членов вы можете вызвать.

Добавление ссылки на mscorlib.tlb (вы найдете ее в C:\Windows\Microsoft.NET\Framework\v4.0.30319 или ссылку на эквивалент из \Framework64, если ваш Excel 64-битный - битность библиотеки должна соответствовать битности хост-приложения ) обычно допускает раннее связывание, но хотя эта библиотека является видимой для COM, она предназначена для использования из управляемого (.net) кода, поэтому вы получаете доступ к этим объектам из интерфейсов - конкретные типы не предоставляют никаких членов напрямую :

object browser showing no members for Hashtable class

Зная, что 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 предоставляется как элемент по умолчанию :

members of IDictionary

Это означает, что вы можете иметь неявный вызов члена 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, вам нужно придерживаться позднего связывания, чтобы избежать проблем с связыванием.

Также обратите внимание, что итерация объекта Hashtable с циклом For Each не будет работать, поскольку счетчики работают в VBA по сравнению с тем, как они работают в .NET; коллекции Keys и Values являются объектами, реализующими интерфейс ICollection, поэтому их повторение также будет нетривиальным: цикл For Each не будет работать, и пока вы можете настроить For i = 0 To hashData.Keys.Count - 1, Вы не можете получить предмет по индексу i из ICollection.

Но мы знаем, что ICollection наследует IEnumerable, а IEnumerable работает с For Each, поэтому мы можем cast Keys collection к 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

Проблема в том, что вы не можете привести к IEnumerable с кодом с поздней привязкой или без ссылки на mscorlib.tlb, и поздняя привязка как-то не увидит члена 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-битных хостов. Немного труднее распространять, но менее болезненно, чем заставить работать код с поздним связыванием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...