Найти тему
VBA Excel с нуля

VBA Excel № 75. Функции Windows API.

Оглавление
Скриншот с моего ноутбука
Скриншот с моего ноутбука

Язык программирования 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` определяет, что окно будет содержать информацию, а строка "Состояние клавиши" - заголовок окна.

Теперь, как это выглядит:

Скриншот с моего ноутбука
Скриншот с моего ноутбука