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:
-
lblUserNamedla kontrolkiLabelktóra wskazuje nazwę użytkownika. -
txtUserNamedla kontrolkiTextBoxktórej użytkownik może wprowadzić nazwę użytkownika. -
cboUserNamedla kontrolkiComboBoxktórej użytkownik może wprowadzić lub wybrać nazwę użytkownika. -
lstUserNamedla kontrolkiListBoxktórej użytkownik może wybrać nazwę użytkownika. -
btnOklubcmdOkdla kontrolkiButtonoznaczonej „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.
-
UserNameLabeldla etykiety tylko do odczytu, która wskazuje nazwę użytkownika. -
UserNameInputdla kontrolki, w której użytkownik może wprowadzić lub wybrać nazwę użytkownika. -
OkButtondla 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 .