Обзор 64-разрядной версии Visual Basic для приложений
Microsoft Visual Basic для приложений (VBA) — это версия Visual Basic, поставляемая вместе с Microsoft Office. В Microsoft Office 2010 язык VBA содержит такие функциональные возможности, которые позволяют коду VBA правильно выполняться как в 32-разрядных, так и в 64-разрядных средах.
Примечание.
По умолчанию пакет Office 2010, 2013 и 2016 устанавливается в 32-разрядной версии. Во время установки необходимо явно выбрать 64-разрядную версию. Начиная с Office 2019 и Microsoft 365, по умолчанию используется 64 – разрядная версия.
Выполнение кода VBA, который был написан до выпуска Office 2010 (VBA версии 6 и более ранних), на 64-разрядной платформе может приводить к возникновению ошибок, если код не был модифицирован для работы в 64-разрядных версиях Office. Ошибки будут возникать по той причине, что язык VBA версии 6 и более ранних версий неявно ориентирован на 32-разрядные платформы и обычно содержит операторы Declare, запускающие в действие функции API Windows путем использования 32-разрядных типов данных для указателей и дескрипторов. Так как язык VBA версии 6 и более ранних версий не имеет специального типа данных для указателей и дескрипторов, им используется тип данных Long, который является 32-разрядным 4-байтным типом данных, предназначенным для ссылки на указатели и дескрипторы. Указатели и дескрипторы в 64-разрядных средах являются 8-байтными 64-разрядными числами. Эти 64-разрядные числа не могут храниться в 32-разрядных типах данных.
Примечание.
Код VBA нуждается в модификации, только если он выполняется в 64-разрядной версии Microsoft Office.
Проблема с выполнением унаследованного программного кода VBA в 64-разрядном пакете Office заключается в том, что при попытке загрузить 64-разрядные значения в 32-разрядный тип данных 64-разрядные числа усекаются. Это может приводить к переполнениям памяти, неожиданным результатам в коде и возможным сбоям приложения.
Для устранения этой проблемы и обеспечения правильной работы кода VBA как в 32-разрядных, так и в 64-разрядных средах в язык VBA добавлен ряд функциональных возможностей. Новые возможности языка VBA обобщены в таблице, представленной внизу этого документа. Три важных добавления: псевдоним типа LongPtr, тип данных LongLong и ключевое слово PtrSafe.
LongPtr. Теперь язык VBA включает псевдоним типа переменной LongPtr. Фактический тип данных, в который разрешается тип LongPtr, зависит от версии пакета Office, в котором он используется; тип LongPtr разрешается в тип Long в 32-разрядных пакетах Office, и тип LongPtr разрешается в тип LongLong в 64-разрядных версиях пакета Office. Используйте тип LongPtr для указателей и дескрипторов.
LongLong. Тип данных LongLong — это 64-разрядные целые числа со знаком, которые доступны только в 64-разрядных версиях пакета Office. Используйте тип LongLong для 64-разрядных целых чисел. Для явного присвоения значений типа LongLong (включая тип LongPtr на 64-разрядных платформах) целочисленным типам данных меньшего размера должны использоваться функции преобразования. Неявные преобразования типа LongLong в меньшие целочисленные типы не допускаются.
PtrSafe. Ключевое слово PtrSafe декларирует, что оператор Declare безотказно выполняется в 64-разрядных версиях пакета Office.
Важно!
Теперь все операторы Declare должны содержать ключевое слово PtrSafe, когда выполняются в 64-разрядных версиях пакета Office. Важно понимать, что просто добавление ключевого слова PtrSafe в оператор Declare означает только, что оператор Declare явно ориентирован на 64-разрядные данные. Все типы данных в операторе, предназначенные для хранения 64-разрядных значений (включая возвращаемые значения и параметры), все еще нуждаются в изменении, чтобы хранить 64-разрядные числа.
Примечание.
Операторы Declare с ключевым словом PtrSafe представляют собой рекомендованный синтаксис. Операторы Declare, содержащие слово PtrSafe, работают корректно в среде разработки VBA7 как на 32-разрядных, так и на 64 разрядных платформах.
Чтобы обеспечить обратную совместимость в VBA7 и более ранних версиях, используйте следующую структуру:
#If VBA7 Then
Declare PtrSafe Sub...
#Else
Declare Sub...
#EndIf
Рассмотрим следующие примеры оператора Declare. Выполнение немодифицированного оператора Declare в 64-разрядных версиях пакета Office приводит к ошибке, показывающей, что оператор Declare не содержит спецификатора PtrSafe. Модифицированный пример кода VBA содержит спецификатор PtrSafe, однако заметим, что возвращаемое значение (указатель на активное окно) возвращает тип данных Long. В 64-разрядном пакете Office это неправильно, так как указатель должен быть 64-разрядным. Спецификатор PtrSafe сообщает компилятору, что оператор Declare ориентирован на 64-разрядные числа, так что оператор выполняется без ошибки. Но поскольку возвращаемое значение не обновлено до 64-разрядного типа данных, возвращаемое значение усекается, в результате чего возвращается некорректное значение.
Ниже приведен пример немодифицированного устаревшего оператора Declare языка VBA:
Declare Function GetActiveWindow Lib "user32" () As Long
Приведенный ниже пример оператора Declare языка VBA модифицирован для включения спецификатора PtrSafe, но по-прежнему использует 32-разрядное возвращаемое значение:
Declare PtrSafe Function GetActiveWindow Lib "user32" () As Long
Чтобы повторно выполнить цикл, следует модифицировать оператор Declare для включения спецификатора PtrSafe, а также необходимо обновить все переменные в операторе, которые требуются для хранения 64-разрядных чисел, чтобы переменные использовали 64-разрядные типы данных.
Приведенный ниже пример оператора Declare языка VBA модифицирован для включения ключевого слова PtrSafe и обновлен для использования 64-разрядного типа данных (LongPtr):
Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Итак, для правильной работы кода в 64-разрядных версиях пакета Office необходимо найти и модифицировать все существующие операторы Declare, чтобы они использовали спецификатор PtrSafe. Внутри этих операторов Declare также необходимо найти и модифицировать все типы данных, которые ссылаются на дескрипторы или указатели, чтобы использовать псевдоним нового 64-разрядного совместимого типа LongPtr и типы, необходимые для хранения 64-разрядных целых чисел с новым типом данных LongLong. Кроме того, следует обновить все определенные пользователем типы, содержащие указатели или дескрипторы и 64-разрядные целые числа, чтобы использовать 64-разрядные типы данных, и убедиться в правильности присвоений всех переменных, чтобы предотвратить появление ошибок несоответствия типов.
Написание кода, который работает как в 32-разрядных, так и 64-разрядных версиях Office
Чтобы написать код, переносимый между 32-разрядными и 64-разрядными версиями Office, требуется лишь использовать для всех указателей и значений дескрипторов псевдоним нового типа LongPtr вместо типа Long или LongLong. Псевдоним типа LongPtr разрешается в правильный тип данных Long или LongLong в зависимости от того, какая версия пакета Office используется.
Обратите внимание, что если требуется реализовать другую логику, например при работе с 64-разрядными значениями в больших проектах Excel, можно использовать константу условной компиляции Win64, как показано в следующем разделе.
Написание кода, который работает как в Office 2010 (32-разрядный или 64-разрядный пакет), так и в предыдущих версиях Office
Чтобы написать код, работающий как в новой, так и в старой версиях Office, можно использовать комбинацию новых условных констант компилятораVBA7 и Win64. Условная константа компилятора Vba7 применяется, чтобы определить, работает ли программный код в версии 7 редактора VB (версия VBA, которая поставляется в Office 2010). Условная константа компиляции Win64 применяется, чтобы определить, какая версия (32-разрядная или 64-разрядная) Office функционирует на компьютере.
#if Vba7 then
' Code is running in the new VBA7 editor
#if Win64 then
' Code is running in 64-bit version of Microsoft Office
#else
' Code is running in 32-bit version of Microsoft Office
#end if
#else
' Code is running in VBA version 6 or earlier
#end if
#If Vba7 Then
Declare PtrSafe Sub...
#Else
Declare Sub...
#EndIf
Сводка обновлений языка VBA7
Новые дополнения языка VBA обобщаются и объясняются в приведенной ниже таблице.
Имя | Тип | Описание |
---|---|---|
PtrSafe | Ключевое слово | Утверждает, что оператор Declare ориентирован на 64-разрядные системы. Требуется для 64-разрядных данных. |
LongPtr | Тип данных | Псевдоним типа, который отображается на тип Long в 32-разрядных системах или на тип LongLong в 64-разрядных системах. |
LongLong | Тип данных | 8-байтный тип данных, который доступен только в 64-разрядных системах. Числовой тип. Целые числа в диапазоне от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. Использование типа LongLong допустимо только на 64-разрядных платформах. Кроме того, тип LongLong может не преобразовываться неявно в тип данных меньшего размера (например, невозможно присвоить тип LongLong типу Long). Это необходимо для предотвращения случайного усечения указателя. Явное приведение типов данных допускается, так что в приведенном выше примере можно было бы применить CLng к LongLong и присвоить результат типу Long (действительно только для 64-разрядных платформ). |
^ | Символ объявления типа LongLong | Явно объявляет литерал как тип LongLong. Требуется для объявления литерала LongLong, который больше чем максимальное значение типа Long (иначе он будет неявно преобразован в тип double). |
CLngPtr | функция преобразования типа | Преобразует простое выражение в LongPtr. |
CLngLng | функция преобразования типа | Преобразует простое выражение в тип данных LongLong (действительно только для 64-разрядных платформ). |
vbLongLong | Константа VarType | Целое число LongLong (действительно только для 64-разрядных платформ). |
DefLngPtr | Оператор DefType | Устанавливает для диапазона переменных тип данных по умолчанию как LongPtr. |
DefLngLng | Оператор DefType | Устанавливает для диапазона переменных тип данных по умолчанию как LongLong. |
См. также
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.