Głównym tematem tej lekcji będzie instrukcja Select Case
, która jest
swego rodzaju odmianą instrukcji warunkowej, przeznaczoną do obsługi warunków z bardzo dużo ilością możliwych
wariantów.
Oprócz tego, podczas tej lekcji poznamy wreszcie wielokrotnie już wspominane wyliczenia.
Instrukcja Select Case
Aby dobrze zrozumieć istotę instrukcji Select Case
, powinieneś się najpierw
zapoznać z przykładowym kodem, w którym instrukcja ta byłaby idealnym rozwiązaniem, jednak zamiast niej użyto tradycyjnej
instrukcji warunkowej If ... Then
.
Poniższa funkcja zwraca nazwę miesiąca w zależności od numeru miesiąca podanego jako argument numer
(jak
zapewne pamiętasz z lekcji o funkcjach wbudowanych, VBA posiada w swoim repertuarze funkcję wykonującą to zadanie, więc
nie ma potrzeby pisania jej na nowo, jednak na potrzeby tej lekcji zostanie uczyniony wyjątek).
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
Function nazwaMiesiaca(numer As Integer) As String
If numer = 1 Then
nazwaMiesiaca = "styczeń"
Else
If numer = 2 Then
nazwaMiesiaca = "luty"
Else
If numer = 3 Then
nazwaMiesiaca = "marzec"
Else
If numer = 4 Then
nazwaMiesiaca = "kwiecień"
Else
If numer = 5 Then
nazwaMiesiaca = "maj"
Else
If numer = 6 Then
nazwaMiesiaca = "czerwiec"
Else
If numer = 7 Then
nazwaMiesiaca = "lipiec"
Else
If numer = 8 Then
nazwaMiesiaca = "sierpień"
Else
'(...)
End If
End If
End If
End If
End If
End If
End If
End If
End Function
Funkcja składa się z 12 warunków, z których każdy kolejny zagnieżdżony jest w poprzednim. Funkcja sprawdza najpierw czy
podany jako argument wejściowy numer miesiąca to 1. Jeżeli warunek ten jest spełniony, funkcja otrzymuje wartość
styczeń i kończy swoje działanie. W przeciwnym razie wykonywanie kodu przekazywane jest do bloku
Else tego warunku, gdzie zagnieżdżona jest kolejna instrukcja warunkowa, sprawdzająca z
kolei czy podany numer miesiąca to 2, itd.
Sam widzisz, że zaprezentowana powyżej postać tej funkcji jest bardzo rozwlekła i czasochłonna. Ponadto przy
zagnieżdżaniu tak dużej ilości instrukcji warunkowych bardzo łatwo o pomyłkę (a przecież miesięcy jest tylko 12,
a mogą zdarzyć się funkcje, gdzie w ten sposób trzeba będzie opisać kilkadziesiąt jakichś obiektów).
Dodatkowo, jeżeli chcesz zachować przejrzystość kodu i przy każdej kolejnej instrukcji warunkowej stosować nowe
wcięcie, to instrukcja warunkowa opisująca grudzień nie mieściłaby się już na ekranie, a zastosowanie w tej sytuacji
przeniesienia tekstu do nowej linii za pomocą operatora _
wprowadziłoby w kodzie jeszcze większy
chaos.
Doskonałym sposobem na ominięcie opisanych niedogodności jest instrukcja Select Case.
Poniżej znajduje się jeszcze jedna wersja funkcji nazwaMiesiaca
, wykorzystująca właśnie tę instrukcję.
Dokładne wyjaśnienie schematu działania polecenia Select Case znajdziesz
pod ramką z kodem.
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
Function nazwaMiesiaca(numer As Integer) As String
Select Case numer
Case 1
nazwaMiesiaca = "styczeń"
Case 2
nazwaMiesiaca = "luty"
Case 3
nazwaMiesiaca = "marzec"
Case 4
nazwaMiesiaca = "kwiecień"
Case 5
nazwaMiesiaca = "maj"
Case 6
nazwaMiesiaca = "czerwiec"
Case 7
nazwaMiesiaca = "lipiec"
Case 8
nazwaMiesiaca = "sierpień"
Case 9
nazwaMiesiaca = "wrzesień"
Case 10
nazwaMiesiaca = "październik"
Case 11
nazwaMiesiaca = "listopad"
Case 12
nazwaMiesiaca = "grudzień"
End Select
End Function
Zastosowanie polecenia Select Case
sprawia, że kod jest o wiele bardziej przejrzysty,
krótszy i łatwiejszy do modyfikowania.
Instrukcja Select Case
jest specyficznym rodzajem instrukcji warunkowej.
Różnica pomiędzy zwykłą instrukcją warunkową, a instrukcją Select Case
polega
na tym, że instrukcja If ... Then
zawsze rozpatruje tylko jeden warunek,
natomiast w instrukcji Select Case
rozpatrywanych może być nieskończenie
wiele warunków i do każdego z nich można przypisać operacje, jakie mają być wykonane w przypadku jego spełnienia.
Instrukcja Select Case
rozpoczyna się od wiersza zawierającego słowo kluczowe
Select Case
oraz wyrażenie, którego wartość będzie przez tę instrukcję
rozpatrywana. W opisywanym przykładzie rozpatrywany jest po prostu argument wejściowy numer
, ale rolę tę,
oprócz pojedynczej zmiennej, równie dobrze może pełnić funkcja lub działanie arytmetyczne.
We wnętrzu instrukcji Select Case
znajdują się bloki opisujące operacje, jakie
mają zostać wykonane dla poszczególnych wartości wyrażenia bazowego. Tak jak wcześniej wspomniano, każdy blok jest jakby
oddzielnym warunkiem sprawdzanym przez instrukcję Select Case
.
Blok rozpoczyna się od słowa kluczowego Case i wartości, dla której blok ten ma być
wykonywany. Jako wartość przypisaną do danego bloku można użyć zmiennej, funkcji lub działania arytmetycznego,
jednak w zdecydowanej większości przypadków stosowane są w tej sytuacji po prostu ręcznie wpisane wartości
(tak jak w omawianym przykładzie).
Drugą częścią bloku Case są instrukcje, które mają być wykonane przez makro,
jeżeli przypisany do niego warunek jest spełniony, czyli wyrażenie rozpatrywane przez instrukcję
Select Case
(w przykładzie jest to wartość zmiennej numer
)
jest równe wartości przypisanej do tego bloku (w przykładzie są to numery poszczególnych miesięcy umieszczone po
słowach kluczowych Case ). W powyższym przykładzie dla każego bloku zdefiniowano
tylko jedno polecenie - przypisanie do zmiennej nazwaMiesiaca
nazw poszczególnych miesięcy. Nie
oznacza to jednak, że każdy blok musi ograniczać się tylko do jednej operacji - w rzeczywistości nie ma w tym
zakresie żadnych ograniczeń i każdy blok może zawierać dowolną liczbę operacji.
Każdy blok kończy się wraz z momentem rozpoczęcia następnego bloku, a więc po napotkaniu przez kod kolejnego
słowa kluczowego Case (lub po natrafieniu na zamknięcie całej instrukcji
Select Case
, jeżeli jest to ostatni blok w całej tej instrukcji).
Instrukcja Select Case
kończy się wierszem zamknięcia:
Schemat działania instrukcji Select Case
jest następujący: po natrafieniu
przez kompilator na wiersz otwarcia instrukcji Select Case
, wyliczana jest
aktualna wartość określonego w nim wyrażenia (w omawianym przykładzie jest to zmienna numer
, będąca
argumentem wejściowym całej funkcji, więc jej aktualną wartością będzie wartość podana przy wywołaniu tej funkcji).
Następnie kompilator sprawdza kolejno wszystkie bloki opisane we wnętrzu instrukcji
Select Case
i jeżeli stwierdzi, że wartość określona dla któregoś z bloków
jest równa wyliczonej wcześniej wartości wyrażenia bazowego, wykonuje wszystkie polecenia zawarte w tym bloku, a
następnie opuszcza całą instrukcję Select Case
.
Jeżeli więc przykładowo, wywołując funkcję nazwaMiesiaca
, podałeś jako argument numer
liczbę 3, to po wejściu do instrukcji Select Case
kompilator pominie
dwa pierwsze bloki, ponieważ ich wartości nie odpowiadają wartości wyrażenia bazowego, a następnie stwierdzi,
że wartość trzeciego bloku spełnia ten wymóg, wykona więc przewidziane dla tego bloku operacje (czyli przypisanie
do zmiennej nazwaMiesiaca
tekstu marzec), po czym opuści instrukcję
Select Case
nie sprawdzając już pozostałych bloków. Oprócz instrukcji
Select Case
opisywana funkcja nie zawiera już żadnych innych poleceń,
więc jej działanie w tym momencie dobiegnie końca i zwróci ona wartość taką, jaką posiada zmienna
nazwaMiesiaca
(czyli przypisany przed chwilą tekst marzec).
W sytuacji, gdy w pojedynczym bloku Case zawarta jest tylko jedna operacja, cały ten blok
może zostać zwinięty do jednego wiersza. Wówczas po określeniu wartości dla tego bloku, należy wstawić dwukropek, a
następnie wpisać przewidzianą dla tego bloku operację.
Jako przykład mogą tu posłużyć bloki Case w instrukcji
Select Case
z poprzedniego przykładu, gdyż dla każdego z nich była wykonanywana
tylko operacja przypisania odpowiedniej nazwy miesiąca do zmiennej nazwaMiesiaca
. Cały poprzedni przykład
mógłby więc równie dobrze wyglądać tak:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Function nazwaMiesiaca(numer As Integer) As String
Select Case numer
Case 1: nazwaMiesiaca = "styczeń"
Case 2: nazwaMiesiaca = "luty"
Case 3: nazwaMiesiaca = "marzec"
Case 4: nazwaMiesiaca = "kwiecień"
Case 5: nazwaMiesiaca = "maj"
Case 6: nazwaMiesiaca = "czerwiec"
Case 7: nazwaMiesiaca = "lipiec"
Case 8: nazwaMiesiaca = "sierpień"
Case 9: nazwaMiesiaca = "wrzesień"
Case 10: nazwaMiesiaca = "październik"
Case 11: nazwaMiesiaca = "listopad"
Case 12: nazwaMiesiaca = "grudzień"
End Select
End Function
Łączenie kilku wartości w pojedynczym bloku Case
Często zdarza się, że operacje wykonywane przez kilka bloków instrukcji Select Case
są dokładnie takie same. Przykładem takiej sytuacji jest poniższa funkcja zwracająca cenę wynajmu miejsca w hotelu w
zależności od miesiąca.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Function cenaWynajmu(miesiac As Integer) As Integer
Select Case miesiac
Case 1: cenaWynajmu = 40
Case 2: cenaWynajmu = 40
Case 3: cenaWynajmu = 40
Case 4: cenaWynajmu = 55
Case 5: cenaWynajmu = 55
Case 6: cenaWynajmu = 70
Case 7: cenaWynajmu = 70
Case 8: cenaWynajmu = 70
Case 9: cenaWynajmu = 60
Case 10: cenaWynajmu = 40
Case 11: cenaWynajmu = 40
Case 12: cenaWynajmu = 40
End Select
End Function
Jak widać w ramce z kodem, cena wynajmu zmienia się trzykrotnie w ciągu roku i wynosi 40 zł w okresie od października
do marca, 55 zł w kwietniu i marcu, 70 zł od czerwca do sierpnia oraz 60 zł we wrześniu.
W powyższym kodzie wielokrotnie powtarzane są te same instrukcje (np. cenaWynajmu = 40
), co powinno być
ograniczone do absolutnego minimum. Na szczęście w tej sytuacji język VBA umożliwia wyeliminowanie tych powtórzeń, a
tym samym znaczne skrócenie całego kodu, poprzez umieszczenie w tym samym bloku Case
kilku wartości, dla których wykonywany ma być taki sam zestaw poleceń.
Poniżej przedstawiono zmodyfikowaną postać funkcji cenaWynajmu
, w której znajdują się już tylko 4 bloki
Case , za to większość z nich obowiązuje równocześnie dla kilku wartości wyrażenia
bazowego.
1
2
3
4
5
6
7
8
Function cenaWynajmu(miesiac As Integer) As Integer
Select Case miesiac
Case 1, 2, 3, 10, 11, 12: cenaWynajmu = 40
Case 4, 5: cenaWynajmu = 55
Case 6, 7, 8: cenaWynajmu = 70
Case 9: cenaWynajmu = 60
End Select
End Function
W obecnej postaci kodu, przy niektórych słowach kluczowych Case wymienionych jest kilka wartości,
oddzielonych od siebie przecinkami. Kompilator sprawdzając teraz, czy poszczególne bloki powinny być wykonane, bierze pod
uwagę wszystkie wartości przypisane do danego bloku. Jeżeli którakolwiek z tych wartości jest równa wartości wyrażenia
bazowego, wykonane zostają operacje przewidziane dla tego bloku Case.
Nawet jeżeli jakaś wartość zostanie przypisana równocześnie do dwóch lub więcej bloków Case,
tak naprawdę będzie obowiązywała tylko dla pierwszego z nich. Dzieje się tak, ponieważ po natrafieniu na blok zawierający
wartość wyrażenia bazowego, kompilator wykonuje operacje przewidziane dla tego bloku, a następnie opuszcza całą
konstrukcję Select Case
, nie sprawdzając już pozostałych bloków.
Przykładowo w poniższym zapisie:
1
2
3
4
5
6
Sub Makro(numer As Integer)
Select Case numer
Case 1, 2, 3: Cells(1,1) = "liczba mniejsza od 4"
Case 3, 4, 5: Cells(2,1) = "liczba większa od 2"
End Select
End Sub
nawet jeżeli argument wejściowy numer
będzie wynosił 3, wykonana zostanie tylko operacja przewidziana
dla pierwszego bloku, mimo że dla wyrażenia bazowego równego 3 warunek zawarty w drugim bloku również byłby spełniony.
Z uwagi na opisany w powyższej ramce schemat działania kodu w instrukcjach Select Case
zawsze najlepiej jest umieszczać bloki Case w kolejności od najbardziej do najmniej
prawdopodobnego.
Załóżmy przykładowo, że funkcja cenaWynajmu
w zdecydowanej większości jest wywoływana, aby sprawdzić cenę pokoju
dla miesięcy wakacyjnych, znacznie rzadziej dla miesięcy wiosennych oraz września, a już zupełnie rzadko dla pozostałych
okresów roku. W takiej sytuacji warto jest przerobić ją do następującej postaci:
1
2
3
4
5
6
7
8
Function cenaWynajmu(miesiac As Integer) As Integer
Select Case miesiac
Case 6, 7, 8: cenaWynajmu = 70
Case 4, 5: cenaWynajmu = 55
Case 9: cenaWynajmu = 60
Case 1, 2, 3, 10, 11, 12: cenaWynajmu = 40
End Select
End Function
Jedyna różnica pomiędzy obecną, a poprzednią postacią funkcji polega na innej kolejności bloków
Case wewnątrz instrukcji Select Case
. Zauważ, że w
obecnej postaci funkcji, jeżeli zapytanie dotyczy któregoś z miesięcy wakacyjnych (a poczynione zostało założenie,
że takie zapytania stanowią zdecydowaną większość), kompilator już przy pierwszym bloku Case
stwierdzi, że jest on spełniony, wykona przypisane do niego operacje i opuści instrukcję Select Case
nie marnując czasu na sprawdzanie pozostałych bloków. W poprzedniej wersji funkcji, zanim kompilator dotarł do bloku
opisującego miesiące wakacyjne, musiał jeszcze wcześniej sprawdzić dwa inne bloki.
Oczywiście w sytuacjach, kiedy jako argument miesiac
podana będzie np. liczba 2, to funkcja w tej postaci
zadziała minimalnie wolniej niż poprzednio. Ale skoro, jak wcześniej ustalono, zapytania takie stanowią jedynie
niewielką część wszystkich zapytań, to korzyści ze skrócenia czasu wykonania funkcji dla miesięcy wakacyjnych
znacznie przewyższą straty wynikające z jego wydłużenia dla pozostałych sytuacji.
Zawsze warto jest więc poświęcić trochę czasu na zastanowienie się, które bloki Case
będą najczęściej spełnione i umieszczenie ich na samej górze instrukcji Select Case
.
Należy w tym miejscu omówić jeszcze jedną właściwość instrukcji Select Case
,
a mianowicie wykonywanie jakichś operacji w sytuacji, gdy żaden z bloków nie został spełniony (czyli odpowiednik sekcji
Else
w zwykłej instrukcji warunkowej
If ... Then
).
Załóżmy, że omawiany w poprzednim przykładzie rozkład ceny wynajmu został zmieniony i teraz cena w czerwcu wynosi 65 zł,
w lipcu - 70 zł, w sierpniu - 75 zł, a we wszystkich pozostałych miesiącach - 50 zł. Oczywiście w takiej sytuacji
również należy zastosować instrukcję Select Case
, a nie
If ... Then
, ponieważ w tym drugim przypadku konieczne byłoby zagnieżdżenie
w sobie trzech warunków.
Kod funkcji cenaWynajmu
wyglądałby więc teraz tak:
1
2
3
4
5
6
7
8
Function cenaWynajmu(miesiac As Integer) As Integer
Select Case miesiac
Case 1, 2, 3, 4, 5, 9, 10, 11, 12: cenaWynajmu = 50
Case 6: cenaWynajmu = 65
Case 7: cenaWynajmu = 70
Case 8: cenaWynajmu = 75
End Select
End Function
Zauważ jednak, że w pierwszym bloku Case wypisanych jest aż 9 wartości, a dodatkowo są to
wszystkie możliwe wartości jakie może przyjąć argument miesiac
oprócz wartości opisanych w pozostałych
blokach (ponieważ numer miesiąca może być tylko liczbą naturalną z zakresu 1-12).
W takiej sytuacji wygodnym rozwiązaniem jest wykorzystanie bloku Case Else.
Blok Case Else jest odpowiednikiem bloku Else
w zwykłej instrukcji warunkowej i określa operacje do wykonania w przypadku niespełnienia żadnego ze
zdefiniowanych warunków.
Funkcja cenaWynajmu
po umieszczeniu w niej bloku Case Else wyglądałaby tak,
jak poniżej:
1
2
3
4
5
6
7
8
Function cenaWynajmu(miesiac As Integer) As Integer
Select Case miesiac
Case 6: cenaWynajmu = 65
Case 7: cenaWynajmu = 70
Case 8: cenaWynajmu = 75
Case Else: cenaWynajmu = 50
End Select
End Function
Teraz, gdy w instrukcji Select Case
znajduje się
blok Case Else, schemat postępowania kodu w tej instrukcji wygląda
następująco: kompilator sprawdza po kolei wszystkie bloki zawarte w instrukcji
Select Case
i jeżeli wartość przypisana do któregoś z bloku odpowiada wartości
wyrażenia bazowego to wykonuje operacje przewidziane dla tego bloku i opuszcza instrukcję
Select Case
. Jeżeli natomiast żaden z bloków nie posiada wartości równej
wyrażeniu bazowemu, to po dotarciu do bloku Case Else kompilator wykonuje czynności
opisane w tym bloku, niezależnie od tego jaka jest wartość wyrażenia bazowego.
Jeżeli więc miesiąc podany jako argument przy wywoływaniu powyższej funkcji będzie pochodził z zakresu wrzesień-maj,
to w instrukcji Select Case
ominięte zostaną trzy pierwsze bloki i po
dotarciu kodu do bloku Case Else wykonane zostaną operacje przewidziane dla tego bloku,
a więc przypisanie do zmiennej cenaWynajmu
wartości 50.
Blok Case Else musi być ostatnim blokiem w instrukcji
Select Case
.
Jeżeli po bloku Case Else zostanie umieszczony jeszcze jakiś inny blok, przy próbie
uruchomienia makra zostanie wyświetlony komunikat Compile error: Case without Select Case.
Wykorzystanie zakresów w blokach Case
Zdarzają się sytuacje, że nawet możliwość umieszczenia kilku wyrażeń w jednym bloku Case
nie wystarcza, aby w pełni opisać wszystkie wartości, jakie może przyjąć zmienna rozpatrywana przez instrukcję
Select Case
.
Za doskonały przykład może tu posłużyć funkcja obliczająca wysokość podatku naliczanego wg skali progresywnej
(przy obowiązujących obecnie w Polsce dwóch progach podatkowych nie byłoby potrzeby stosowania instrukcji
Select Case
, ponieważ świetnie nadaje się do tego celu zwykła instrukcja
warunkowa If ... Then
; dlatego na potrzeby przykładu załóżmy, że obowiązują
trzy progi podatkowe: 20%, 30% i 40% osiągane odpowiednio przy dochodach: 0 - 40 000, 40 000 - 80 000, ponad 80 000).
Oczywiście niemożliwością byłoby ręczne wypisanie wszystkich możliwych wartości, przy których podatnik należy przykładowo
do drugiego progu, gdyż zapis taki musiałby wyglądać mniej więcej tak:
Case 40000.01, 40000.02, 40000.03, 40000.04 ... 'itd.
Trzeba byłoby w ten sposób wypisać wszystkie liczby, aż do osiągnięcia górnego pułapu tego progu, czyli kwoty 80 000
(na domiar złego trzeba byłoby poczynić założenie, że przy wywoływaniu tej funkcji argument określający wysokość pensji
brutto nie zostanie podany z trzema lub więcej miejscami po przecinku).
Ratunkiem jest w tej sytuacji kolejna bardzo przydatna właściwość instrukcji Select Case
- możliwość opisania w bloku Case zakresu wartości.
Poniżej znajduje się schemat funkcji wyliczającej podatek, w którym do zdefiniowania poszczególnych bloków instrukcji
Select Case
wykorzystano zakresy liczb:
1
2
3
4
5
6
7
8
9
Function podatekDochodowy(pensjaBrutto As Single) As Single
Select Case pensjaBrutto
Case Is < 40000: podatekDochodowy = pensjaBrutto * 0.2
Case Is < 80000
podatekDochodowy = 8000 + (pensjaBrutto - 40000) * 0.3
Case Else
podatekDochodowy = 20000 + (pensjaBrutto - 80000) * 0.4
End Select
End Function
Zwróć uwagę, że każdy z zakresów opisujących poszczególne bloki jest ograniczony tylko z jednej strony. W przypadku
pierwszego bloku nie ma w tym nic dziwnego, ponieważ ma on być wykonywany dla wartości pensji brutto mniejszych od
40 000, więc jednostronne ograniczenie zakresu (Is < 40000
) jest jak najbardziej wskazane.
Drugi blok ma być jednak wykonywany dla pensji brutto z przedziału 40 000 - 80 000, natomiast,
jak widzisz w kodzie, jedyne ograniczenie nałożone na jego wartości jest takie, że muszą być one mniejsze niż
80 000. Czy oznacza to, że blok ten może zostać wykonany także dla wartości mniejszych niż 40 000?
Oczywiście taka sytuacja nigdy się nie wydarzy, a wynika to z opisywanego wcześniej schematu zachowania aplikacji
po natrafieniu w kodzie na instrukcję Select Case
. Jeżeli argument
pensjaBrutto
będzie mniejszy niż 40 000 to już pierwszy blok (Case Is < 40000
)
będzie spełniony i po jego wykonaniu kompilator opuści instrukcję Select Case
w ogóle nie sprawdzając czy spełnione są kolejne bloki. Aby więc wykonywanie kodu w ogóle dotarło do drugiego
bloku, zmienna pensjaBrutto
nie może być mniejsza niż 40 000.
Jak więc widzisz, za jedno z ograniczeń zakresu przypisanego do bloku Case
mogą posłużyć zakresy zdefiniowane dla poprzedzających go bloków, tak jak ma to miejsce w powyższym przykładzie,
gdzie rolę dolnej granicy zakresu wartości dla drugiego bloku (Case Is < 80000)
pełni zakres przypisany
do pierwszego bloku.
W ostatnim bloku Case nie ma już potrzeby szczegółowego opisywania wartości, ponieważ ma
on być wykonywany dla wszystkich pozostałych wartości pensji brutto, dzięki czemu można skorzystać z polecenia
Case Else (oczywiście zapis Case Is >= 80 000
również byłby poprawny,
jednak użyty w przykładzie zapis Case Else jest wygodniejszy w użyciu).
Ogólny zapis bloku Case z zakresem wartości ograniczonym jednostronnie przedstawia się
następująco:
Case Is > limit
Case Is >= limit
Case Is < limit
Case Is <= limit
Charakterystycznym elementem bloku z jednostronnym zakresem jest słowo kluczowe Is występujące
pomiędzy poleceniem Case, a opisem limitu. Jeżeli jednak przy definiowaniu jakiegoś bloku
zapomnisz wpisać tego słowa, a równocześnie użyjesz znaku mniejszości (<) lub większości (>), edytor VBA domyśli się,
że chcesz określić wartośc za pomocą jednostronnego zakresu i automatycznie doda w odpowiednim miejscu słowo kluczowe
Is.
Instrukcja Select Case
umożliwia także wykorzystanie w blokach
Case zakresów ograniczonych z obu stron.
Aby przedstawić wykorzystanie tego typu zakresów w instrukcji Select Case
jeszcze raz zostanie użyta funkcja cenaWynajmu
, zwracająca koszt wynajmu miejsca w hotelu. Tym razem
jednak, argumentem podawanym przy wywoływaniu funkcji jest data dzienna, a nie jak poprzednio numer miesiąca. Dzięki
temu można bardziej szczegółowo opisać zmianę ceny miejsca hotelowego i wziąć pod uwagę terminy, w których powinna
być ona wyższa, np. długie weekendy (dla uproszczenia funkcja zwraca tylko ceny na rok 2011).
Funkcja cenaWynajmu
wykorzystująca w blokach Case zakresy danych przedstawia
się następująco:
1
2
3
4
5
6
7
8
9
10
Function cenaWynajmu(data As Date) As Integer
Select Case data
Case #2011-01-01# To #2011-04-28#: cenaWynajmu = 40
Case #2011-04-29# To #2011-05-03#: cenaWynajmu = 70
Case #2011-05-04# To #2011-06-16#: cenaWynajmu = 55
Case #2011-06-17# To #2011-08-28#: cenaWynajmu = 70
Case #2011-08-29# To #2011-10-02#: cenaWynajmu = 55
Case #2011-10-03# To #2011-12-31#: cenaWynajmu = 40
End Select
End Function
Ogólny zapis bloku Case z dwustronnie ograniczonym zakresem wartości wygląda następująco:
gdzie x
to dolna granica tego zakresu, a y
- górna. Bardzo istotne jest zachowanie kolejności
dolnego i górnego limitu, ponieważ w sytuacji gdy najpierw umieścisz wyższą wartość, a potem niższą
(np. Case 20 To 10
), kompilator
potraktuje to jako pusty zbiór i blok ten nigdy nie zostanie wykonany.
Przypisując do bloku Case zakresy również możesz korzystać z możliwości umieszczania w
pojedynczym bloku kilku wyrażeń.
Powyższa funkcja cenaWynajmu
zawiera przykładowo aż 6 bloków Case, ale tak
naprawdę wykonują one na przemian 3 operacje - przypisanie do funkcji wartości 40 zł, 55 zł lub 70 zł. Nie ma więc
przeszkód, aby połączyć ze sobą bloki wykonujące te same operacje:
1
2
3
4
5
6
7
8
9
10
Function cenaWynajmu(data As Date) As Integer
Select Case data
Case #2011-01-01# To #2011-04-28#,
#2011-10-03# To #2011-12-29#
cenaWynajmu = 40
Case #2011-04-29# To #2011-05-03#,
#2011-06-17# To #2011-08-28#
cenaWynajmu = 70
Case #2011-05-04# To #2011-06-16#,
#2011-08-29# To #2011-10-02#
cenaWynajmu = 55
End Select
End Function
Zasada łączenia kilku zakresów w jednym bloku jest dokładnie taka sama jak w przypadku łączenia pojedynczych wartości -
wystarczy po prostu wymienić po słowie kluczowym Case wszystkie obowiązujące dla tego bloku
zakresy oddzielając je od siebie przecinkami.
Nie ma też żadnych przeszkód, aby w jednym bloku wymienić zarówno zakresy, jak i pojedyncze wartości. Jeżeli przykładowo
do pierwszego bloku w powyższej funkcji chciałbyć dodać jeszcze datę 14 maja, wystarczyłoby dopisać tę datę do listy
wartości zdefiniowanych dla tego bloku:
Case #2011-01-01# To #2011-04-28#,
#2011-10-03# To #2011-12-29#, #2011-05-14#
Zagnieżdżanie instrukcji Select Case
Instrukcja Select Case
, podobnie jak inne omówione dotychczas instrukcje,
smoże być zagnieżdżana. Zagnieżdżanie instrukcji Select Case
jest bardzo
proste i wymaga po prostu wstawienia w bloku Case , należącym do jednej instrukcji,
kolejnej instrukcji Select Case
.
Przykład makra zawierającego zagnieżdżone instrukcje Select Case
przedstawiono poniżej. Jest to rozbudowana wersja omawianej wcześniej funkcji cenaWynajmu
, która oprócz
daty wynajmu bierze pod uwagę wielkość wynajmowanego pokoju.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function cenaWynajmu(data As Date, ileOsobWPokoju
As Byte) As Integer
Select Case data
Case #2011-01-01# To #2011-04-28#,
#2011-10-03# To #2011-12-29#
Select Case ileOsobWPokoju
Case 2: cenaWynajmu = 46
Case 3: cenaWynajmu = 60
Case 4: cenaWynajmu = 72
End Select
Case #2011-04-29# To #2011-05-03#,
#2011-06-17# To #2011-08-28#
Select Case ileOsobWPokoju
Case 2: cenaWynajmu = 80
Case 3: cenaWynajmu = 99
Case 4: cenaWynajmu = 120
End Select
Case #2011-05-04# To #2011-06-16#,
#2011-08-29# To #2011-10-02#
Select Case ileOsobWPokoju
Case 2: cenaWynajmu = 60
Case 3: cenaWynajmu = 78
Case 4: cenaWynajmu = 92
End Select
End Select
End Function
Funkcja cenaWynajmu
posiada teraz dwa argumenty wejściowe: data
oraz ileOsobWPokoju
.
Wewnątrz funkcji znajduje się instrukcja Select Case
, która rozpatruje podaną przy
wywoływaniu funkcji datę. W każdym z bloków Case znajduje się natomiast kolejna instrukcja
Select Case
, w której rozpatrywanym wyrażeniem jest wartość zmiennej
ileOsobWPokoju
. Dopiero w tej zagnieżdżonej instrukcji w blokach Case
znajdują się konkretne operacje wpływające na wynik funkcji, czyli przypisanie do niej odpowiedniej ceny wynajmu.
Wyliczenia
Często zdarza się, że przy wywoływaniu funkcji lub procedury, oprócz argumentów wejściowych na podstawie których
obliczane będą wyniki, potrzebny jest jeszcze jakiś dodatkowy parametr określający sposób wykonania tej funkcji
lub procedury.
Przykładem takiego dodatkowego parametru jest np. dzień uważany za pierwszy dzień tygodnia podawany przy wywoływaniu
funkcji Weekday
, zwracającej numer dnia tygodnia, lub rodzaj ikony jaka ma się pojawić w oknie
wyświetlanym przez funkcję MsgBox
.
W takim przypadku konieczne jest określenie listy dostępnych wariantów danego parametru, dla których będą zdefiniowane
odpowiadające im operacje w kodzie. Zdefiniować trzeba także spójny system zapisu tych wariantów, tak aby w każdym
miejscu kodu były one tak samo oznaczane i by kompilator nie miał problemu z ich interpretacją (np. dla parametru
oznaczającego dzień uważany za pierwszy dzień tygodnia nie można podawać w jednym miejscu słowa poniedziałek,
a w innym Monday - w każdym miejscu kodu sposób zapisu musi być jednakowy).
Być może na razie brzmi to trochę zawile, ale wszystko powinno stać się dla Ciebie jaśniejsze po zapoznaniu się z
poniższym przykładem.
Wróćmy do funkcji nazwaMiesiaca
analizowanej na początku tej lekcji przy okazji omawiania instrukcji
Select Case
i załóżmy, że funkcja ta ma zostać zmodyfikowana w taki
sposób, aby przy jej wywoływaniu, oprócz argumentu określającego numer miesiąca, dla którego ma być zwrócona
nazwa, podawany był jeszcze drugi argument, określający język, w którym nazwa tego miesiąca ma być zwrócona.
Funkcja będzie umożliwiała uzyskanie nazwy miesiąca w jednym z trzech języków (polskim, angielskim i hiszpańskim),
konieczne będzie więc zastosowanie zagnieżdżonych instrukcji Select Case
-
jedna z tych instrukcji będzie sprawdzała numer miesiąca, a druga język, który podano przy wywoływaniu funkcji.
Jaki w ogóle typ powinien posiadać w tej funkcji argument jezyk
? Na podstawie dotychczas
zdobytej wiedzy, mógłbyś się zastanawiać nad dwiema możliwościami - typem String
lub którymś z typów
liczbowych - niestety, oba te rozwiązania obarczone są wadami, które szerzej opisano poniżej.
Jeżeli argument jezyk
zostanie zdefiniowany jako argument typu String
, pierwsza przeszkoda
pojawia się już przy budowaniu instrukcji Select Case
, określającej w jakim
języku ma być zwrócona nazwa miesiąca.
Jaką wartość należy zdefiniować dla bloku Case, aby kompilator wiedział, że chodzi przykładowo
o język polski? Załóżmy, że dla opisania poszczególnych języków użyłeś nazw polski, angielski i hiszpański,
a cała funkcja wygląda tak (dla skrócenia kodu w każdym języku zapisano tylko 6 pierwszy miesięcy):
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
Function nazwaMiesiaca(numer As Integer, jezyk As String) As String
Select Case jezyk
Case "polski"
Select Case numer
Case 1: nazwaMiesiaca = "styczeń"
Case 2: nazwaMiesiaca = "luty"
Case 3: nazwaMiesiaca = "marzec"
Case 4: nazwaMiesiaca = "kwiecień"
Case 5: nazwaMiesiaca = "maj"
Case 6: nazwaMiesiaca = "czerwiec"
End Select
Case "angielski"
Select Case numer
Case 1: nazwaMiesiaca = "January"
Case 2: nazwaMiesiaca = "February"
Case 3: nazwaMiesiaca = "March"
Case 4: nazwaMiesiaca = "April"
Case 5: nazwaMiesiaca = "May"
Case 6: nazwaMiesiaca = "June"
End Select
Case "hiszpański"
Select Case numer
Case 1: nazwaMiesiaca = "enero"
Case 2: nazwaMiesiaca = "febrero"
Case 3: nazwaMiesiaca = "marzo"
Case 4: nazwaMiesiaca = "abril"
Case 5: nazwaMiesiaca = "mayo"
Case 6: nazwaMiesiaca = "junio"
End Select
End Select
End Function
Budowa oraz schemat działania tej funkcji są bardzo proste i, jeżeli zapoznałeś się z podrozdziałem dotyczącym
zagnieżdżania
instrukcji Select Case
, ich zrozumienie nie powinno przysporzyć Ci
żadnych kłopotów. Funkcja składa się z instrukcji Select Case
, zawierającej
trzy bloki - każdy opisujący jeden z języków. W każdym z tych bloków zagnieżdżona jest kolejna instrukcja
Select Case
, która zawiera z kolei bloki z poszczególnymi
numerami miesięcy.
Kompilator sprawdza więc najpierw który język został podany przy wywołaniu funkcji, a następnie, wewnątrz bloku
przeznaczonego dla tego języka, wyszukuje podanego w argumencie numeru miesiąca i przypisuje do wyniku funkcji
odpowiednią nazwę miesiąca.
Zauważ, że aby kompilator rozpoznał, jaki język masz na myśli wywołując tę funkcję, musisz podać jego nazwę dokładnie
w takiej postaci, w jakiej określiłeś ją w odpowiednim bloku Case . Jeżeli więc chcesz
przykładowo wyświetlić nazwę któregoś miesiąca po hiszpańsku, jako argument jezyk
musisz podać wyraz
hiszpański, a nie hiszpanski, ESP czy jeszcze jakąś inną formę. Oczywiście bezpośrednio po
utworzeniu tej funkcji będziesz pamiętał o tej zasadzie i nie będzie problemów z jej prawidłowym wywołaniem
(aczkolwiek nawet wtedy może się przytrafić jakaś literówka, która spowoduje zwrócenie błędnej wartości).
Wyobraź sobie teraz jednak, że po kilku tygodniach w aplikacji korzystającej z tej funkcji trzeba coś dodać lub
poprawić, więc po długiej przerwie ponownie musisz zajrzeć do kodu tego makra (lub, co gorsza, musi do niego
zajrzeć ktoś inny, kto nigdy wcześniej nie widział go na oczy). Po kilku tygodniach prawdopodobnie nie będziesz
już pamiętał czy do bloku Case , opisującego język polski, przypisałeś tekst
polski czy też może było to pol lub PL. Być może nie pamiętałbyś już nawet, jakie języki
są w ogóle dostępne w funkcji nazwaMiesiaca
.
Pozostaje Ci więc albo odszukanie tej funkcji w kodzie i przeanalizowanie jej budowy, albo zgadywanie, jaka nazwa
została zastosowana do zidentyfikowania bloku Case zawierającego polskie nazwy
miesięcy. Jeżeli jednak użyjesz nieprawidłowej nazwy i wywołasz funkcję przykładowo w takiej postaci:
kompilator w żaden sposób nie domyśli się, że chcesz w ten sposób zwrócić polską nazwę miesiąca, ponieważ do żadnego
bloku Case w funkcji nazwaMiesiaca
nie przypisano wartości pl.
Wynikiem tej funkcji przy takich argumentach wejściowych byłby więc pusty ciąg znaków.
Oczywiście, jak pamiętasz z podrozdziału poświęconego rozbudowanym blokom Case , do pojedynczego bloku można
przypisać kilka wartości, zwiększając tym samym prawdopodobieństwo późniejszego trafienia właściwej nazwy, np.
Case "polski", "pol", "pl", "język polski", "Polish"
Nigdy nie ma jednak gwarancji, że wypiszesz wszystkie wartości, które przyjdą do głowy innym osobom korzystającym z tej
funkcji lub Tobie samemu podczas jej późniejszego stosowania. Właściwie to jest niemal pewne, że prędzej czy później
ktoś użyje wartości, której w tym bloku Case nie uwzględniono.
Jeszcze gorszym pomysłem wydaje się być zastosowanie liczbowego typu zmiennej do określania, w jakim języku ma być
zwrócona nazwa miesiąca. W tym przypadku trzeba byłoby najpierw przypisać do każdego z dostępnych języków jakąś liczbę,
a potem stosować tę numerację przy definiowaniu poszczególnych bloków w instrukcji Select Case
oraz przy późniejszym wywoływaniu tej funkcji.
Takie rozwiązanie jest jednak bardzo niewygodne i podatne na błędy, gdyż na dłuższą metę nie sposób zapamiętać jaka liczba
została przypisana do każdego z języków, tym bardziej, jeżeli w aplikacji znajdowałoby się więcej tego typu parametrów.
Wszystkich niedogodności związanych z korzystaniem w podobnych sytuacjach ze zmiennych tekstowych lub liczbowych
pozbawione są natomiast wyliczenia.
Wyliczenie, zwane też enumeracją, jest zestawem dopuszczalnych wartości, jakie można przypisać do jakiegoś parametru.
W omawianym przykładzie takim parametrem jest język, a lista dostępnych wartości składa się z trzech pozycji: języka
polskiego, angielskiego i hiszpańskiego.
Postać ogólna wyliczenia wygląda następująco:
Enum Nazwa
wartosc1 [=liczba]
wartosc2 [=liczba]
'(...)
wartoscN [=liczba]
End Enum
Nazwa
powinna jak najdokładniej określać parametr opisywany przez to wyliczenie. Możesz ustalić sobie także
jakiś skrót, który będzie poprzedzał wszystkie deklarowane w kodzie wyliczenia, tak aby potem w trakcie pisania makr
móc szybko przeglądać ich listę (np. enumNazwaWyliczenia
). Przykładowo, wszystkie wyliczenia fabrycznie
zaimplementowane w VBA poprzedzone są literami Vb, dzięki czemu korzystając z autopodpowiedzi, po wpisaniu
tych dwóch liter widzisz zgromadzoną w jednym miejscu listę wszystkich wbudowanych wyliczeń, tak jak to widać na
poniższym rysunku (zwróć przy okazji uwagę na ikonę symbolizującą wyliczenie, pozwalającą z łatwością rozpoznać,
które elementy znajdujące się na liście autopodpowiedzi są wyliczeniami).
We wnętrzu wyliczenia powinny zostać wypisane wszystkie wartości dostępne dla opisywanego przez to wyliczenie parametru.
W każdej linijce powinna zostać umieszczona tylko nazwa opisująca konkretny wariant parametru bez żadnych poprzedzających
ją słów kluczowych. Do każdej wartości można ewentualnie przypisać jakąś wartość liczbową, co czasami może okazać się
bardzo przydatne (przykłady takich sytuacji zostaną jednak przedstawione w dalszej części kursu).
Przy nadawaniu nazw wartościom wyliczenia obowiązują te same reguły, co przy
nadawaniu nazw funkcjom i zmiennym. Dodatkowe zastrzeżenie jest takie,
że w ramach jednego wyliczenia nie mogą znaleźć się dwie wartości o identycznych nazwach.
Blok definiujący wyliczenie musi być umieszczony u góry modułu, jeszcze przed rozpoczęciem jakiejkolwiek funkcji lub procedury.
Umieszczenie bloku z wyliczeniem za jakąś funkcją lub procedurą spowoduje, że przy próbie uruchomienia makra zostanie
wyświetlony błąd: Compile error: Only comments may appear after End Sub, End Function or End Property.
Wyliczenie, które będzie użyte w analizowanej funkcji nazwaMiesiaca
powinno wyglądać następująco:
1
2
3
4
5
Enum Jezyk
polski
angielski
hiszpanski
End Enum
co oznacza, że opisuje ono języki i udostępnia trzy warianty tego parametru: język polski, angielski i hiszpański.
Wiesz już jak stworzyć w kodzie blok wyliczeniowy i zdefiniować dostępne dla niego wartości, najwyższy więc czas,
abyś dowiedział się, jak można to wyliczenie wykorzystać podczas pisania programu.
Każde wyliczenie jest traktowane przez edytor VBA jak dodatkowy typ danych. Oznacza to, że od tego momentu możesz
deklarować zmienne jako typ Jezyk
. Zauważ, że typ Jezyk
pojawia się też od teraz na
rozwijanej liście dostępnych typów zmiennych (co pokazano na poniższym rysunku):
Tak jak w przypadku każdego innego typu zmiennych, zakres danych przyjmowanych przez typ Jezyk
nie jest
dowolny i ma pewne ograniczenia. Jak się zapewne domyślasz, każdy wyliczeniowy typ danych może przyjmować tylko takie
wartości, jakie zostały zdefiniowane w bloku opisującym to wyliczenie. W przypadku typu Jezyk
zakres
przyjmowanych przez zmienne wartości będzie więc ograniczony do trzech wartości: polski
,
angielski
oraz hiszpanski
.
Pamiętaj, że nazwy wyliczeniowe wypisywane są w kodzie bez cudzysłowów, ponieważ nie są one tekstami.
Teraz można zmodyfikować funkcję nazwaMiesiaca
tak, aby zamiast zmiennej tekstowej wykorzystywała do określania
języka zmienną typu wyliczeniowego Jezyk
. Nowa postać funkcji przedstawia się następująco (zmienione fragmentu
kodu zostały oznaczone na czerwono):
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
Function nazwaMiesiaca(numer As Integer, jezyk As Jezyk)
As String
Select Case jezyk
Case polski
Select Case numer
Case 1: nazwaMiesiaca = "styczeń"
Case 2: nazwaMiesiaca = "luty"
Case 3: nazwaMiesiaca = "marzec"
Case 4: nazwaMiesiaca = "kwiecień"
Case 5: nazwaMiesiaca = "maj"
Case 6: nazwaMiesiaca = "czerwiec"
Case 7: nazwaMiesiaca = "lipiec"
Case 8: nazwaMiesiaca = "sierpień"
Case 9: nazwaMiesiaca = "wrzesień"
Case 10: nazwaMiesiaca = "październik"
Case 11: nazwaMiesiaca = "listopad"
Case 12: nazwaMiesiaca = "grudzień"
End Select
Case angielski
Select Case numer
Case 1: nazwaMiesiaca = "January"
Case 2: nazwaMiesiaca = "February"
Case 3: nazwaMiesiaca = "March"
Case 4: nazwaMiesiaca = "April"
Case 5: nazwaMiesiaca = "May"
Case 6: nazwaMiesiaca = "June"
Case 7: nazwaMiesiaca = "July"
Case 8: nazwaMiesiaca = "August"
Case 9: nazwaMiesiaca = "September"
Case 10: nazwaMiesiaca = "October"
Case 11: nazwaMiesiaca = "November"
Case 12: nazwaMiesiaca = "December"
End Select
Case hiszpanski
Select Case numer
Case 1: nazwaMiesiaca = "enero"
Case 2: nazwaMiesiaca = "febrero"
Case 3: nazwaMiesiaca = "marzo"
Case 4: nazwaMiesiaca = "abril"
Case 5: nazwaMiesiaca = "mayo"
Case 6: nazwaMiesiaca = "junio"
Case 7: nazwaMiesiaca = "julio"
Case 8: nazwaMiesiaca = "agosto"
Case 9: nazwaMiesiaca = "septiembre"
Case 10: nazwaMiesiaca = "octubre"
Case 11: nazwaMiesiaca = "noviembre"
Case 12: nazwaMiesiaca = "diciembre"
End Select
End Select
End Function
W wierszu otwarcia funkcji zmienił się tylko typ danych dla argumentu jezyk
.
Zmieniła się także wartość dla każdego z bloków Case w instrukcji
Select Case
rozpatrującej zmienną jezyk
.
Wcześniej rozpatrywana przez tę instrukcję zmienna jezyk
była zmienną typu tekstowego, dlatego też
do bloków Case przypisane była wartości tekstowe: polski, angielski
oraz hiszpański. Jednak w obecnej postaci funkcji, zmienna jezyk
posiada typ wyliczeniowy
Jezyk
, w związku z czym wartości przypisane do poszczególnych bloków Case
muszą być zgodne z tym typem. Nie mogą więc to być dłużej zmienne tekstowe, ponieważ typ wyliczeniowy Jezyk
(ani żaden inny typ wyliczeniowy) nie obsługuje zmiennych tekstowych. Jedyne wartości dostępne dla tego typu danych
to polski
, angielski
oraz hiszpanski
, dlatego takie właśnie wartości są teraz
zdefiniowane dla bloków Case zamiast poprzednich wartości tekstowych.
Spróbuj teraz wywołać w oknie Immediate gotową już funkcję nazwaMiesiaca
(a właściwie prawie gotową,
bo w jednej z kolejnych lekcji, poświęconej tablicom, zostanie ona jeszcze bardziej udoskonalona).
Zwróć uwagę, że kiedy wpiszesz już numer miesiąca i przejdziesz do określania języka, edytor VBA wyświetli rozwijaną
listę zawierającą wszystkie dostępne warianty tego parametru. Nie ma więc już miejsca na żadną pomyłkę, nie musisz się
też dłużej zastanawiać, jakie języki dostępne są w tej funkcji, a dodatkowo nie musisz wpisywać całej nazwy definiującej
parametr, ponieważ możesz po prostu wybrać go z listy.
Typy wyliczeniowe były już kilkakrotnie stosowane we wcześniejszych lekcjach tego kursu. Należały do nich np. parametry
określające pierwszy dzień tygodnia i tydzień uważany za pierwszy tydzień roku (wykorzystywane we wbudowanych funkcjach
datowych) lub wszystkie parametry podawane dla argumentu Buttons
w funkcji MsgBox
.
Należy jeszcze w tym miejscu wrócić do opisanego w lekcji dziewiątej sposobu odczytywania przycisku wciśniętego
przez użytkownika w oknie MsgBox
.
Z racji tego, że nie znałeś jeszcze typów wyliczeniowych, w omawianym tam przykładzie wciśnięty przycisk był określany
za pomocą zmiennej typu Integer. Teraz nie ma już przeszkód, aby wykorzystać do tego celu
typ wyliczeniowy VbMsgBoxResult
, który jest wbudowanym typem wyliczeniowym przeznaczonym właśnie do
idetyfikacji przycisku wciśniętego przez użytkownika w oknie MsgBox
.
Omawiana w tamtej lekcji procedura
wyswietlanieDaty
może więc przyjąć następującą postać (standardowo zmienione fragmenty kodu oznaczono na
czerwono):
1
2
3
4
5
6
7
8
9
10
Sub wyswietlanieDaty()
Dim przycisk As VbMsgBoxResult
przycisk = MsgBox("Czy chcesz wyświetlić w arkuszu aktualną godzinę?", _
vbYesNo + vbQuestion, "Potwierdzenie")
If przycisk = VbYes Then
Cells(1, 1) = Time
End If
End Sub
Zmienna przycisk
posiada teraz typ VbMsgBoxResult
. Za każdym razem, gdy jest ona
wykorzystywana w kodzie, edytor VBA wyświetla listę wszystkich dostępnych dla niej wartości, dzięki czemu bardzo
łatwo wybrać odpowiednią wartość, a przytoczona w tamtej lekcji tabelka zawierająca liczbowe odpowiedniki
poszczególnych przycisków staje się mało użyteczna.