Formularze użytkownika to najważniejszy element interfejsu aplikacji EXCEL/VBA. Aby prawidłowo z nich korzystać musimy dobrze zrozumieć jak działa obiekt UserForm. W kodzie VBA możemy spotkać takie instrukcje jak: Show, Load, Hide, Unload. Do tego dochodzą podobne pary zdarzeń – Initialize vs. Activate, Terminate vs. QueryClose. Jak się w tym połapać? O tym przeczytasz w tym artykule.
Jak działa formularz?
Zerknij proszę na diagram poniżej. Jest duży galimatias. Od czego zacząć analizę?

Najlepiej od tego, że możemy umownie wyróżnić kilka faz pracy z już zaprojektowanym formularzem. Jest to więc pewien proces, ale działa on w dwie strony – od lewej do prawej i vice versa..
W pierwszym działamy od lewa do prawa. Mamy więc zaprojektowany formularz, ale nie jest on w żaden sposób aktywny (ETAP 0). Następnie jest on ładowany do pamięci komputera (ETAP 1) i następnie zostaje wyświetlony użytkownikowi (ETAP 2).
W drugim procesie działamy odwrotnie. Najpierw mamy wyświetlony formularz (ETAP 2), a następnie go ukrywamy (ETAP 1). Ostatnią fazą (ETAP 0) jest jego pozbycie się z pamięci i utrata dostępu do wprowadzonych danych.
Sprawdźmy po kolei wszystkie instrukcje i zobaczmy z jakimi zdarzeniami są powiązane.
SHOW – pokaż formularz
Zacznę od chyba najbardziej popularnej instrukcji. Często możemy zetknąć się z taką linią kodu.
1 2 3 4 5 |
Sub PokazFormularz() UserForm1.Show End Sub |
Intencją użytkownika jest wyświetlenie formularza, celem zaś wpisanie informacji do kontrolek i pobranie ich wartości do komórek arkusza.
Instrukcja ta może mieć dwa różne punkty startowe (ETAP 0 lub ETAP 1), natomiast metą jest tutaj zawsze ETAP 2, czyli wyświetlenie formularza UserForm.
W pierwszym przypadku formularz jest najpierw ładowany do pamięci komputera (wyzwala to zdarzenie Initialize) i potem wyświetlany na ekranie (wyzwala to zdarzenie Activate). W drugim przypadku UserForm jest już załadowany, więc następuje tylko jego pokazanie/wyświetlenie (wyzwala to zdarzenie Activate).
Jeżeli formularz nie chce się wyświetlić i wyrzuca błąd to znaczy, że bug znajduje się w którymś z tych dwóch zdarzeń. Zazwyczaj jest to Initialize bowiem w praktyce niewiele osób oprogramowuje zdarzenie Activate. W Initialize jak wskazuje sama nazwa, wprowadzamy ustawienia startowe formularza – głównie ładujemy listy do pól listy lub pól kombi, zaznaczamy domyślne pola wyboru lub przyciski opcji.
1 2 3 4 5 6 7 |
Private Sub UserForm_Initialize() Me.ComboBox1.AddItem "Opcja 1" Me.ComboBox1.AddItem "Opcja 2" Me.ComboBox1.ListIndex = 0 End Sub |
LOAD – załaduj formularz
Instrukcją znacznie rzadziej spotykaną w praktyce jest Load Userform1. Dzięki tej instrukcji przechodzimy z punktu 0 do punktu 1. Czyli UserForm jest ładowany do pamięci komputera, ale nie jest wyświetlany. Zachodzi tu więc tylko zdarzenie Initialize.
Czy ma to sens? Tak! Zwłaszcza w przypadku bardzo rozbudowanych formularzy, które składają się z kilkuset kontrolek. W takiej sytuacji, ładowanie do pamięci da się zauważyć gołym okiem, więc lepiej jest na starcie załadować raz formularz do pamięci, a potem go tylko wyświetlać.
1 2 3 4 5 6 |
Sub ZaladujFormularz() Load UserForm1 MsgBox "Formularz załadowany do pamięci!" End Sub |
UNLOAD – pozbądź się formularza
Polecenie Unload bardzo często występuje w symbiozie z Show. Jest to taka trochę programistyczna partyzantka. Polecenie Unload Me oznacza zamknięcie formularza i usunięcie go z pamięci. Jest to więc przejście z punktu 2 do punktu 0.
1 2 3 4 5 |
Private Sub CommandButton1_Click() Unload Me End Sub |
Na tę instrukcję musimy uważać z jednego bardzo ważnego powodu. Po jej wywołaniu tracimy bezpowrotnie informacje wprowadzone przez nas do kontrolek formularza. Jeżeli wpisaliśmy swoje imię w polu tekstowym, wybraliśmy wartość na polu listy, zaznaczyliśmy niektóre checkboxy – wszystkie te informacje utracimy (punkt 0). Po ponownym wyświetleniu formularza, pokaże się domyślny układ.
UWAGA! Polecenie to wyzwala dwa zdarzenia: najpierw QueryClose, a potem Terminate. W tym pierwszym zdarzeniu mamy jeszcze możliwość wycofania się, przejścia z punktu 2 do punktu 1 (a nie do 0). W ten sposób zachowujemy dane wprowadzone na formularzu.
HIDE – ukryj formularz
Zamiast instrukcji Unload Me często stosuje się Userform1.Hide lub Me.Hide.
1 2 3 4 5 |
Private Sub CommandButton2_Click() Me.Hide End Sub |
Pozwala nam to przejść z punktu 2 do punktu 1. Ukrywamy formularz, ale ciągle znajduje się on w pamięci. Dzięki temu, możemy wciąż odwoływać się do jego kontrolek i odczytywać ich wartości.
Jest to zdecydowanie lepsza praktyka od radykalnego Unload Me.
UWAGA! Instrukcja ta nie wyzwala żadnego zdarzenia (ani QueryClose, ani tym bardziej Terminate).
QUERYCLOSE – upewnij się
W module formularza często możemy się spotkać z takim dziwnym kodem… Sam go stosuję! Co on oznacza?
1 2 3 4 5 6 7 8 9 |
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) 1 If CloseMode = vbFormControlMenu Then 2 MsgBox "Nie ma zamykania przez krzyżyk!" 3 Me.Hide 4 Cancel = True 5 End If End Sub |
Wspomniałem już, że zdarzenie QueryClose pozwala nam na utrzymanie formularza w pamięci. Możemy to zrobić dzięki parametrowi Cancel, ustawionemu na True. W takiej sytuacji makro przerwie działanie i nie pozwoli na całkowite pozbycie się formularza..
Zdarzenie to posiada również drugi parametr CloseMode, który określa sposób w jaki próbowano zakończyć pracę z formularzem. Tryb vbFormControlMenu dotyczy kliknięcia w czerwony krzyżyk na formularzu.
Powyższy kod należy zatem rozumieć tak. Zdarzenie QueryClose przechwytuje próbę usunięcia formularza (punkt 0) za pomocą czerwonego krzyżyka. Nie pozwala jednak na to. Zamiast tego – ukrywa formularz (punkt 1) i wyświetla komunikat MsgBox.
Trzeba zauważyć, że stosujemy tutaj warunek na tryb zamknięcia. Zdarzenie QueryClose zostanie wyzwolone również wtedy, gdy klikniemy w przycisk, pod który podpięty jest kod Unload Me (próba przejścia do punktu 0). W takiej sytuacji jednak nasz warunek nie zadziała, ponieważ stała CloseMode wyniesie 1, a nie 0. W efekcie formularz faktycznie zostanie całkowicie usunięty z pamięci.
TERMINATE – posprzątaj
To zdarzenie jest wyzwalane w momencie usuwania formularza z pamięci. Nie posiada ono żadnych parametrów, które pozwalałyby przerwać ten proces. W efekcie, w tym zdarzeniu umieszcza się jedynie krótkie instrukcje czyszczenia zmiennych obiektowych.
1 2 3 4 5 6 |
Private Sub UserForm_Terminate() Set UserForm1 = Nothing MsgBox "Formularz został usunięty z pamięci." End Sub |