Ранее я рассмотрел методы создания пользовательских форм и основы работы с ними (если вы никогда не работали с пользовательскими формами, рекомендую для начала прочитать указанную заметку). Во многих приложениях для предоставления пользователям пошаговых инструкций по выполнению определенных задач используются специальные мастера, например, мастер импорта текстовых файлов Excel.[1] Мастер — это последовательность диалоговых окон, которые предоставляют пользователю информацию и запрашивают у него необходимые сведения. Часто выбор пользователя в первых диалоговых окнах влияет на содержимое последующих окон. Как правило, пользователю предоставляется возможность свободно перемещаться вперед и назад по последовательности диалоговых окон. Кроме того, он может щелкнуть на кнопке Готово, чтобы использовать значения, принятые по умолчанию.
Рис. 1. Состоящий из четырех этапов мастер, использующий элемент управления MultiРаgе; чтобы увеличить изображение кликните на нем правой кнопкой мыши и выберите Открыть картинку в новой вкладке
Скачать заметку в формате Word или pdf, примеры в формате Excel (содержит макросы)
Вы можете создать мастер посредством VBA-кода и использования последовательности диалоговых окон UserForm. Однако существует более эффективный способ создания мастера с помощью единственного диалогового окна UserForm и элемента управления MultiРаgе со скрытыми вкладками (рис. 1; см. также файл wizard demo.xlsm). Далее описывается создание полноценного приложения-мастера.
Настройка элемента управления MultiPage
Начните с создания диалогового окна UserForm. После этого добавьте элемент управления MultiPage. По умолчанию он содержит две страницы. Щелкните правой кнопкой мыши на элементе управления MultiPage и вставьте достаточное количество страниц, которые будут использоваться при создании мастера (по одной странице на каждый этап работы мастера). Наш пример содержит четыре страницы. Имена страниц элемента управления MultiPage в данном случае роли не играют. Добавьте все необходимые элементы на каждую страницу MultiPage. Эти элементы будут зависеть от целей конкретного приложения. Вы также можете изменить размер MultiPage, чтобы обеспечить место для всех элементов управления.
Добавление кнопок
Далее необходимо добавить кнопки, которые будут управлять переходом между этапами работы мастера. Эти кнопки должны размещаться за пределами элемента управления MultiPage, поскольку они используются при отображении любой страницы элемента управления MultiPage. Как правило, мастера имеют четыре стандартные кнопки:
- Отмена. Отменяет работу мастера, а также результаты всех ранее выполненных действий.
- Назад. Позволяет перейти к предыдущему этапу работы мастера. На первом этапе эта кнопка должна быть неактивной.
- Вперед. Позволяет перейти к следующему этапу работы мастера. На последнем этапе эта кнопка должна быть неактивной.
- Готово. Позволяет завершить работу мастера.
В одних случаях пользователь может щелкнуть на кнопке Готово на любом этапе выполнения мастера, в результате чего будут использованы значения, принятые по умолчанию. В других случаях мастер требует ответа пользователя на некоторые вопросы. Если возникает подобная ситуация, кнопка Готово должна быть отключена до тех пор, пока пользователь не введет все необходимые сведения. В нашем примере требуется ввести информацию в текстовое поле на первом этапе работы мастера. Элементы управления CommandButton в коде называются CancelButton, BackButton, NextButton и FinishButton.
Программирование кнопок
В каждой из четырех кнопок мастера необходима процедура обработки события Click. Ниже приведена процедура обработки события для кнопки CancelButton. Она использует функцию MsgBox (рис. 2), чтобы проверить, завершена ли работа мастера. Если пользователь щелкнет на кнопке Отмена, то диалоговое окно UserForm будет выгружено из памяти и никакие действия выполнены не будут. Этот тип проверки не является обязательным.
1 2 3 4 5 6 7 |
Private Sub CancelButton_Click() Dim Msg As String Dim Ans As Integer Msg = "Отменить выполнение мастера?" Ans = MsgBox(Msg, vbQuestion + vbYesNo, APPNAME) If Ans = vbYes Then Unload Me End Sub |
Рис. 2. После щелчка на кнопке Отмена отображается соответствующее сообщение
Ниже приведена процедура обработки событий для кнопок Назад и Вперед.
1 2 3 4 5 6 7 8 9 |
Private Sub BackButton_Click() MultiPage1.Value = MultiPage1.Value - 1 UpdateControls End Sub Private Sub NextButton_Click() MultiPage1.Value = MultiPage1.Value + 1 UpdateControls End Sub |
Эти две процедуры изменяют значение свойства Value элемента управления MultiРagе, после чего вызывают процедуру – UpdateControls, которая отвечает за включение и отключение кнопок BackButton и NextButton.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Sub UpdateControls() Select Case MultiPage1.Value Case 0 BackButton.Enabled = False NextButton.Enabled = True Case MultiPage1.Pages.Count - 1 BackButton.Enabled = True NextButton.Enabled = False Case Else BackButton.Enabled = True NextButton.Enabled = True End Select ' Изменение заголовка Me.Caption = APPNAME & " Шаг " _ & MultiPage1.Value + 1 & " из " _ & MultiPage1.Pages.Count ' Поле Имя обязательно для ввода данных If tbName.Text = "" Then FinishButton.Enabled = False Else FinishButton.Enabled = True End If End Sub |
Процедура изменяет заголовок диалогового окна UserForm, и в результате он отображает текущий этап работы мастера и общее количество этапов (константа APPNAME является глобальной и определена в модуле кода Module1). После этого проверяется содержимое поля Имя на первой странице элемента управления MultiРаgе (для создания этого поля используется элемент управления TextBox, который называется tbName). Данное поле обязательно нужно заполнить, поэтому кнопка Готово отключена до момента заполнения. Если элемент управления TextBox остается пустым, кнопка FinishButton отключена. В противном случае кнопка Готово активизируется, и у пользователя появляется возможность щелкнуть на ней.
Программирование зависимостей
В большинстве мастеров ответ пользователя на определенном этапе может повлиять на элементы управления, которые отображаются на последующих этапах. В нашем примере (см. рис. 1) на третьем этапе пользователь должен указать, какие программы он применяет в работе. После этого (на четвертом этапе) пользователю предлагается оценить выбранные программные продукты Microsoft. Элемент управления OptionButton для каждого продукта отображается только в том случае, если пользователь выбрал этот продукт на предыдущем этапе.
С точки зрения программирования эта задача реализуется в результате обработки события Change элемента управления MultiPage. Как только значение элемента управления MultiPage изменится (после щелчка на кнопке Назад или Вперед), будет запущена процедура MultiPagel_Change. Если в элементе управления активна последняя страница (четвертый этап), то процедура проверяет значения элементов управления Checkbox на странице, соответствующей третьему этапу работы мастера. После этого на странице для четвертого этапа выполняются необходимые изменения элементов управления.
В данном примере используются два массива: один — для элементов управления CheckBox, соответствующих продуктам (используется на третьем этапе), а второй — для элементов управления Frame (используется на четвертом этапе). Цикл For Next скрывает элементы управления Frame для тех продуктов, которые не были выбраны на предыдущем этапе. После этого изменяется вертикальное расположение отображаемых на экране элементов управления Frame. Если на странице, соответствующей третьему этапу работы мастера, не был выбран ни один из продуктов, то на последнем этапе скрываются все элементы управления, кроме TextBox, который содержит сообщение. Щелкните на кнопке Готово для выхода (если, конечно, на первом этапе введено имя). Процедура MultiPage1_Change:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
Private Sub MultiPage1_Change() Dim TopPos As Long Dim FSpace As Long Dim AtLeastOne As Boolean Dim i As Long ' Настроить страницу оценок? If MultiPage1.Value = 3 Then ' Создание массива элементов управления CheckBox Dim ProdCB(1 To 3) As MSForms.CheckBox Set ProdCB(1) = cbExcel Set ProdCB(2) = cbWord Set ProdCB(3) = cbAccess ' Создание массива элементов управления Frame Dim ProdFrame(1 To 3) As MSForms.Frame Set ProdFrame(1) = FrameExcel Set ProdFrame(2) = FrameWord Set ProdFrame(3) = FrameAccess TopPos = 22 FSpace = 8 AtLeastOne = False ' Цикл по всем продуктам For i = 1 To 3 If ProdCB(i) Then ProdFrame(i).Visible = True ProdFrame(i).Top = TopPos TopPos = TopPos + ProdFrame(i).Height + FSpace AtLeastOne = True Else ProdFrame(i).Visible = False End If Next i ' Никакой из продуктов не используется? If AtLeastOne Then lblHeadings.Visible = True Image4.Visible = True lblFinishMsg.Visible = False Else lblHeadings.Visible = False Image4.Visible = False lblFinishMsg.Visible = True If tbName = "" Then lblFinishMsg.Caption = _ "Укажите имя на шаге 1." Else lblFinishMsg.Caption = _ "Щелкните на кнопке Готово для завершения." End If End If End If End Sub |
Выполнение задачи
Когда пользователь щелкает на кнопке Готово, мастер выполняет свою задачу: перемещает информацию из диалогового окна UserForm в следующую пустую строку рабочего листа. Эта процедура – FinishButton_Click. Она начинается с определения следующей пустой строки рабочего листа и задания значения переменной (r). Остальная часть процедуры выполняет идентификацию значений элементов управления и ввод данных в ячейки листа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
Private Sub FinishButton_Click() Dim r As Long r = Application.WorksheetFunction. _ CountA(Range("A:A")) + 1 ' Вставка имени Cells(r, 1) = tbName.Text ' Вставить пол Select Case True Case obMale: Cells(r, 2) = "Мужчина" Case obFemale: Cells(r, 2) = "Женщина" Case obNoAnswer: Cells(r, 2) = "Неизвестно" End Select ' Сведения о пользователе Cells(r, 3) = cbExcel Cells(r, 4) = cbWord Cells(r, 5) = cbAccess ' Вставка оценок If obExcel1 Then Cells(r, 6) = "" If obExcel2 Then Cells(r, 6) = 0 If obExcel3 Then Cells(r, 6) = 1 If obExcel4 Then Cells(r, 6) = 2 If obWord1 Then Cells(r, 7) = "" If obWord2 Then Cells(r, 7) = 0 If obWord3 Then Cells(r, 7) = 1 If obWord4 Then Cells(r, 7) = 2 If obAccess1 Then Cells(r, 8) = "" If obAccess2 Then Cells(r, 8) = 0 If obAccess3 Then Cells(r, 8) = 1 If obAccess4 Then Cells(r, 8) = 2 Unload Me End Sub |
Как только мастер будет испытан и все станет работать должным образом, можно изменить значение свойства Style элемента управления MultiPage. Это свойство должно иметь значение 2 — fmTabStyleNone.
[1] По материалам книги Джон Уокенбах. Excel 2010. Профессиональное программирование на VBA. – М: Диалектика, 2013. – С. 484–491.