VBA
Пользовательские формы
Поиск…
Лучшие практики
UserForm
- это модуль класса с дизайнером и экземпляром по умолчанию . Доступ к дизайнеру можно получить, нажав Shift + F7 при просмотре кода , а доступ к коду можно получить, нажав F7 во время просмотра дизайнера .
Работайте с новым экземпляром каждый раз.
Будучи модулем класса , форма является, таким образом, планом для объекта . Поскольку форма может содержать состояние и данные, лучше работать с новым экземпляром класса, а не с по умолчанию / глобальным:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
'...
End If
End With
Вместо:
UserForm1.Show vbModal
If Not UserForm1.IsCancelled Then
'...
End If
Работа с экземпляром по умолчанию может привести к тонким ошибкам, когда форма закрыта красной кнопкой «X» и / или когда Unload Me
используется в коде.
Реализуйте логику в другом месте.
Форма должна касаться только презентации : кнопка Click
handler, которая подключается к базе данных и запускает параметризованный запрос на основе ввода пользователем, делает слишком много вещей .
Вместо этого внедрите прикладную логику в код, который отвечает за отображение формы или даже лучше в выделенных модулях и процедурах.
Напишите код таким образом, чтобы UserForm всегда отвечал за знание того, как отображать и собирать данные: откуда поступают данные или что происходит с данными после этого, не является проблемой.
Абонент не должен беспокоиться о контроле.
Создайте хорошо определенную модель для формы, с которой можно работать, либо в своем собственном выделенном модуле класса, либо инкапсулироваться внутри самого кода кода - выставлять модель с процедурами Property Get
и работать с этим кодом клиента: это делает форма абстракции над элементами управления и их подробные детали, подвергая только соответствующие данные клиенту.
Это означает, что код выглядит следующим образом:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .Message, vbInformation
End If
End With
Вместо этого:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .txtMessage.Text, vbInformation
End If
End With
Обработать событие QueryClose.
Обычно формы имеют кнопку « Закрыть» , а в подсказках / диалоговом окне есть кнопки « ОК» и « Отмена» ; пользователь может закрыть форму, используя блок управления формы (красная кнопка «X»), которая по умолчанию уничтожает экземпляр формы (еще одна веская причина работать с новым экземпляром каждый раз ).
With New UserForm1
.Show vbModal
If Not .IsCancelled Then 'if QueryClose isn't handled, this can raise a runtime error.
'...
End With
End With
Самый простой способ обработать событие QueryClose
- установить для параметра Cancel
значение True
, а затем скрыть форму, а не закрывать ее:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
Me.Hide
End Sub
Таким образом, кнопка «X» никогда не уничтожит экземпляр, и вызывающий может безопасно получить доступ ко всем открытым членам.
Скрыть, не закрывать.
Код, который создает объект, должен нести ответственность за его уничтожение: ответственность за разгрузку и завершение работы лежит не на форме.
Избегайте использования Unload Me
в коде кода. Вызовите Me.Hide
вместо этого, чтобы вызывающий код все еще мог использовать объект, который он создал, когда форма закрывается.
Назовите вещи.
Используйте окно свойств ( F4 ) для тщательного определения каждого элемента управления в форме. Имя элемента управления используется в коде, так что, если вы не используете инструмент рефакторинга, который может справиться с этим, переименование элемента управления приведет к поломке кода - так что гораздо проще делать все правильно, в первую очередь, чем пытаться чтобы точно определить, какой из 20 текстовых TextBox12
означает.
Традиционно элементы управления UserForm называются префиксами венгерского стиля:
-
lblUserName
дляlblUserName
управленияLabel
, указывающего имя пользователя. -
txtUserName
дляtxtUserName
управленияTextBox
где пользователь может ввести имя пользователя. -
cboUserName
для управленияComboBox
где пользователь может ввести или выбрать имя пользователя. -
lstUserName
дляlstUserName
управленияListBox
где пользователь может выбрать имя пользователя. -
btnOk
илиcmdOk
для управленияButton
с надписью «Ok».
Проблема заключается в том, что когда, например, пользовательский интерфейс изменен и ComboBox
изменяется на ListBox
, имя необходимо изменить, чтобы отразить новый тип управления: лучше называть элементы управления для того, что они представляют, а не после их типа управления - отделить кода из пользовательского интерфейса, насколько это возможно.
-
UserNameLabel
для метки только для чтения, которая указывает имя пользователя. -
UserNameInput
дляUserNameInput
управления, в котором пользователь может ввести или выбрать имя пользователя. -
OkButton
для командной кнопки с надписью «Ok».
Какой бы стиль ни выбрали, все лучше, чем оставлять все элементы управления по умолчанию. Согласованность в стиле именования тоже идеальна.
Обработка QueryClose
Событие QueryClose
возникает всякий раз, когда форма закрывается, независимо от того, выполняется ли это с помощью действия пользователя или программно. Параметр CloseMode
содержит VbQueryClose
перечисления VbQueryClose
которое указывает, как форма была закрыта:
постоянная | Описание | Значение |
---|---|---|
vbFormControlMenu | Форма закрывается в ответ на действие пользователя | 0 |
vbFormCode | Форма закрывается в ответ на оператор Unload | 1 |
vbAppWindows | Сеанс Windows завершается | 2 |
vbAppTaskManager | Диспетчер задач Windows закрывает приложение-хост | 3 |
vbFormMDIForm | Не поддерживается в VBA | 4 |
Для лучшей читаемости лучше использовать эти константы, а не использовать их значение напрямую.
Отмена пользовательской формы
Учитывая форму с кнопкой « Отмена»
Кодировка кода формы может выглядеть так:
Option Explicit
Private Type TView
IsCancelled As Boolean
SomeOtherSetting As Boolean
'other properties skipped for brievety
End Type
Private this As TView
Public Property Get IsCancelled() As Boolean
IsCancelled = this.IsCancelled
End Property
Public Property Get SomeOtherSetting() As Boolean
SomeOtherSetting = this.SomeOtherSetting
End Property
'...more properties...
Private Sub SomeOtherSettingInput_Change()
this.SomeOtherSetting = CBool(SomeOtherSettingInput.Value)
End Sub
Private Sub OkButton_Click()
Me.Hide
End Sub
Private Sub CancelButton_Click()
this.IsCancelled = True
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
this.IsCancelled = True
Me.Hide
End If
End Sub
Затем вызывающий код может отображать форму и знать, была ли она отменена:
Public Sub DoSomething()
With New UserForm1
.Show vbModal
If .IsCancelled Then Exit Sub
If .SomeOtherSetting Then
'setting is enabled
Else
'setting is disabled
End If
End With
End Sub
Свойство IsCancelled
возвращает True
при нажатии кнопки « Отмена» или когда пользователь закрывает форму с помощью блока управления .