Сводка
После объявления массива для некоторого типа объекта, в котором тип не использует интерфейс, который получает из COM 's IDispatch
интерфейс (и поэтому неправильно настроен для включения технологии позднего связывания [OLE] Automation ), пытаясь назначить массив для Variant
переменная не работает в соответствии с моими ожиданиями.
В частности, похоже, что целочисленный указатель на массив назначен Variant
переменная, а не копия массива.
Может кто-нибудь объяснить такое поведение?Это стандартное поведение языка VBA 7.1? [EDIT-A1] Это тип VBA Variant
не может обрабатывать такие массивы? [EDIT-A2]
[EDIT-A1] - В настоящее время (04/6/19),похоже, что это ошибка.
[EDIT-A2] - Нет, поскольку внутренние параметры процедуры для аргументов ByRef
Variant
могутправильно указывать на такие массивы, если такие массивы передаются в качестве значений для таких аргументов.
Фон
Подробнее о том, что, по-видимому, происходит
После проверки различных адресов и указателей памяти, похоже, что при назначении таких массивов переменным Variant
, Long
(или LongPtr
) указатели на 'указатели безопасного массива VB' массивов назначаются вместо этого.Это противоречит поведению копирования массива, задокументированному здесь в спецификации языка VBA как ожидаемое поведение.Я пришел к выводу, что такое присвоение указателя происходило после просмотра документации VB6 по массивам VB и их разметке памяти, хранящейся здесь .
Мое исследование того, была ли ранее задокументирована проблема
Я искал в Интернете, Office VBA Reference документацию, а также спецификацию языка VBA , чтобы узнать, задокументирована ли эта проблема кем-либо еще.Единственное место, где я обнаружил, что эта проблема, возможно, уже была частично задокументирована, это ответ на переполнение стека, размещенный здесь .К сожалению, пост не говорит много о проблеме.
Определенные типы массивов, с которыми я тестировал эту проблему
Я столкнулся с этой проблемой с массивами следующих типов объектов, которые не используют интерфейсы вывод из IDispatch
:
stdole.IUnknown
* stdole.IFont
mscoree.CorRuntimeHost
† mscorlib.AppDomain
† mscorlib.Type
* Из библиотеки типов OLE Automation COMв stdole2.tlb
.
† Из библиотеки типов COM для .NET framework v4.0.30319.
Подробнее о типе объекта, который использует интерфейс, не производный от IDispatch
, является
Такими типами объектов являются vbDataObject
типы.К сожалению, текущая документация VBA по константе vbDataObject
является неточной.Я нахожусь в процессе обновления документации, и вы можете увидеть мое обновленное определение для константы здесь .
[ПРАВКА - ссылка на спецификацию COM удалена, поскольку она больше не актуальна.]
Относительно массивов других типов объектов
Массивы типов vbObject
(типы объектов COM, поддерживающие технологию позднего связывания [OLE] Automation), по-видимому, назначены на Variant
переменные в прямом и ожидаемом порядке - массив копируется и присваивается напрямую
Сбой VBE при проверке таких массивов с использованием часов VBE
Потенциально связанная проблема связана с ошибкой, которая возникала, когда VBE наблюдательное выражение было помещено в массив типа, который использовал интерфейс, а не вывод из IDispatch
.Ошибка, используемая для неожиданного сбоя VBE.Эта ошибка, похоже, была исправлена Microsoft в течение последнего месяца.
Версии программного обеспечения
<strong>Software</strong> | <strong>Version</strong>
-------------------------+---------------<br> VBA | 7.1 <sup>‡</sup><br>-------------------------+---------------<br> Microsoft Excel | 2016 <sup>§</sup><br>-------------------------+---------------<br> Microsoft Windows (OS) | 8.1 <sup>¶</sup>
‡ Полный текст для версии «Retail 7.1.1088» - последняя версия.
§ В частности, последняя версия и сборка (выпущена 3 июня 2019 г., версия 1905, сборка 11629.20214), а также более ранние номера сборок 11629.20196 и 11601.20204 (первая была выпущена14 мая 2019 г.)
¶ ver.exe
программа печатает "Microsoft Windows [Версия 6.3.9600]" .
Код
Dim MyArray() As stdole.IUnknown ' Type from OLE Automation
' COM type library in stdole2.tlb.
Dim MyVariant As Variant
MyVariant = MyArray
Я ожидал, что MyVariant
сохранит копию массива MyArray
.
Вместо этого в 32-битномверсия VBA, MyVariant
хранит значение Long
, которое выглядит как указатель на MyArray
.
Проблема отладки
Нажмите здесь , чтобы код VBA могпомочь в устранении проблемы.