Меню на VBA. Готовим профессионально
Автор: Виталий Шаповал
[Скачать пример к статье] [Комментировать в форуме]
Введение
Любая прикладная программа, ориентированная на широкий круг пользователей, должна иметь простые и удобные средства для взаимодействия с ними. Данные средства, в совокупности именуемые пользовательским интерфейсом, предназначены для подачи определенной команды работающей программе, выбора необходимого режима работы или осуществления какого-либо стандартного действия. В графическом интерфейсе Windows для передачи команд приложению используются меню и панели управления.
При разработке интерфейса программы основное проблемой является юзабилити, т.е. ориентированность на максимальное психологическое и эстетическое удобство для пользователя.
VBA, в отличие от своего "старшего" собрата, не имеет собственного редактора меню, однако он может использовать стандартные объекты MS Office. Конечно, в офисных разработках вполне можно обойтись и без меню. Однако меню придает программе профессиональный вид, позволяя избежать использования множества командных кнопок, натыканных на листы и/или формы, позволяя достичь того самого юзабилити.
Теоретическое отступление
В объектной модели MS Office все меню и панели инструментов представлены объектами типа CommandBar. Каждая панель инструментов, строка меню, каждое меню в строке меню и даже подменю, заключающееся в пункте меню - это объекты типа CommandBar. Все объекты CommandBar любого приложения Office объединены в семейство CommandBars данного приложения (рис.1).
Рис. 1 - Иерархическая схема объекта CommandBar
Элементы управления, находящиеся на панели инструментов, представлены объектами типа CommanBarControl, которые объединены в семейство CommandBarControls, где CommandBarButton - кнопка или элемент меню, вызывающий выполнение команды; CommandBarComboBox - сложно организованные меню, такие как список, поле ввода или поле со списком; CommandBarPopUp - непосредственно меню либо вложенное меню.
Таким образом, меню - это набор пунктов, каждый из которых соответствует той или иной команде или действию, а панели инструментов представляют собой обычные кнопки с пиктограммами, объединенные в единое целое и сгруппированные по функциональному назначению [1, 2].
Зачем все это?
Практически каждый пользователь MS Office знает, что с помощью диалогового окна Сервис - Настройка можно создавать новые панели инструментов и дополнительные пункты главного меню для всех приложений Office, а в Access - еще и новую строку меню [3]. Однако данные настройки действую глобально для всего приложения MS Office.
Программирование же позволяет создавать для разрабатываемых прикладных приложений (на базе Excel, Word и т.д.) собственный интерфейс, например, исключить из меню и панелей инструментов родительского приложения кнопки и команды, не используемые в пользовательском приложении и добавить новые необходимые средства. Причем изменения в стандартный интерфейс приложений Офис будут внесены только на время работы дочернего приложения, и по его закрытии все вернется на круги своя.
Пример реализации
В принципе, процесс создания собственной панели инструментов или даже собственного меню достаточно подробно рассмотрен в [3, 4]. В данной статье остановимся лишь на специфической задаче, а именно - добавления пользовательского пункта меню в основное меню Excel, подобно тому, как это делают Trados, Adobe Acrobat, Promt и т.п. Однако наше меню должно появляться только при запуске пользовательской программы и благополучно удаляться по завершении работы, никак не влияя на работоспособность исходного приложения.
Ниже приведен код с подробными комментариями, содержащими всю полноту информации. Отмечу только, что основной код находится в программном модуле VBA (Module), а процедуры, выполняемые при открытии и закрытии - в модуле "ЭтаКнига" (ThisWorkbook). Для автоматического запуска при том или ином событии макрос должен иметь одно из следующих имен:
AutoExec - запускается при старте приложения или загрузке глобального шаблона.
AutoNew - запускается при создании нового документа.
AutoOpen - запускается при открытии документа.
AutoClose - запускается при закрытии документ.
AutoExit - запускается при выходе из приложения или при закрытии глобального шаблона.
Кроме того, с помощью логического флага производится проверка на наличие уже существующего пункта меню с таким названием. Это сделано во избежание дублирования меню вследствие повторного запуска программы.
Листинг кода из Module '
' Создание выпадающего меню приложения в главном меню Excel
'
' Запрет использования недекларированных переменных
Option Explicit
' Объявляем наши переменные
Dim WorksheetsMenuBar As CommandBar ' Основная панель Excel
Dim cmdBarCtrl As CommandBarControl ' Пункт основного меню Excel
'
' Функция формирования меню при открытии файла
'
Private Sub Auto_open()
Dim MyNewMenu As CommandBarPopup ' Выпадающее пользовательское меню
Dim cmdSubBarCtrl As CommandBarControl ' Пункт выпадающего меню
Dim MenuExists As Boolean ' Флаг существования пользовательского меню
Dim SubMenu As CommandBarPopup ' Выпадающее подменю
Dim SubCmdCtrl As CommandBarControl ' Пункт выпадающего подменю
'
' Проверка существования меню с таким названием
'
Set WorksheetsMenuBar = CommandBars.ActiveMenuBar
MenuExists = False
For Each cmdBarCtrl In WorksheetsMenuBar.Controls
If cmdBarCtrl.Caption = "&Новое меню" Then
MenuExists = True
Exit For
End If
Next cmdBarCtrl
If Not MenuExists Then ' Если меню не существует, то
'
' Формирование нового меню
'
Set MyNewMenu = WorksheetsMenuBar.Controls.Add(Type:=msoControlPopup, Temporary:=True)
MyNewMenu.Caption = "&Новое меню"
'
' Формирование пункты нового меню
'
Set cmdSubBarCtrl = MyNewMenu.Controls.Add(Type:=msoControlButton)
With cmdSubBarCtrl
.BeginGroup = True
.FaceId = 926
.Caption = "&О программе"
.OnAction = "About"
End With
'
' Добавление выпадающего подменю
'
Set SubMenu = MyNewMenu.Controls.Add(Type:=msoControlPopup, Temporary:=True, Before:=1)
SubMenu.Caption = "Подменю"
'
' Пункты выпадающего подменю
'
Set SubCmdCtrl = SubMenu.Controls.Add(Type:=msoControlButton, ID:=1)
With SubCmdCtrl
.FaceId = 71
.Caption = "&Подпункт 1"
.OnAction = "SubMacro1"
End With
Set SubCmdCtrl = SubMenu.Controls.Add(Type:=msoControlButton, ID:=2)
With SubCmdCtrl
.BeginGroup = True
.FaceId = 72
.Caption = "&Подпункт 2"
.OnAction = "SubMacro2"
End With
End If
End Sub
'
' Функция удаления пользовательского меню
' и восстановления исходного меню при закрытии файла
'
Private Sub Auto_close()
On Error Resume Next
Set WorksheetsMenuBar = CommandBars.ActiveMenuBar
For Each cmdBarCtrl In WorksheetsMenuBar.Controls
If cmdBarCtrl.Caption = "&Новое меню" Then
WorksheetsMenuBar.Reset
Exit For
End If
Next cmdBarCtrl
End Sub
'
' Собственно, обработка пунктов нового меню
' Сейчас здесь прописаны заглушки, вместо которых
' подставляются ваши макросы
'
Private Sub About() ' Пункт основного меню
MsgBox "Выполнен пункт меню", vbInformation, "О программе"
End Sub
Private Sub SubMacro1() ' Подпункт 1 выпадающего меню
MsgBox "Запущен макрос из подпункта 1", vbInformation, "Выполнен"
End Sub
Private Sub SubMacro2() ' Подпункт 2 выпадающего меню
MsgBox "Запущен макрос из подпункта 2", vbInformation, "Выполнен"
End Sub
Листинг кода из "Эта книга" Option Explicit
Private Sub Workbook_Open()
With Application
.Caption = "Создаем свое меню"
End With
' Собственно, формируем меню при открытии
ActiveWorkbook.RunAutoMacros xlAutoOpen
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
With Application
.Caption = Empty
End With
' Возвращаем все, как было до нас
ActiveWorkbook.RunAutoMacros xlAutoClose
End Sub
В результате запуска на выполнение меню должно приобрести вид, подобный изображенному на рис. 2. В одном меню можно расположить несколько подменю - главное знать меру и не запутать самих себя. Меню могут быть украшены пиктограммами, т.н. FaceIDs. (О том, как их получить, будет рассказано в следующей статье).
Рис. 2 - Наше приложение с нашим меню
В архиве находится готовый файл, который можно использовать в качестве шаблона для разработки собственных решений.
Литература
- Хорев В.Д. Самоучитель программирования на VBA в Microsoft Office. - К.: Юниор, 2001. - 296 с.
- Гарнаев А. Ю. Самоучитель VBA. - СПб.: БХВ-Петербург, 2002. - 512 с.
- Биллиг Владимир Арнольдович. Основы офисного программирования и язык VBA
- Тихвинский Виталий. VBA Создание меню