VBA
Formularze użytkownika
Szukaj…
Najlepsze praktyki
UserForm
to moduł klasy z projektantem i instancją domyślną . Dostęp do projektanta można uzyskać, naciskając Shift + F7 podczas przeglądania kodu z tyłu , a dostęp do kodu można uzyskać, naciskając klawisz F7 podczas przeglądania projektanta .
Za każdym razem pracuj z nową instancją.
Forma, będąc modułem klasy , jest więc planem obiektu . Ponieważ formularz może przechowywać stan i dane, lepszą praktyką jest praca z nową instancją klasy niż z domyślną / globalną:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
'...
End If
End With
Zamiast:
UserForm1.Show vbModal
If Not UserForm1.IsCancelled Then
'...
End If
Praca z domyślną instancją może prowadzić do subtelnych błędów, kiedy formularz jest zamykany czerwonym przyciskiem „X” i / lub gdy Unload Me
jest używany z tyłu kodu.
Zaimplementuj logikę gdzie indziej.
Formularz powinien być zaniepokojony, ale nic z prezentacją: przycisk Click
obsługi, który łączy się z bazą danych i uruchamia zapytania parametrycznego na podstawie danych wprowadzonych przez użytkownika, robi zbyt wiele rzeczy.
Zamiast tego zaimplementuj logikę aplikacyjną w kodzie odpowiedzialnym za wyświetlanie formularza, a nawet lepiej, w dedykowanych modułach i procedurach.
Napisz kod w taki sposób, że UserForm jest zawsze odpowiedzialny za to, jak wyświetlać i gromadzić dane: skąd dane pochodzą lub co dzieje się z danymi później, nie ma znaczenia.
Dzwoniącemu nie powinno przeszkadzać sterowanie.
Stwórz dobrze zdefiniowany model formularza do pracy, albo we własnym dedykowanym module klasy, albo zamknięty w samym kodzie formularza - ujawnij model za pomocą procedur Property Get
i pozwól, aby kod klienta działał z tymi: tworzą abstrakcję kontroli i ich drobiazgowe szczegóły, ujawniając tylko odpowiednie dane w kodzie klienta.
Oznacza to kod, który wygląda następująco:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .Message, vbInformation
End If
End With
Zamiast tego:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .txtMessage.Text, vbInformation
End If
End With
Obsługa zdarzenia QueryClose.
Formularze zazwyczaj mają przycisk Zamknij , a monity / okna dialogowe mają przyciski Ok i Anuluj ; użytkownik może zamknąć formularz za pomocą pola kontrolnego formularza (czerwony przycisk „X”), który domyślnie niszczy instancję formularza (kolejny dobry powód, aby za każdym razem pracować z nową instancją ).
With New UserForm1
.Show vbModal
If Not .IsCancelled Then 'if QueryClose isn't handled, this can raise a runtime error.
'...
End With
End With
Najprostszym sposobem obsługi zdarzenia QueryClose
jest ustawienie parametru Cancel
na True
, a następnie ukrycie formularza zamiast jego zamknięcia :
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
Me.Hide
End Sub
W ten sposób przycisk „X” nigdy nie zniszczy instancji, a osoba dzwoniąca może bezpiecznie uzyskać dostęp do wszystkich członków publicznych.
Ukryj, nie zamykaj.
Kod, który tworzy obiekt, powinien być odpowiedzialny za jego zniszczenie: forma nie jest odpowiedzialna za rozładowanie i zakończenie się.
Unikaj używania opcji Unload Me
w formularzu za kodem. Me.Hide
tego zadzwoń do Me.Hide
, aby kod wywołujący mógł nadal korzystać z obiektu utworzonego po zamknięciu formularza.
Nazwij rzeczy.
Użyj okna narzędzi właściwości ( F4 ), aby ostrożnie nazwać każdą kontrolkę w formularzu. Nazwa kontrolki jest używana w kodzie, więc jeśli nie używasz narzędzia refaktoryzującego, które może to obsłużyć, zmiana nazwy kontrolki spowoduje uszkodzenie kodu - więc o wiele łatwiej jest robić rzeczy właściwie, niż próbować aby dokładnie ustalić, które z 20 TextBox12
oznacza TextBox12
.
Tradycyjnie formanty UserForm są nazywane prefiksami w stylu węgierskim:
-
lblUserName
dla kontrolkiLabel
która wskazuje nazwę użytkownika. -
txtUserName
dla kontrolkiTextBox
której użytkownik może wprowadzić nazwę użytkownika. -
cboUserName
dla kontrolkiComboBox
której użytkownik może wprowadzić lub wybrać nazwę użytkownika. -
lstUserName
dla kontrolkiListBox
której użytkownik może wybrać nazwę użytkownika. -
btnOk
lubcmdOk
dla kontrolkiButton
oznaczonej „Ok”.
Problem polega na tym, że gdy np. Interfejs użytkownika zostanie przeprojektowany, a ComboBox
zmieni się w ListBox
, nazwa musi się zmienić, aby odzwierciedlić nowy typ kontrolki: lepiej nazwać formanty dla tego, co reprezentują, niż po ich typie kontrolnym - aby oddzielić kod z interfejsu użytkownika w jak największym stopniu.
-
UserNameLabel
dla etykiety tylko do odczytu, która wskazuje nazwę użytkownika. -
UserNameInput
dla kontrolki, w której użytkownik może wprowadzić lub wybrać nazwę użytkownika. -
OkButton
dla jednego przycisku oznaczonego „Ok”.
Niezależnie od tego, który styl zostanie wybrany, wszystko jest lepsze niż pozostawienie wszystkim kontrolkom ich domyślnych nazw. Idealna jest również spójność stylu nazewnictwa.
Obsługa QueryClose
Zdarzenie QueryClose
jest wywoływane za każdym razem, gdy formularz ma zostać zamknięty, czy to poprzez działanie użytkownika, czy programowo. Parametr CloseMode
zawiera wartość VbQueryClose
która wskazuje, w jaki sposób formularz został zamknięty:
Stały | Opis | Wartość |
---|---|---|
vbFormControlMenu | Formularz zamyka się w odpowiedzi na działanie użytkownika | 0 |
vbFormCode | Formularz zamyka się w odpowiedzi na instrukcję Unload | 1 |
vbAppWindows | Sesja Windows się kończy | 2) |
vbAppTaskManager | Menedżer zadań systemu Windows zamyka aplikację hosta | 3) |
vbFormMDIForm | Nieobsługiwany w VBA | 4 |
Dla lepszej czytelności najlepiej jest użyć tych stałych zamiast bezpośrednio ich wartości.
Formularz użytkownika, który można anulować
Biorąc pod uwagę formularz z przyciskiem Anuluj
Kod w formularzu może wyglądać następująco:
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
Kod wywołujący może następnie wyświetlić formularz i wiedzieć, czy został anulowany:
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
Właściwość IsCancelled
zwraca wartość True
po kliknięciu przycisku Anuluj lub po zamknięciu formularza przez użytkownika za pomocą pola kontrolnego .