Обзор 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 и обратная связь.