Язык программирования VBA предоставляет возможность использования методов, заимствованных из различных файлов, не связанных с Excel или VBA. Примером таких файлов являются библиотеки DLL (Dynamic Link Library - динамически подключаемые библиотеки), используемые операционной системой Windows и другими приложениями. Это открывает перед VBA возможность выполнять операции, выходящие за рамки стандартных функциональностей языка.
Windows API (Application Programming Interface - интерфейс прикладного программирования) представляет собой набор функций, доступных для программистов в среде Windows. Вызывая эти функции из VBA, мы фактически обращаемся к Windows API. Многие ресурсы Windows, используемые системными программистами, находятся в файлах DLL, где хранятся подпрограммы и функции, подключаемые в процессе выполнения модуля, а не во время компиляции.
Функции Windows API и 64-разрядная версия Excel
С началом версии Excel 2010 разработчикам VBA необходимо учитывать особенности 32- и 64-разрядных выпусков. Для обеспечения совместимости с обеими версиями Excel функции Windows API следует объявлять дважды, используя соответствующие директивы компилятора.
Например, следующее объявление совместимо с 32-разрядными версиями Excel, но вызовет ошибку компиляции в 64-разрядных версиях:
Declare Function GetWindowsDirectoryA Lib "kernel32" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
В большинстве случаев достаточно добавить ключевое слово PtrSafe после ключевого слова Declare для обеспечения совместимости с 64-разрядной версией Excel:
Declare PtrSafe Function GetWindowsDirectoryA Lib "kernel32" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Однако следует помнить, что это не будет распознано в более ранних версиях Excel, таких как Excel 2007.
Объявление API-функции и ее использование
Прежде чем использовать функцию Windows API, ее следует объявить вверху программного модуля. Если это нестандартный модуль VBA (например, модуль UserForm, Лист или ЭтаКнига), API-функцию необходимо объявить, как Private.
API-функция должна быть объявлена максимально точно, включая имя используемой функции, библиотеку, в которой она находится, и аргументы функции. После объявления, API-функцию можно использовать в программе VBA.
Сбои при использовании функций Windows API в VBA могут возникнуть, поэтому рекомендуется сохранять работу перед тестированием.
Пример использования функции GetKeyState
Допустим, вы написали макрос VBA, который будет выполняться по-разному, в зависимости от того, удерживает ли пользователь клавишу <Shift> при нажатии кнопки. Для распознавания нажатия клавиши <Shift> можно использовать API-функцию GetKeyState. Эта функция сообщает о состоянии конкретной клавиши, и ее можно использовать для определения, была ли нажата клавиша <Shift> в момент вызова функции.
Приведенный ниже код демонстрирует пример использования функции GetKeyState:
В данном примере используется константа VK_SHIFT для кода клавиши <Shift>, и функция GetKeyState возвращает значение, которое позволяет определить, нажата ли клавиша <Shift>.
При не нажатой клавиши <Shift> и нажатии кнопки запуска макроса, выглядит так:
Как назначить макрос на кнопку описано в статье №6.
Пример определения нажатий клавиш <Shift>, <Ctrl> и <Alt>
Ниже представлен пример, иллюстрирующий различные способы определения нажатий клавиш <Shift>, <Ctrl> и <Alt> с использованием вызовов Windows API:
Обратите внимание, что строка: Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer – КРАСНАЯ. Как думаете почему? Но макрос работает!
Давайте разберем код:
- #If VBA7 And Win64 Then
- Declare PtrSafe Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
- #Else
- Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
- #End If
Эта часть кода представляет собой условное компиляционное выражение (`#If...Then...#Else...#End If`), которое проверяет условие `VBA7 And Win64`. Если данное условие истинно, то используется объявление с ключевым словом `PtrSafe`, указывающим, что функция совместима с 64-битной версией VBA. В противном случае используется стандартное объявление функции без `PtrSafe`.
' Константы для клавиш
- Const КЛ_SHIFT As Integer = &H10
- Const КЛ_CONTROL As Integer = &H11
- Const КЛ_ALT As Integer = &H12 ' клавиша Alt
Здесь определяются константы для клавиш Shift, Control и Alt с их соответствующими значениями. Например, `КЛ_SHIFT` имеет значение `&H10`, что представляет код клавиши Shift.
- Sub ПроверкаКлавиш()
- Dim TabChar As String * 1
- Dim CRChar As String * 1
- Dim Shift As Boolean, Control As Boolean, Alt As Boolean
- Dim Msg As String
- TabChar = Chr(9)
- CRChar = Chr(13)
Здесь создаются переменные `TabChar` и `CRChar`, представляющие символы табуляции и возврата каретки соответственно. Эти символы будут использованы для форматирования сообщения.
' Использование вызовов Windows API для идентификации нажатых клавиш
If GetKeyState(КЛ_SHIFT) < 0 Then Shift = True Else Shift = False
If GetKeyState(КЛ_CONTROL) < 0 Then Control = True Else Control = False
If GetKeyState(КЛ_ALT) < 0 Then Alt = True Else Alt = False
В этой части кода вызываются функции Windows API с использованием объявленных ранее констант для определения состояния клавиш Shift, Control и Alt. Если клавиша нажата, соответствующей переменной (Shift, Control, Alt) присваивается значение `True`, в противном случае - `False`.
' Создание сообщения
Msg = "Shift:" & TabChar & Shift & CRChar
Msg = Msg & "Control:" & TabChar & Control & CRChar
Msg = Msg & "Alt:" & TabChar & Alt & CRChar
Здесь формируется строка Msg, содержащая информацию о состоянии клавиш Shift, Control и Alt. Символы табуляции и возврата каретки используются для удобного форматирования.
' Отображение окна сообщения
MsgBox Msg, vbInformation, "Состояние клавиши"
И, наконец, используется функция MsgBox для отображения окна сообщения с информацией о состоянии клавиш. Параметр `vbInformation` определяет, что окно будет содержать информацию, а строка "Состояние клавиши" - заголовок окна.
Теперь, как это выглядит: