Tematem tej lekcji będą instrukcje warunkowe. Nauczymy się sterować wykonywaniem programu za pomocą warunku
Przy okazji, zgodnie z obietnicą z poprzedniej lekcji, nauczymy się jak zabezpieczyć aplikację przed wpisaniem przez użytkownika niewłaściwego typu danych w oknie
Lekcja została podzielona na następujące części:
Sterowanie programem za pomocą warunków
Bardzo często zdarza się, że program ma wykonywać jakieś czynności, ale tylko wówczas, gdy spełnione są określone warunki.
Przykłady takich sytuacji wymieniono już w poprzedniej lekcji omawiającej komunikację z użytkownikiem. Jedną z nich było
uzależnienie dalszego wykonywania makra od przycisku, który wcisnął użytkownik, drugą natomiast sprawdzanie, jaką
wartość wpisał użytkownik w oknie InputBox
, i wyświetlenie informacji o nieprawidłowym typie danych,
jeżeli wpisano tekst zamiast liczby.
Poniżej znajduje się makro obliczające pensję netto, w której wartość pensji brutto jest pobierana od użytkownika za
pomocą okna InputBox
. Makro to było omawiane w poprzedniej lekcji i, jak wówczas wspomniano, nie miało
żadnego zabezpieczenia przed wpisaniem przez użytkownika nieprawidłowego typu danych (np. tekstu xyz w miejscu,
gdzie powinna być podana wysokość pensji brutto) - w takiej sytuacji makro po prostu przestawało działać, a na ekranie
ukazywał się wygenerowany przez VBA komunikat z informacją o błędzie Run-time error '13': Type mismatch, co jest
oczywiście zupełnie niezrozumiałe dla końcowego użytkownika.
W poniższym kodzie do makra dodano instrukcję warunkową, która w przypadku podania przez użytkownika nieprawidłowego typu danych wyświetla odpowiedni komunikat (wiersze kodu dodane w tej wersji makra 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
Sub zarobki()
Dim s As String
Dim pensjaBrutto As Long
Dim pensjaNetto As Long
s = InputBox("Podaj wysokość pensji brutto", "Pensja brutto")
If IsNumeric(s) Then
pensjaBrutto = s
pensjaNetto = pensjaPoOpodatkowaniu(pensjaBrutto)
Call MsgBox("Pensja brutto: " & pensjaBrutto & vbCrLf & _
"Pensja netto: " & pensjaNetto, , "Pensja netto")
Else
Call MsgBox("Nieprawidłowa wartość pensji brutto" & _
vbCrLf & "Podana wartość musi być liczbą", _
vbOKOnly + vbExclamation, "Nieprawidłowa wartość")
End If
End Sub
1
2
3
Function pensjaPoOpodatkowaniu(podstawa As Long) As Long
pensjaPoOpodatkowaniu = podstawa - (podstawa * 0.18)
End Function
W sekcji deklaracji zmiennych, obok zmiennych pensjaBrutto
i pensjaNetto
, została jeszcze
zadeklarowana pomocnicza zmienna typu tekstowego s
. W omawianym przykładzie niezbędna jest właśnie zmienna
tekstowa, tak by mogła być do niej przypisana dowolna wartość wprowadzona przez użytkownika w oknie InputBox
.
Wcześniej, kiedy wartość wpisana przez użytkownika była przypisywana bezpośrednio do zmiennej liczbowej
pensjaBrutto
, generowany był błąd w sytuacji, gdy użytkownik wprowadził wartość tekstową zamiast liczby.
W wierszu 6 do zmiennej s
zostaje przypisany wynik działania funkcji
InputBox
, czyli wartość wpisana przez użytkownika. Zmienna s
, jako zmienna typu tekstowego,
może przyjąć każdą wartość nie generując przy tym żadnych błędów.
W wierszu 8 pojawia się wreszcie instrukcja warunkowa, będąca tematem dzisiejszej lekcji.
Postać ogólna instrukcji warunkowej przedstawia się następująco:
1
2
3
4
5
If [warunek] Then
'instrukcje wykonywane, jeżeli warunek jest spełniony
Else
'instrukcje wykonywane, jeżeli warunek nie jest spełniony
End If
1
2
3
4
5
If [warunek] Then
'instrukcje wykonywane, jeżeli warunek jest spełniony
Else
'instrukcje wykonywane, jeżeli warunek nie jest spełniony
End If
Między słowami kluczowymi If
oraz Then
należy wstawić tzw. warunek, czyli działanie,
którego wynikiem będzie wartość logiczna True
lub
False
.
Jeżeli warunek określony w wierszu If ... Then
jest spełniony zostaną
wykonane instrukcje zawarte między linijkami If ... Then
oraz
Else
(oznaczone na powyższym schemacie ogólnym instrukcji warunkowej
zielonym komentarzem), a następnie wykonywanie makra przenosi się do końcowego wiersza instrukcji warunkowej -
End If
(pomijany jest więc blok instrukcji znajdujący się pomiędzy
słowami kluczowymi Else
a End If
,
oznaczony na powyższym schemacie na czerwono).
Analogicznie w sytuacji, gdy warunek zwróci wartość False
- makro pomija
blok instrukcji oznaczony na schemacie na zielono i przeskakuje do bloku poleceń umieszczonego pomiędzy linijkami
Else
oraz End If
(oznaczonego na czerwono), a następnie kontynuuje swoje działanie za instrukcją warunkową.
Najczęściej jako warunki decydujące o dalszych losach wykonywania kodu wykorzystywane są zmienne typu
Boolean
lub funkcje zwracające taki typ danych.
Jak jednak wspomniano w lekcji czwartej, jeżeli zamiast wymaganej
wartości logicznej kompilator natrafi na inny typ danych, próbuje automatycznie przekonwertować tę napotkaną wartość
do wymaganego typu logicznego (tak samo zresztą dzieje się z innymi typami zmiennych). Dzięki tej automatycznej konwersji,
jako warunek instrukcji warunkowej można podstawić również wszystkie liczby, teksty True oraz False, a także
funkcje zwracające te wartości. Dla przypomnienia - jako wartość True
interpretowane są wszystkie liczby różne od 0 oraz tekst True, natomiast tekst False oraz liczba 0
są równoznaczne z wartością logiczną False
.
W związku z powyższym prawidłowe są na przykład takie zapisy:
If 0 Then
(w tym przypadku warunek nie jest spełniony),
If 2 Then
(warunek spełniony),
If -1 Then
(warunek spełniony),
If 0.0132 Then
(warunek spełniony),
If 2 * (4-5) Then
(warunek spełniony),
If Sqr(5) Then
(warunek spełniony),
If "True" Then
(warunek spełniony),
If "False" Then
(warunek nie jest spełniony).
Ale już na przykład zapis If "Prawda" Then
spowoduje wygenerowanie błędu Run-time error '13': Type mismatch.
W powyższym przykładzie warunkiem rozpatrywanym przez wyrażenie If ... Then
jest funkcja IsNumeric
, w której jako argument podano zmienną s
. Jak dowiedziałeś się
w lekcji opisującej funkcje wbudowane funkcja IsNumeric
zwraca wartość
True
, jeżeli argument jest liczbą lub tekstową reprezentacją liczby.
Wartość False
jest natomiast zwracana dla każdej innej wartości argumentu.
Dlatego też, jeżeli użytkownik wpisze w oknie InputBox
tekst nie dający się przełożyć na liczbę
lub pozostawi puste pole, funkcja IsNumeric
zwróci wartość False
i wykonywanie makra zostanie przeniesione do poleceń znajdujących się pomiędzy słowami kluczowymi
Else
a End If
.
W sekcji tej znajduje się tylko jedna instrukcja - wywołanie okna zatytułowanego Nieprawidłowa wartość z ikoną
ostrzeżenia i komunikatem Nieprawidłowa wartość pensji brutto. Podana wartość musi być liczbą.
Jeżeli natomiast użytkownik wpisze w oknie InputBox
wartość liczbową, wartość zmiennej s
będzie
tekstową reprezentacją liczby i funkcja IsNumeric
zwróci wartość True
.
W takiej sytuacji aplikacja będzie kontynuowała swoje działanie wykonując polecenia zawarte w bloku znajdującym się
pomiędzy linią If ... Then
, a słowem kluczowym
Else
. Najpierw do zmiennej pensjaBrutto
zostanie
więc przypisana liczba reprezentowana przez tekst s
(wiersz 9), a następnie
wywoływana będzie funkcja pensjaPoOpodatkowaniu
, w której argumentem jest właśnie ta liczba (wiersz
10). Ostatecznie makro wyświetli końcowy wynik w oknie z komunikatem, przedstawiając
informacje o wysokości podanej przez użytkownika pensji brutto i wyliczonej na tej podstawie pensji netto (wiersze
12-13). Po wykonaniu wszystkich instrukcji znajdujących się w tym bloku, makro ominie blok
przewidziany dla niespełnionego warunku i przejdzie do wiersza End If
zamykającego instrukcji warunkowej (czyli do wiersza 18).
Zagnieżdżanie i zwijanie instrukcji warunkowych
Poniżej znajdziesz kolejny przykład zastosowania instrukcji If ... Then
,
w którym zaprezentowano dwie jej ważne cechy - możliwość zagnieżdżania jednego warunku w drugim oraz zwijanie całej
instrukcji do jednej linijki.
Zaprezentowane makro wymaga najpierw od użytkownika podania liczby, a następnie wyświetla okno z komunikatem czy podana przez niego liczba jest parzysta. Przed sprawdzeniem parzystości liczby, podobnie jak w poprzednim przykładzie, zastosowano oczywiście zweryfikowanie poprawności podanej przez użytkownika wartości, gdyż niemożliwe byłoby sprawdzanie parzystości np. tekstu abc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Sub zarobki()
Dim s As String
Dim opis As String
s = InputBox("Podaj liczbę", "Liczba wejściowa")
If IsNumeric(s) Then
If s Mod 2 Then opis = "nieparzysta" Else opis = "parzysta"
Call MsgBox("Podana przez Ciebie liczba jest " & opis, vbOkOnly)
Else
Call MsgBox("Nieprawidłowa wartość." & _
vbCrLf & "Podana wartość musi być liczbą", _
vbOKOnly + vbExclamation, "Nieprawidłowa wartość")
End If
End Sub
W makrze zadeklarowane są zmienne tekstowe s
oraz opis
.
Do zmiennej s
, podobnie jak w poprzednim przykładzie, przypisana zostanie wartość wprowadzona przez
użytkownika. Zastosowanie w tej sytuacji zmiennej tekstowej ma na celu umożliwienie wpisania dowolnej wartości
bez generowania komunikatów o błędzie w sytuacji, gdy wartość ta nie będzie liczbą.
Zmienna opis
będzie natomiast przechowywać wynik operacji obliczania reszty z dzielenia podanej przez
użytkownika liczby przez 2. Sensowność zastosowania w tej sytuacji zmiennej tekstowej zostanie wyjaśniona w dalszej
części analizy kodu.
W wierszu 5 wyświetlone zostaje okno InputBox
, w którym użytkownik powinien podać
wybraną przez siebie liczbę. Następnie, w wierszu 7, makro sprawdza za pomocą funkcji
IsNumeric
czy podana przez użytkownika wartość jest liczbą, a więc czy można na niej wykonać operację
obliczania reszty z dzielenia.
Jeżeli zmienna s
nie przechowuje wartości liczbowej, wykonywanie makra zostaje przeniesione do wiersza
13 i wyświetlone zostaje ostrzeżenie o nieprawidłowym typie danych.
Jeżeli natomiast wartość podana w oknie InputBox
jest liczbą, makro przechodzi do bloku zadań znajdującego
się pomiędzy wierszem If ... Then
a Else
i zabiera się za sprawdzanie parzystości podanej liczby.
Najciekawszym wierszem omawianej aplikacji jest wiersz 9, zawierajacy instrukcję:
9
If s Mod 2 Then opis = "nieparzysta"
Else opis = "parzysta"
9
If s Mod 2 Then opis = "nieparzysta"
Else opis = "parzysta"
Pierwszy wniosek, jaki nasuwa się na podstawie tej linijki kodu, to fakt, że instrukcje warunkowe
If ... Then
mogą być zagnieżdżane. Jak widzisz, instrukcja
If
znajdująca się w tym wierszu jest zagnieżdżona w instrukcji
If
rozpoczynającej się wiersz wyżej. Jak zobaczysz w dalszych lekcjach,
zagnieżdżanie instrukcji warunkowych jest bardzo powszechną praktyką i nie ma tutaj żadnego ograniczenia jeżeli chodzi
o liczbę poziomów zagnieżdżania i ich skomplikowanie - równie dobrze można byłoby dodać jeszcze instrukcję
If
w bloku wykonywanym w przypadku niespełnienia warunku, w niej jeszcze
jedną instrukcję warunkową itd.
Kolejną rzucającą się w oczy rzeczą jest to, że cała instrukcja warunkowa If ... Then
została umieszczona w jednym wierszu.
Umieszczenie całej instrukcji warunkowej w jednym wierszu jest możliwe tylko w jednej sytuacji: jeżeli czynności wykonywane zarówno w sytuacji spełnienia, jak i nie spełnienia warunku, mogą być opisane w pojedynczej linii kodu.
W opisywanej sytuacji w przypadku spełnienia warunku funkcji wykonywane jest tylko przypisanie tekstu nieparzysta
do zmiennej opis
. Podobnie w przypadku, gdy warunek nie jest spełniony, jedyną wykonywaną przez makro
czynnością jest przypisanie do zmiennej opis
tekstu parzysta.
Dla odmiany instrukcja warunkowa rozpoczynająca się w wierszu 7 nie może zostać zwinięta do
jednego wiersza, ponieważ czynności wykonywane dla spełnionego warunku IsNumeric(s)
obejmują dwie linijki
kodu: zagnieżdżoną pętlę warunkową (wiersz 9) oraz wywołanie okna z komunikatem
(wiersz 10).
Zauważ, że jeśli cała instrukcja warunkowa umieszczona jest w jednej linijce pomijane jest słowo kluczowe
End If
.
Zwijanie instrukcji warunkowej do jednej linijki nie powinno być nadużywane, aby nie wpływać negatywnie na czytelność kodu. Jedyną sytuacją, w której powinno się stosować ten zabieg, jest właśnie zaprezentowana tutaj instrukcja warunkowa, w której dla obu wyników warunku jedynymi operacjami jest przypisanie do jakiejś zmiennej wartości określonej wprost (a nie za pomocą funkcji, gdyż wówczas cały wpis jest zazwyczaj zbyt rozwlekły i nie mieści się na szerokości ekranu).
Dokładniejszego omówienia wymaga też warunek podany dla instrukcji If
wywoływanej w wierszu (9). Zastosowanie znajduje tutaj zasada opisana na początku lekcji,
mówiąca o tym, że warunkiem instrukcji If
może być też operacja matematyczna
albo funkcja, jeżeli jej wynikiem będzie liczba lub teksty True i False. Dla przypomnienia dla tekstu
False oraz liczby 0 warunek przyjmuje wartość False
, natomiast dla
tekstu True oraz każdej innej liczby - warunek jest spełniony.
W tej konkretnej sytuacji warunkiem jest operacja obliczania reszty z dzielenia liczby podanej przez użytkownika
(przechowywanej w zmiennej s
- jest to wprawdzie zmienna tekstowa, ale przy zastosowaniu jej w operacji
Mod
zostaje automatycznie przekonwertowana do liczby całkowitej) przez liczbę 2.
Dla liczb parzystych wynikiem tego działania będzie 0, co jest równoznaczne ze zwróceniem przez warunek wartości
False
.
Resztą z dzielenie liczb nieparzystych przez 2 będzie natomiast 1, a więc warunek umieszczony w sekcji warunkowej
instrukcji If
będzie spełniony i zwróci wartość
True
.
W związku z powyższym - jeżeli dla liczb nieparzystych warunek zwróci wartość True
,
a dla parzystych False
- w bloku opisującym czynności dla spełnionego warunku do
zmiennej opis
należy przypisać tekst nieparzysta, natomiast w bloku dla niespełnionego warunku -
tekst parzysta.
W wierszu 10 wywoływana jest funkcja MsgBox
, która w zależności od wyniku obliczenia
reszty z dzielenia, wyświetla na ekranie okno z komunikatem Podana przez Ciebie liczba jest parzysta lub Podana
przez Ciebie liczba jest nieparzysta.
Warto jeszcze krótko uzasadnić sensowność wykorzystania w tym makrze zmiennej tekstowej opis
.
Gdyby w makrze zabrakło tej zmiennej, zamiast tych dwóch wierszy:
9
10
If s Mod 2 Then opis = "nieparzysta"
Else opis = "parzysta"
Call MsgBox("Podana przez Ciebie liczba jest " & opis, vbOkOnly)
należałoby wstawić poniższy blok instrukcji:
If s Mod 2 Then
Call MsgBox("Podana przez Ciebie liczba jest nieparzysta", vbOkOnly)
Else
Call MsgBox("Podana przez Ciebie liczba jest parzysta", vbOkOnly)
End If
9
10
If s Mod 2 Then opis = "nieparzysta"
Else opis = "parzysta"
Call MsgBox("Podana przez Ciebie liczba jest " & opis, vbOkOnly)
If s Mod 2 Then
Call MsgBox("Podana przez Ciebie liczba jest nieparzysta", vbOkOnly)
Else
Call MsgBox("Podana przez Ciebie liczba jest parzysta", vbOkOnly)
End If
Jedyną zaletą takiego rozwiązania byłoby zmniejszenie liczby zmiennych używanych w aplikacji z dwóch do jednej.
Jednak operacja obliczenia reszty z dzielenia i wyświetlenia komunikatów wydłuża się w takiej sytuacji z dwóch
linijek do pięciu. Ponadto wobec braku zmiennej opis
, dwukrotnie powtórzona jest niemal identyczna
operacja:
Call MsgBox("Podana przez Ciebie liczba jest ...", vbOkOnly)
która w obu przypadkach różni się tylko ostatnim słowem komunikatu, uzależnionym od wyniku operacji
s Mod 2
(jak już zostało podczas tego kursu wielkorotnie wspomniane - każda sytuacja, w której
powtarzany jest taki sam fragment kodu jest niepożądana).
Call MsgBox("Podana przez Ciebie liczba jest ...", vbOkOnly)
W omówionej wersji makra, wykorzystującej dodatkową zmienną tekstową opis
, ostatnie słowo komunikatu
jest przypisywane właśnie do tej zmiennej, a funkcja MsgBox
wywoływana jest z komunikatem będącym
połączeniem tekstu wspólnego dla obu sytuacji: Podana przez Ciebie liczba jest oraz tekstu przechowywanego
w zmiennej opis
(a więc parzysta lub nieparzysta).
Pomijanie bloku Else
Często zdarza się, że instrukcja warunkowa If ... Then
ma wykonywać jakieś
czynności tylko w sytuacji, kiedy warunek jest spełniony, natomiast w przypadku niespełnienia warunku powinna po prostu
przejść do kolejnych poleceń, znajdujących się za instrukcją warunkową (a więc za słowem kluczowym
End If
, które ją zamyka).
W takiej sytuacji można oczywiście pozostawić puste miejsce w bloku, w którym powinny znaleźć się instrukcje do
wykonania w razie niespełnienia warunku, tak jak w poniższym przykładzie:
If x > 0 Then
Call MsgBox("Liczba x jest większa od zera")
Else
End if
If x > 0 Then
Call MsgBox("Liczba x jest większa od zera")
Else
End if
W powyższej instrukcji warunkowej w sytuacji, gdy liczba x
jest większa od zera, zostaje wyświetlona
informacja o treści Liczba x jest większa od zera. Natomiast dla liczb niedodatnich, wykonywanie kodu
przenoszone jest do bloku pomiędzy słowami kluczowymi Else
a End If
.
Nie napotyka tam jednak żadnych poleceń, więc przechodzi od razu do polecenia
End If
, zamykającego całą instrukcję warunkową.
W takim wypadku jak powyżej słowo kluczowe Else
może, a nawet powinno być pominięte, a cały zapis
powinien wyglądać tak jak poniżej:
If x > 0 Then
Call MsgBox("Liczba x jest większa od zera")
End If
If x > 0 Then
Call MsgBox("Liczba x jest większa od zera")
End If
W takiej sytuacji można też zastosować opisane wcześniej zwijanie wierszy, a więc cała powyższa konstrukcja
równie dobrze mogłaby wyglądać tak:
If x > 0 Then Call MsgBox("Liczba x jest większa od zera")
If x > 0 Then Call MsgBox("Liczba x jest większa od zera")
Niedopuszczalna jest natomiast sytuacja, w której to słowo kluczowe Then
zostałoby
pominięte. Słowo kluczowe Then
zawsze musi pojawić się w tej samej linijce kodu,
w której znajduje się słowo If
oraz warunek (oczywiście można rozbić ten wiersz za pomocą operatora
_
). Zresztą w przypadku pominięcia słowa kluczowego Then
lub
umieszczenia go w niewłaściwej linii kodu, edytor VBA podświetli całą tę linię na czerwono i nie dopuści do uruchomienia
makra.
W instrukcji warunkowej, która ma wykonywać jakieś polecenia tylko w razie niespełnienia warunku, po prostu nie umieszcza
się żadnego kodu w bloku pomiędzy linijką If ... Then
a
Else
, nie można jednak w takiej sytuacji pomijać żadnego elementu całej konstrukcji:
If x > 0 Then
Else
Call MsgBox("Liczba x jest mniejsza od zera")
End If
Zamiast tego można jednak odwrócić wynik warunku za pomocą operatora Not()
(operatory logiczne wykorzystywane w instrukcjach warunkowych zostały omówione
w kolejnym podrozdziale tej lekcji). Wówczas to, co dotychczas było prawdą, stanie się fałszem i na odwrót, a
operacje wykonywane dotychczas przy niespełnionym warunku będą teraz wykonywane przy jego spełnieniu:
If Not(x >= 0) Then
Call MsgBox("Liczba x jest mniejsza od zera")
Else
End If
W powyższym kodzie można się już pozbyć słowa kluczowego Else
,
a dodatkowo zwinąć całą instrukcję warunkową do jednej linijki:
If Not(x >= 0) Then Call MsgBox("Liczba x jest mniejsza od zera")
Operatory logiczne
Określając warunek dla instrukcji If ... Then
można konstruować rozbudowane
warunki, składające się z kilku prostych warunków połączonych ze sobą za pomocą operatorów logicznych.
Kilka z operatorów logicznych dostępnych w VBA ma swoje odpowiedniki wśród funkcji arkuszowych, więc możesz je już
znać (np. LUB()
czy ORAZ()
). Są one często wykorzystywane do budowania warunków dla arkuszowej
funkcji warunkowej =JEŻELI()
).
Poniższa lista zawiera wykaz wszystkich operatorów logicznych dostępnych w VBA. Klikając w nazwę poszczególnych
operatorów przeniesiesz się do ich szczegółowego opisu z przykładami zastosowania.
Operator negacji (Not)
Operator Not
stosowany jest wraz z pojedynczym wyrażeniem i odwraca jego
wartość.
Operator Not
działa identycznie jak funkcja arkuszowa =NIE
.
Jeżeli wynikiem jakiegoś wyrażenia jest True
to dodanie przed nim operatora
Not
zmieni jego wartość na False
i odwrotnie.
Poniżej znajduje się kilka przykładów zastosowania operatora Not
w instrukcjach
If ... Then
.
If Not(x = 0) Then
Sam warunek x = 0
byłby spełniony dla zera, natomiast dla każdej innej liczby zwróciłby wartość
False
. Jednak dodanie przed nim operatora
Not
sprawia, że sytuacja odwraca się o 180 stopni.
Teraz w przypadku, gdy zmienna x
ma wartość 0 całe wyrażenie warunkowe jest fałszywe, a więc wykonywane
będą operacje umieszczone w bloku zawartym między słowami Else
a
End If
.
Jeżeli zmienna x
będzie natomiast miała wartość różną od 0, warunek będzie spełniony i wykonane zostaną
polecenia znajdujące się pomiędzy słowami Then
a
Else
.
If Not(2 > 1) Then
W tej sytuacji instrukcja If
zawsze będzie wykonywała operacje przewidziane dla niespełnionego warunku.
Wyrażenie 2 > 1
zawsze jest prawdziwe, jednak operator Not
zamienia
jego wartość na False
.
If Not(Len(nazwa)) Then
Zmienna nazwa
musi być zmienną tekstową, ponieważ tylko taki typ danych jest przyjmowany przez funkcję
Len
.
Funkcja Len(nazwa)
zwraca długość tekstu przechowywanego w zmiennej nazwa
.
Pamiętając o zasadzie konwersji liczby 0 na wartość logiczną False
, a każdej
innej liczby na True
, można stwierdzić, że jeśli zmienna nazwa
jest pustym ciągiem znaków (a więc jej długość zwrócona przez funkcję Len
wyniesie 0) wyrażenie
Len(nazwa)
jest równoważne False
, natomiast jeżeli tekst
przechowywany w zmiennej nazwa
zawiera jakieś znaki (a więc funkcja Len
zwróci liczbę
większą od zera) wyrażenie Len(nazwa)
jest równoważne wartości logicznej
True
.
Jednak wyrażenie Len(nazwa)
jest dodatkowo ujęte w operator Not()
,
który odwraca jego wynik. Po uwzględnieniu tego operatora wyrażenie warunkowe jest spełnione dla pustych ciągów znaków,
a fałszywe, jeżeli zmienna nazwa
zawiera niepusty tekst.
Operator iloczynu logicznego (And)
Operator And
łączy ze sobą dwa wyrażenia i tworzy z nich jedno
złożone wyrażenie, które zwraca wartość True
, jeżeli oba składowe
wyrażenia są prawdziwe oraz wartość False
, jeżeli co najmniej jedno
z nich nie jest spełnione. Operator And
działa identycznie jak
arkuszowa funkcja =ORAZ
.
Poniżej znajduje się kilka przykładów zastosowania operatora And
w
instrukcjach If ... Then
:
If x > 0 And x Mod 2
Then
Przedstawiony w tym przykładzie złożony warunek składa się z dwóch warunków składowych: x > 0
oraz x Mod 2
, połączonych operatorem And
, oznaczającym
że oba te warunki muszą być równocześnie spełnione, aby całe wyrażenie było prawdziwe.
Pierwsza składowa tego złożonego warunku - x>0
- określa, że wartość zmiennej x
musi
być większa od zera.
Drugim składnikiem jest wyrażenie x Mod 2
, które zwraca resztę z dzielenia liczby x
przez 2. Aby wartość tego składowego wyrażenia była prawdziwa, wynikiem funkcji x Mod 2
musi być
liczba różna od zera (ponieważ liczba zero równoważna jest wartości False
,
a każda inna liczba wartości True
), a więc liczba x
musi
być nieparzysta (dla liczb parzystych resztą z dzielenia ich przez 2 jest 0).
Patrząc łącznie na podany warunek można stwierdzić, że będzie on spełniony w sytuacji, gdy zmienna x
przechowuje liczbę nieparzystą większą od zera.
If Len(tekst) >= 6 And
Mid(tekst, 2, 1) = "a" Then
W tym przykładzie składowymi konstrukcji logicznej z operatorem And
są wyrażenia:
Len(tekst)>=6
oraz Mid(tekst, 2, 1)
.
Pierwsze z tych wyrażeń - Len(tekst) >= 6
- jest spełnione jeżeli długość zmiennej tekstowej tekst
wynosi co najmniej 6 znaków.
W drugim wyrażeniu zastosowano funkcję Mid
, która zwraca określony fragment podanego tekstu. W tym konkretnym
przypadku funkcja Mid
zwraca fragment tekstu przechowywanego w zmiennej tekst
, o długości jednego
znaku, rozpoczynający się od drugiego znaku tego tekstu (a więc zwraca drugi znak tego tekstu). Wyrażenie jest spełnione,
jeśli wartość zwrócona przez funkcję Mid
wynosi a, a więc jeżeli drugi znak wyrazu przypisanego do
zmiennej tekst
to litera a.
Podsumowując, cały powyższy warunek jest spełniony w sytuacji, gdy zmienna tekst
przechowuje tekst o długości
co najmniej 6 znaków, w którym drugi znak to a.
If x >= 10 And x <= 20
Then
Powyższy zapis jest bardzo popularnym zastosowaniem operatora And
i polega na
sprawdzeniu czy wartość zmiennej zawiera się w jakimś przedziale.
Pierwsza składowa całego wyrażenia jest prawdziwa dla liczb większych lub równych 10, natomiast druga dla liczb mniejszych
lub równych 20. W związku z tym, całe wyrażenie jest prawdziwe, jeżeli zmienna x
jest równocześnie >= 10 i <= 20,
a więc jeśli zawiera się w przedziale 10-20.
Operator sumy logicznej (Or)
Operator Or
łączy ze sobą dwa wyrażenia i tworzy z nich jedno złożone
wyrażenie, które jest prawdziwe, jeżeli przynajmniej jedno składowe wyrażenia jest prawdziwe oraz fałszywe,
jeżeli oba wyrażenia składowe są równocześnie fałszywe. Operator Or
działa
identycznie jak arkuszowa funkcja =LUB
.
Poniżej znajduje się kilka przykładów zastosowania operatora Or
w instrukcjach
If ... Then
:
If x < 10 Or x > 20
Then
Powyższy przykład jest odwrotnością ostatniego z przykładów przedstawionych przy okazji opisywania operatora
And
, w którym wartość True
była zwracana, jeżeli liczba zawierała się w określonym przedziale.
Pierwsze składowe wyrażenie - x < 10
- jest spełnione, jeżeli zmienna x
jest mniejsza od 10,
drugie natomiast - x>20
- jest prawdziwe dla liczb większych od 20.
Oba wyrażenia są ze sobą połączone operatorem Or
, dlatego też wystarczy aby
jedno z tych wyrażeń było prawdziwe, a całe wyrażenie przyjmie wartość True
.
Aby zatem całe wyrażenie było prawdziwe, zmienna x
może przyjąć wartość mniejszą od 10 lub większą od 20.
Dla liczb z zakresu 10-20 całe wyrażenie zwróci wartość False
, ponieważ żadna
z tych liczb nie jest ani mniejsza od 10, ani większa od 20.
Z uwagi na to, że to wyrażenie jest dokładną odwrotnością wspomnianej funkcji używającej operatora
And
, można je również zapisać poprzez wstawienie jego pierwszej wersji
(tej z operatorem And
) do operatora Not
:
If Not(x >= 10 And x <= 20) Then
If Weekday(Date, vbMonday) = 2 Or
Weekday(Date, vbMonday) = 4 Then
Załóżmy, że napisałeś makro wykonujące jakiś raport, przy czym we wtorki i czwartki ma ono jeszcze wykonywać jakieś
dodatkowe operacje - np. przesyłać ten raport do klientów.
W takiej sytuacji mógłbyś skorzystać z powyższej instrukcji warunkowej. Składa się ona z dwóch składowych wyrażeń, z których
każde sprawdza czy aktualna data przypada w określonym dniu tygodnia.
Każde z tych cząstkowych wyrażeń korzysta z funkcji Weekday
, która zwraca numer dnia tygodnia dla określonej
daty i określonego dnia uważanego za początek tygodnia oraz z funkcji Date
, która zwraca aktualną datę.
Całe wyrażenie jest prawdziwe, jeżeli przynajmniej jedno ze składowych wyrażeń jest prawdziwe (zresztą w tym przypadku w
jednym czasie tylko jedno wyrażenie może być prawdziwe, ponieważ określony dzień nie może być równocześnie wtorkiem i
czwartkiem), a więc jeżeli aktualny dzień zwrócony przez funkcję Date
przypada na wtorek lub czwartek.
Operator wyłączenia (Xor)
Operator Xor
łączy ze sobą dwa wyrażenia i tworzy z nich jedno złożone
wyrażenie, które zwraca wartość True
tylko wtedy, kiedy jedno składowe
wyrażenia jest prawdziwe, a drugie fałszywe, oraz wartość False
jeżeli
oba składowe wyrażenia są prawdziwe albo oba są fałszywe. Operator Xor
nie ma odpowiednika wśród funkcji arkuszowych.
Poniżej znajduje się przykład zastosowania operatora Xor
w instrukcji
If ... Then
:
If i >= 0 Xor
j >= 0 Then
Przedstawiona powyżej instrukcja warunkowa składa się z dwóch wyrażeń: i >= 0
oraz j >= 0
połączonych operatorem Xor
. Każde ze składowych wyrażeń sprawdza czy jedna
ze zmiennych jest ujemna.
Jak wcześniej wspomniano, wyrażenie zawierające operator Xor
jest prawdziwe,
jeżeli oba jego składniki zwracają różne wartości. Aby więc cały warunek był spełniony, zmienna i
musi być
dodatnia, a zmienna j
ujemna, lub odwrotnie. W sytuacji, gdy obie zmienne będą miały taki sam znak, warunek
nie będzie spełniony.
Operator równości (Eqv)
Operator Eqv
jest dokładną odwrotnością operatora
Xor
. Warunek zawierający operator Eqv
jest spełniony w sytuacji, gdy oba wyrażenia składowe zwracają tę samą wartość. Jeżeli natomiast jeden ze
składowych warunków jest prawdziwy, a drugi fałszywy, całe wyrażenie jest fałszywe. Operator
Eqv
nie ma swojego odpowiednika wśród funkcji arkuszowych.
Ponieważ operator Eqv
jest dokładną odwrotnością operatora
Xor
, każdy warunek wykorzystujący Xor
można zapisać w inny sposób - zastępując operator Xor
operatorem
Eqv
i wstawiając całe wyrażenie do operatora
Not
(zasada działa też oczywiście w odwrotną stronę - każde wyrażenie
z operatorem Eqv
można zastąpić takim samym wyrażeniem z operatorem
Xor
, wstawionym do operatora Not
).
Poniżej znajduje się przykład zastosowania operatora Eqv
w instrukcji
If ... Then
:
If i >= 0 Eqv j >= 0
Then
Powyższa instrukcja jest dokładną odwrotnością instrukcji zaprezentowanej przy okazji omawiania operatora
Xor
. Instrukcja ta również składa się z dwóch wyrażeń:
i >= 0
oraz j >= 0
, w których każde sprawdza czy jedna ze zmiennych jest ujemna.
Jako, że operatorem łączącym oba wyrażenia składowe jest Eqv
, cały
warunek będzie spełniony w sytuacji, gdy oba cząstkowe wyrażenia zwrócą tę samą wartość, a więc gdy obie
zmienne będą liczbami ujemnymi, lub obie będą liczbami dodatnimi. Jeżeli jedna z tych dwóch zmiennych
będziesz przechowywała liczbę dodatnią, a druga ujemną, całe wyrażenie zwróci wartość
False
.
Operator implikacji (Imp)
Operator Imp
, zwany operatorem implikacji, łączy ze sobą dwa wyrażenia
składowe i zwraca wartość False
w sytuacji, gdy pierwsze wyrażenie
jest prawdziwe, a drugie fałszywe, oraz wartość True
w każdej
innej sytuacji.
Poniżej znajduje się przykład zastosowania operatora Imp
w instrukcji
If ... Then
:
If dataPlatnosci < Date() Imp czyZaplacono Then
Celem powyższego wyrażenia, złożonego z dwóch składowych warunków połączonych operatorem Imp
,
jest wychwycenie przeterminowanych płatności.
Pierwszy składowy warunek sprawdza czy zmienna dataPlatnosci
, przechowująca, jak nietrudno się domyślić,
wymaganą datę płatności, jest mniejsza od aktualnej daty (jeśli jest mniejsza, płatność powinna być już uiszczona).
Drugi warunek jest natomiast po prostu zmienną logiczną i jest spełniony wówczas, gdy zmienna ta przechowuje wartość
True
.
Tak jak wcześniej zaznaczono, wyrażenia powiązane operatorem Imp
są fałszywe,
jeżeli pierwsze z nich zwraca wartość True
, a drugie False
.
W każdej innej sytuacji wyrażenia takie są prawdziwe.
W powyższym przykładzie wyrażenie będzie więc fałszywe tylko w sytuacji, gdy minęła już wymagana data płatności (czyli
warunek dataPlatnosci > Date()
zwróci True
), a jednocześnie
płatność ta nie została jeszcze uregulowana (zmienna czyZaplacono=False
). W związku z tym, w instrukcji
warunkowej If ... Then
w bloku przewidzianym dla niespełnionych warunków
można np. umieścić komunikat MsgBox
z informacją o konieczności wykonania płatności.
Imp
jest jedynym operatorem, przy którym kolejność przedstawienia obu
składowych wyrażeń ma istotne znaczenie i może wpłynąć na wynik.
Język VBA umożliwia również tworzenie jeszcze bardziej złożonych wyrażeń, wykorzystujących równocześnie kilka
operatorów logicznych.
Do przykładu przedstawionego przy okazji omawiania operatora Or
, w którym
sprawdzano czy aktualna data przypada we wtorek lub czwartek, można równie dobrze dopisać dodatkowy dzień:
If Weekday(Date, vbMonday) = 2 Or
Weekday(Date, vbMonday) = 4 Or Weekday(Date, vbMonday) = 5 Then
Wyrażenie wykorzystuje teraz dwa operatory logiczne Or
, które łączą ze sobą
trzy składowe warunki, i będzie spełnione także dla dat przypadających w piątek.
Poniższe wyrażenie wykorzystuje natomiast dwa operatory And
:
If x >= 0 And x <= 20
And x Mod 2 Then
Jako że wszystkie części składowe tego wyrażenia są ze sobą połączone operatorami And
,
będzie ono prawdziwe tylko wtedy, gdy prawdziwe będą wszystkie jego składniki.
Jak więc się już pewnie domyślasz na podstawie poprzednich przykładów, wyrażenie to będzie spełnione, jeżeli
zmienna x
będzie nieparzystą liczbą z zakresu 0-20 (aby spełniony był pierwszy warunek - x >= 0
- zmienna x
musi być większa od zera; drugi warunek - x <= 20
- jest spełniony, jeżeli zmienna
x
jest mniejsza od 20; wreszcie aby spełnić trzeci warunek - x Mod 2
- operacja zwracania
reszty z dzielenia zmiennej x
przez 2 musi zwrócić liczbę różną od zera, a więc zmienna x
musi być nieparzysta).
Możliwe jest też oczywiście łączenie w jednym wyrażeniu różnych operatorów. Przykład takiego wyrażenia zaprezentowano
poniżej:
If x < 0 Or x > 20
And x Mod 2 Then
W przedstawionym powyżej wyrażeniu wykorzystane zostały operatory Or
i
And
. Na pierwszy rzut oka mogłoby się wydawać, że wyrażenie to jest
odwrotnością poprzedniego, które było spełnione dla liczb nieparzystych z zakresu 1-20. W rzeczywistości jest
jednak inaczej.
Podobnie, jak to ma miejsce w przypadku operatorów arytmetycznych, niektóre operatory logiczne mają wyższy priorytet
od innych i są wykonywane przed nimi. Kolejność wykonywania operatorów logicznych jest dokładnie taka, w jakiej
zostały one omówione w nieniejszym podrozdziale: Not
/
And
/ Or
/
Xor
/ Eqv
/
Imp
.
W związku z tym, w omawianym przykładzie, złożonym z trzech składowych wyrażeń, jako pierwsze rozpatrywane są wyrażenia
drugie i trzecie - x > 20 And x Mod 2
, które łącznie będą spełnione dla nieparzystych liczb większych od 20.
Dopiero teraz wynik tego wyrażenia jest łączony z pierwszym składowym wyrażeniem (x < 0
) za pomocą
operatora Or
. Użycie tego operatora oznacza, że wystarczy spełnienie
jednego z warunków, aby spełnione było całe wyrażenie - wystarczy więc, że zmienna x
będzie mniejsza
od zera (nawet jeśli będzie parzysta), a całe wyrażenie zwróci wartość True
.
Przedstawiony przykład pokazuje, że ignorowanie kolejności wykonywania działań na operatorach logicznych może
prowadzić do wyników niezgodnych z zamierzeniami. Aby uniknąć tego typu kłopotów, podobnie jak w przypadku
operatorów arytmetycznych, należy posłużyć się nawiasami.
Żeby omawiane wcześniej wyrażenie rzeczywiście było spełnione dla nieparzystych liczb spoza zakresu 1-20, musiałoby
być zapisane w następujący sposób:
If (x < 0 Or
x > 20) And x Mod 2 Then
W takiej postaci tego wyrażenia najpierw rozpatrywane są warunki znajdujące się w nawiasie, a więc
x < 0 Or x > 20
, i dopiero wynik tego podwyrażenia jest zestawiany
za pomocą operatora And
z warunkiem x Mod 20
.
Poniżej przedstawiono jeszcze jeden przykład obrazujący różnicę wynikającą ze zmiany kolejności działań
poprzez zastosowanie nawiasów.
If Not x >= 0 And x < 20 Then
If Not (x >= 0 And x < 20) Then
W pierwszym zapisie najpierw wykonywana jest operacja negacji, a więc warunek Not x >= 0
jest przez kompilator
przekładany na wyrażenie x < 0
. Dopiero ten zapis jest łączony za pomocą operatora And
z drugim składowym warunkiem: x < 20
. Wyrażenie to będzie więc prawdziwe, jeżeli zmienna x
będzie
przechowywała liczbę ujemną.
Natomiast w drugim zapisie jako pierwsza wykonywana jest operacja w nawiasie, która zwraca wartość
True
dla liczb z zakresu 0-20. Dopiero po uzyskaniu wyniku wyrażenia w nawiasie,
jest on odwracany przez operator Not
, w związku z czym całe wyrażenie będzie
spełnione dla liczb niezawierających się w zakresie 0-20.
Odczytywanie przycisku wciśniętego przez użytkownika
Ostatnim zagadnieniem, poruszonym przy okazji omawiania instrukcji warunkowych, będzie odczytywanie wyniku funkcji
MsgBox
(czyli przycisku wciśniętego przez użytkownika w oknie z komunikatem), które również wykorzystuje
konstrukcję If ... Then
.
Poniżej znajduje się przykładowe makro, które wyświetla najpierw pytanie Czy chcesz wyświetlić w arkuszu aktualną
godzinę?, a następnie, w zależności od wciśniętego przycisku(Yes lub No) wyświetla w arkuszu godzinę
lub kończy swoje działanie.
1
2
3
4
5
6
7
8
9
10
Sub wyswietlanieDaty()
Dim przycisk As Integer
przycisk = MsgBox("Czy chcesz wyświetlić w arkuszu aktualną godzinę?", _
vbYesNo + vbQuestion, "Potwierdzenie")
If przycisk = 6 Then
Cells(1, 1) = Time
End If
End Sub
W omawianym makrze zadeklarowana została jedna zmienna typu liczbowego - przycisk
, która będzie
przechowywała wartość liczbową wciśniętego przez użytkownika przycisku.
Do każdego typu przycisku, jaki może pojawić się w oknie MsgBox
przypisane są odpowiednie liczby,
które zostały przedstawione w poniższej tabelce:
PRZYCISK WARTOŚĆ
OK 1
Cancel 2
Abort 3
Retry 4
Ignore 5
Yes 6
No 7
Po kliknięciu w oknie MsgBox
jakiegokolwiek przycisku, okno to znika z ekranu, a cała funkcja
MsgBox
zwraca taką wartość, jaka jest przypisana do tego przycisku.
Okno MsgBox
wyświetlane w opisywanym przykładzie posiada dwa przyciski: Yes oraz No,
a więc funkcja MsgBox
może przyjąć wartość 6 (jeżeli zostanie wciśnięty przycisk Yes) lub 7
(jeżeli użytkownik wciśnie No).
W wierszu 5 znajduje się instrukcja warunkowa, sprawdzająca czy do zmiennej przycisk
przypisana jest wartość 6, co byłoby równoznaczne z kliknięciem przycisku Yes. Jeżeli warunek ten jest spełniony,
makro wyświetla w komórce arkusza informację o aktualnej godzinie. W sytuacji, gdy warunek z wiersza
5 nie jest spełniony, czyli wciśnięty został przycisk No, makro nie ma wykonywać żadnych
operacji, pominięty więc został blok Else
instrukcji warunkowej.
W jednej z kolejnych lekcji poznasz wreszcie przywoływane od jakiegoś czasu wartości wyliczeniowe, dzięki którym zamiast
korzystać przy odczytywaniu wyniku funkcji MsgBox
z niewygodnych i trudnych do zapamiętania liczb, będziesz
mógł użyć dobrze opisanych nazw wyliczeniowych, takich jak np. vbYes lub vbNo.
If x > 0 Then
Else
Call MsgBox("Liczba x jest mniejsza od zera")
End If
Zamiast tego można jednak odwrócić wynik warunku za pomocą operatora Not()
(operatory logiczne wykorzystywane w instrukcjach warunkowych zostały omówione
w kolejnym podrozdziale tej lekcji). Wówczas to, co dotychczas było prawdą, stanie się fałszem i na odwrót, a
operacje wykonywane dotychczas przy niespełnionym warunku będą teraz wykonywane przy jego spełnieniu:
If Not(x >= 0) Then
Call MsgBox("Liczba x jest mniejsza od zera")
Else
End If
W powyższym kodzie można się już pozbyć słowa kluczowego Else
,
a dodatkowo zwinąć całą instrukcję warunkową do jednej linijki:
If Not(x >= 0) Then Call MsgBox("Liczba x jest mniejsza od zera")
If Not(x >= 0) Then Call MsgBox("Liczba x jest mniejsza od zera")
Określając warunek dla instrukcji If ... Then
można konstruować rozbudowane
warunki, składające się z kilku prostych warunków połączonych ze sobą za pomocą operatorów logicznych.
Kilka z operatorów logicznych dostępnych w VBA ma swoje odpowiedniki wśród funkcji arkuszowych, więc możesz je już
znać (np. LUB()
czy ORAZ()
). Są one często wykorzystywane do budowania warunków dla arkuszowej
funkcji warunkowej =JEŻELI()
).
Poniższa lista zawiera wykaz wszystkich operatorów logicznych dostępnych w VBA. Klikając w nazwę poszczególnych operatorów przeniesiesz się do ich szczegółowego opisu z przykładami zastosowania.
Operator negacji (Not)
Operator Not
stosowany jest wraz z pojedynczym wyrażeniem i odwraca jego
wartość.
Operator Not
działa identycznie jak funkcja arkuszowa =NIE
.
Jeżeli wynikiem jakiegoś wyrażenia jest True
to dodanie przed nim operatora
Not
zmieni jego wartość na False
i odwrotnie.
Poniżej znajduje się kilka przykładów zastosowania operatora Not
w instrukcjach
If ... Then
.
If Not(x = 0) Then
Sam warunek x = 0
byłby spełniony dla zera, natomiast dla każdej innej liczby zwróciłby wartość
False
. Jednak dodanie przed nim operatora
Not
sprawia, że sytuacja odwraca się o 180 stopni.
Teraz w przypadku, gdy zmienna x
ma wartość 0 całe wyrażenie warunkowe jest fałszywe, a więc wykonywane
będą operacje umieszczone w bloku zawartym między słowami Else
a
End If
.
Jeżeli zmienna x
będzie natomiast miała wartość różną od 0, warunek będzie spełniony i wykonane zostaną
polecenia znajdujące się pomiędzy słowami Then
a
Else
.
If Not(2 > 1) Then
W tej sytuacji instrukcja If
zawsze będzie wykonywała operacje przewidziane dla niespełnionego warunku.
Wyrażenie 2 > 1
zawsze jest prawdziwe, jednak operator Not
zamienia
jego wartość na False
.
If Not(Len(nazwa)) Then
Zmienna nazwa
musi być zmienną tekstową, ponieważ tylko taki typ danych jest przyjmowany przez funkcję
Len
.
Funkcja Len(nazwa)
zwraca długość tekstu przechowywanego w zmiennej nazwa
.
Pamiętając o zasadzie konwersji liczby 0 na wartość logiczną False
, a każdej
innej liczby na True
, można stwierdzić, że jeśli zmienna nazwa
jest pustym ciągiem znaków (a więc jej długość zwrócona przez funkcję Len
wyniesie 0) wyrażenie
Len(nazwa)
jest równoważne False
, natomiast jeżeli tekst
przechowywany w zmiennej nazwa
zawiera jakieś znaki (a więc funkcja Len
zwróci liczbę
większą od zera) wyrażenie Len(nazwa)
jest równoważne wartości logicznej
True
.
Jednak wyrażenie Len(nazwa)
jest dodatkowo ujęte w operator Not()
,
który odwraca jego wynik. Po uwzględnieniu tego operatora wyrażenie warunkowe jest spełnione dla pustych ciągów znaków,
a fałszywe, jeżeli zmienna nazwa
zawiera niepusty tekst.
Operator iloczynu logicznego (And)
Operator And
łączy ze sobą dwa wyrażenia i tworzy z nich jedno
złożone wyrażenie, które zwraca wartość True
, jeżeli oba składowe
wyrażenia są prawdziwe oraz wartość False
, jeżeli co najmniej jedno
z nich nie jest spełnione. Operator And
działa identycznie jak
arkuszowa funkcja =ORAZ
.
Poniżej znajduje się kilka przykładów zastosowania operatora And
w
instrukcjach If ... Then
:
If x > 0 And x Mod 2
Then
Przedstawiony w tym przykładzie złożony warunek składa się z dwóch warunków składowych: x > 0
oraz x Mod 2
, połączonych operatorem And
, oznaczającym
że oba te warunki muszą być równocześnie spełnione, aby całe wyrażenie było prawdziwe.
If x > 0 And x Mod 2
Then
Pierwsza składowa tego złożonego warunku - x>0
- określa, że wartość zmiennej x
musi
być większa od zera.
Drugim składnikiem jest wyrażenie x Mod 2
, które zwraca resztę z dzielenia liczby x
przez 2. Aby wartość tego składowego wyrażenia była prawdziwa, wynikiem funkcji x Mod 2
musi być
liczba różna od zera (ponieważ liczba zero równoważna jest wartości False
,
a każda inna liczba wartości True
), a więc liczba x
musi
być nieparzysta (dla liczb parzystych resztą z dzielenia ich przez 2 jest 0).
Patrząc łącznie na podany warunek można stwierdzić, że będzie on spełniony w sytuacji, gdy zmienna x
przechowuje liczbę nieparzystą większą od zera.
If Len(tekst) >= 6 And
Mid(tekst, 2, 1) = "a" Then
If Len(tekst) >= 6 And
Mid(tekst, 2, 1) = "a" Then
W tym przykładzie składowymi konstrukcji logicznej z operatorem And
są wyrażenia:
Len(tekst)>=6
oraz Mid(tekst, 2, 1)
.
Pierwsze z tych wyrażeń - Len(tekst) >= 6
- jest spełnione jeżeli długość zmiennej tekstowej tekst
wynosi co najmniej 6 znaków.
W drugim wyrażeniu zastosowano funkcję Mid
, która zwraca określony fragment podanego tekstu. W tym konkretnym
przypadku funkcja Mid
zwraca fragment tekstu przechowywanego w zmiennej tekst
, o długości jednego
znaku, rozpoczynający się od drugiego znaku tego tekstu (a więc zwraca drugi znak tego tekstu). Wyrażenie jest spełnione,
jeśli wartość zwrócona przez funkcję Mid
wynosi a, a więc jeżeli drugi znak wyrazu przypisanego do
zmiennej tekst
to litera a.
Podsumowując, cały powyższy warunek jest spełniony w sytuacji, gdy zmienna tekst
przechowuje tekst o długości
co najmniej 6 znaków, w którym drugi znak to a.
If x >= 10 And x <= 20
Then
If x >= 10 And x <= 20
Then
Powyższy zapis jest bardzo popularnym zastosowaniem operatora And
i polega na
sprawdzeniu czy wartość zmiennej zawiera się w jakimś przedziale.
Pierwsza składowa całego wyrażenia jest prawdziwa dla liczb większych lub równych 10, natomiast druga dla liczb mniejszych
lub równych 20. W związku z tym, całe wyrażenie jest prawdziwe, jeżeli zmienna x
jest równocześnie >= 10 i <= 20,
a więc jeśli zawiera się w przedziale 10-20.
(Or)
Operator Or
łączy ze sobą dwa wyrażenia i tworzy z nich jedno złożone
wyrażenie, które jest prawdziwe, jeżeli przynajmniej jedno składowe wyrażenia jest prawdziwe oraz fałszywe,
jeżeli oba wyrażenia składowe są równocześnie fałszywe. Operator Or
działa
identycznie jak arkuszowa funkcja =LUB
.
Poniżej znajduje się kilka przykładów zastosowania operatora Or
w instrukcjach
If ... Then
:
If x < 10 Or x > 20
Then
If x < 10 Or x > 20
Then
Powyższy przykład jest odwrotnością ostatniego z przykładów przedstawionych przy okazji opisywania operatora
And
, w którym wartość True
była zwracana, jeżeli liczba zawierała się w określonym przedziale.
Pierwsze składowe wyrażenie - x < 10
- jest spełnione, jeżeli zmienna x
jest mniejsza od 10,
drugie natomiast - x>20
- jest prawdziwe dla liczb większych od 20.
Oba wyrażenia są ze sobą połączone operatorem Or
, dlatego też wystarczy aby
jedno z tych wyrażeń było prawdziwe, a całe wyrażenie przyjmie wartość True
.
Aby zatem całe wyrażenie było prawdziwe, zmienna x
może przyjąć wartość mniejszą od 10 lub większą od 20.
Dla liczb z zakresu 10-20 całe wyrażenie zwróci wartość False
, ponieważ żadna
z tych liczb nie jest ani mniejsza od 10, ani większa od 20.
Z uwagi na to, że to wyrażenie jest dokładną odwrotnością wspomnianej funkcji używającej operatora
And
, można je również zapisać poprzez wstawienie jego pierwszej wersji
(tej z operatorem And
) do operatora Not
:
If Not(x >= 10 And x <= 20) Then
If Not(x >= 10 And x <= 20) Then
If Weekday(Date, vbMonday) = 2 Or
Weekday(Date, vbMonday) = 4 Then
If Weekday(Date, vbMonday) = 2 Or
Weekday(Date, vbMonday) = 4 Then
Załóżmy, że napisałeś makro wykonujące jakiś raport, przy czym we wtorki i czwartki ma ono jeszcze wykonywać jakieś dodatkowe operacje - np. przesyłać ten raport do klientów.
W takiej sytuacji mógłbyś skorzystać z powyższej instrukcji warunkowej. Składa się ona z dwóch składowych wyrażeń, z których każde sprawdza czy aktualna data przypada w określonym dniu tygodnia.
Każde z tych cząstkowych wyrażeń korzysta z funkcji Weekday
, która zwraca numer dnia tygodnia dla określonej
daty i określonego dnia uważanego za początek tygodnia oraz z funkcji Date
, która zwraca aktualną datę.
Całe wyrażenie jest prawdziwe, jeżeli przynajmniej jedno ze składowych wyrażeń jest prawdziwe (zresztą w tym przypadku w
jednym czasie tylko jedno wyrażenie może być prawdziwe, ponieważ określony dzień nie może być równocześnie wtorkiem i
czwartkiem), a więc jeżeli aktualny dzień zwrócony przez funkcję Date
przypada na wtorek lub czwartek.
Operator wyłączenia (Xor)
Operator Xor
łączy ze sobą dwa wyrażenia i tworzy z nich jedno złożone
wyrażenie, które zwraca wartość True
tylko wtedy, kiedy jedno składowe
wyrażenia jest prawdziwe, a drugie fałszywe, oraz wartość False
jeżeli
oba składowe wyrażenia są prawdziwe albo oba są fałszywe. Operator Xor
nie ma odpowiednika wśród funkcji arkuszowych.
Poniżej znajduje się przykład zastosowania operatora Xor
w instrukcji
If ... Then
:
If i >= 0 Xor
j >= 0 Then
Przedstawiona powyżej instrukcja warunkowa składa się z dwóch wyrażeń: i >= 0
oraz j >= 0
połączonych operatorem Xor
. Każde ze składowych wyrażeń sprawdza czy jedna
ze zmiennych jest ujemna.
Jak wcześniej wspomniano, wyrażenie zawierające operator Xor
jest prawdziwe,
jeżeli oba jego składniki zwracają różne wartości. Aby więc cały warunek był spełniony, zmienna i
musi być
dodatnia, a zmienna j
ujemna, lub odwrotnie. W sytuacji, gdy obie zmienne będą miały taki sam znak, warunek
nie będzie spełniony.
Xor
łączy ze sobą dwa wyrażenia i tworzy z nich jedno złożone
wyrażenie, które zwraca wartość True
tylko wtedy, kiedy jedno składowe
wyrażenia jest prawdziwe, a drugie fałszywe, oraz wartość False
jeżeli
oba składowe wyrażenia są prawdziwe albo oba są fałszywe. Operator Xor
nie ma odpowiednika wśród funkcji arkuszowych.
Xor
w instrukcji
If ... Then
:
If i >= 0 Xor
j >= 0 Then
i >= 0
oraz j >= 0
połączonych operatorem Xor
. Każde ze składowych wyrażeń sprawdza czy jedna
ze zmiennych jest ujemna.
Xor
jest prawdziwe,
jeżeli oba jego składniki zwracają różne wartości. Aby więc cały warunek był spełniony, zmienna i
musi być
dodatnia, a zmienna j
ujemna, lub odwrotnie. W sytuacji, gdy obie zmienne będą miały taki sam znak, warunek
nie będzie spełniony.
Operator równości (Eqv)
Operator Eqv
jest dokładną odwrotnością operatora
Xor
. Warunek zawierający operator Eqv
jest spełniony w sytuacji, gdy oba wyrażenia składowe zwracają tę samą wartość. Jeżeli natomiast jeden ze
składowych warunków jest prawdziwy, a drugi fałszywy, całe wyrażenie jest fałszywe. Operator
Eqv
nie ma swojego odpowiednika wśród funkcji arkuszowych.
Ponieważ operator Eqv
jest dokładną odwrotnością operatora
Xor
, każdy warunek wykorzystujący Xor
można zapisać w inny sposób - zastępując operator Xor
operatorem
Eqv
i wstawiając całe wyrażenie do operatora
Not
(zasada działa też oczywiście w odwrotną stronę - każde wyrażenie
z operatorem Eqv
można zastąpić takim samym wyrażeniem z operatorem
Xor
, wstawionym do operatora Not
).
Poniżej znajduje się przykład zastosowania operatora Eqv
w instrukcji
If ... Then
:
If i >= 0 Eqv j >= 0
Then
If i >= 0 Eqv j >= 0
Then
Powyższa instrukcja jest dokładną odwrotnością instrukcji zaprezentowanej przy okazji omawiania operatora
Xor
. Instrukcja ta również składa się z dwóch wyrażeń:
i >= 0
oraz j >= 0
, w których każde sprawdza czy jedna ze zmiennych jest ujemna.
Jako, że operatorem łączącym oba wyrażenia składowe jest Eqv
, cały
warunek będzie spełniony w sytuacji, gdy oba cząstkowe wyrażenia zwrócą tę samą wartość, a więc gdy obie
zmienne będą liczbami ujemnymi, lub obie będą liczbami dodatnimi. Jeżeli jedna z tych dwóch zmiennych
będziesz przechowywała liczbę dodatnią, a druga ujemną, całe wyrażenie zwróci wartość
False
.
Operator implikacji (Imp)
Operator Imp
, zwany operatorem implikacji, łączy ze sobą dwa wyrażenia
składowe i zwraca wartość False
w sytuacji, gdy pierwsze wyrażenie
jest prawdziwe, a drugie fałszywe, oraz wartość True
w każdej
innej sytuacji.
Poniżej znajduje się przykład zastosowania operatora Imp
w instrukcji
If ... Then
:
If dataPlatnosci < Date() Imp czyZaplacono Then
If dataPlatnosci < Date() Imp czyZaplacono Then
Celem powyższego wyrażenia, złożonego z dwóch składowych warunków połączonych operatorem Imp
,
jest wychwycenie przeterminowanych płatności.
Pierwszy składowy warunek sprawdza czy zmienna dataPlatnosci
, przechowująca, jak nietrudno się domyślić,
wymaganą datę płatności, jest mniejsza od aktualnej daty (jeśli jest mniejsza, płatność powinna być już uiszczona).
Drugi warunek jest natomiast po prostu zmienną logiczną i jest spełniony wówczas, gdy zmienna ta przechowuje wartość
True
.
Tak jak wcześniej zaznaczono, wyrażenia powiązane operatorem Imp
są fałszywe,
jeżeli pierwsze z nich zwraca wartość True
, a drugie False
.
W każdej innej sytuacji wyrażenia takie są prawdziwe.
W powyższym przykładzie wyrażenie będzie więc fałszywe tylko w sytuacji, gdy minęła już wymagana data płatności (czyli
warunek dataPlatnosci > Date()
zwróci True
), a jednocześnie
płatność ta nie została jeszcze uregulowana (zmienna czyZaplacono=False
). W związku z tym, w instrukcji
warunkowej If ... Then
w bloku przewidzianym dla niespełnionych warunków
można np. umieścić komunikat MsgBox
z informacją o konieczności wykonania płatności.
Imp
jest jedynym operatorem, przy którym kolejność przedstawienia obu
składowych wyrażeń ma istotne znaczenie i może wpłynąć na wynik.
Język VBA umożliwia również tworzenie jeszcze bardziej złożonych wyrażeń, wykorzystujących równocześnie kilka operatorów logicznych.
Do przykładu przedstawionego przy okazji omawiania operatora Or
, w którym
sprawdzano czy aktualna data przypada we wtorek lub czwartek, można równie dobrze dopisać dodatkowy dzień:
If Weekday(Date, vbMonday) = 2 Or
Weekday(Date, vbMonday) = 4 Or Weekday(Date, vbMonday) = 5 Then
If Weekday(Date, vbMonday) = 2 Or
Weekday(Date, vbMonday) = 4 Or Weekday(Date, vbMonday) = 5 Then
Wyrażenie wykorzystuje teraz dwa operatory logiczne Or
, które łączą ze sobą
trzy składowe warunki, i będzie spełnione także dla dat przypadających w piątek.
Poniższe wyrażenie wykorzystuje natomiast dwa operatory And
:
If x >= 0 And x <= 20
And x Mod 2 Then
If x >= 0 And x <= 20
And x Mod 2 Then
Jako że wszystkie części składowe tego wyrażenia są ze sobą połączone operatorami And
,
będzie ono prawdziwe tylko wtedy, gdy prawdziwe będą wszystkie jego składniki.
Jak więc się już pewnie domyślasz na podstawie poprzednich przykładów, wyrażenie to będzie spełnione, jeżeli
zmienna x
będzie nieparzystą liczbą z zakresu 0-20 (aby spełniony był pierwszy warunek - x >= 0
- zmienna x
musi być większa od zera; drugi warunek - x <= 20
- jest spełniony, jeżeli zmienna
x
jest mniejsza od 20; wreszcie aby spełnić trzeci warunek - x Mod 2
- operacja zwracania
reszty z dzielenia zmiennej x
przez 2 musi zwrócić liczbę różną od zera, a więc zmienna x
musi być nieparzysta).
Możliwe jest też oczywiście łączenie w jednym wyrażeniu różnych operatorów. Przykład takiego wyrażenia zaprezentowano
poniżej:
If x < 0 Or x > 20
And x Mod 2 Then
If x < 0 Or x > 20
And x Mod 2 Then
W przedstawionym powyżej wyrażeniu wykorzystane zostały operatory Or
i
And
. Na pierwszy rzut oka mogłoby się wydawać, że wyrażenie to jest
odwrotnością poprzedniego, które było spełnione dla liczb nieparzystych z zakresu 1-20. W rzeczywistości jest
jednak inaczej.
Podobnie, jak to ma miejsce w przypadku operatorów arytmetycznych, niektóre operatory logiczne mają wyższy priorytet
od innych i są wykonywane przed nimi. Kolejność wykonywania operatorów logicznych jest dokładnie taka, w jakiej
zostały one omówione w nieniejszym podrozdziale: Not
/
And
/ Or
/
Xor
/ Eqv
/
Imp
.
W związku z tym, w omawianym przykładzie, złożonym z trzech składowych wyrażeń, jako pierwsze rozpatrywane są wyrażenia
drugie i trzecie - x > 20 And x Mod 2
, które łącznie będą spełnione dla nieparzystych liczb większych od 20.
Dopiero teraz wynik tego wyrażenia jest łączony z pierwszym składowym wyrażeniem (x < 0
) za pomocą
operatora Or
. Użycie tego operatora oznacza, że wystarczy spełnienie
jednego z warunków, aby spełnione było całe wyrażenie - wystarczy więc, że zmienna x
będzie mniejsza
od zera (nawet jeśli będzie parzysta), a całe wyrażenie zwróci wartość True
.
Przedstawiony przykład pokazuje, że ignorowanie kolejności wykonywania działań na operatorach logicznych może prowadzić do wyników niezgodnych z zamierzeniami. Aby uniknąć tego typu kłopotów, podobnie jak w przypadku operatorów arytmetycznych, należy posłużyć się nawiasami.
Żeby omawiane wcześniej wyrażenie rzeczywiście było spełnione dla nieparzystych liczb spoza zakresu 1-20, musiałoby
być zapisane w następujący sposób:
If (x < 0 Or
x > 20) And x Mod 2 Then
If (x < 0 Or
x > 20) And x Mod 2 Then
W takiej postaci tego wyrażenia najpierw rozpatrywane są warunki znajdujące się w nawiasie, a więc
x < 0 Or x > 20
, i dopiero wynik tego podwyrażenia jest zestawiany
za pomocą operatora And
z warunkiem x Mod 20
.
Poniżej przedstawiono jeszcze jeden przykład obrazujący różnicę wynikającą ze zmiany kolejności działań poprzez zastosowanie nawiasów.
If Not x >= 0 And x < 20 Then
If Not (x >= 0 And x < 20) Then
W pierwszym zapisie najpierw wykonywana jest operacja negacji, a więc warunek Not x >= 0
jest przez kompilator
przekładany na wyrażenie x < 0
. Dopiero ten zapis jest łączony za pomocą operatora And
z drugim składowym warunkiem: x < 20
. Wyrażenie to będzie więc prawdziwe, jeżeli zmienna x
będzie
przechowywała liczbę ujemną.
Natomiast w drugim zapisie jako pierwsza wykonywana jest operacja w nawiasie, która zwraca wartość
True
dla liczb z zakresu 0-20. Dopiero po uzyskaniu wyniku wyrażenia w nawiasie,
jest on odwracany przez operator Not
, w związku z czym całe wyrażenie będzie
spełnione dla liczb niezawierających się w zakresie 0-20.
Ostatnim zagadnieniem, poruszonym przy okazji omawiania instrukcji warunkowych, będzie odczytywanie wyniku funkcji
MsgBox
(czyli przycisku wciśniętego przez użytkownika w oknie z komunikatem), które również wykorzystuje
konstrukcję If ... Then
.
Poniżej znajduje się przykładowe makro, które wyświetla najpierw pytanie Czy chcesz wyświetlić w arkuszu aktualną
godzinę?, a następnie, w zależności od wciśniętego przycisku(Yes lub No) wyświetla w arkuszu godzinę
lub kończy swoje działanie.
1
2
3
4
5
6
7
8
9
10
Sub wyswietlanieDaty()
Dim przycisk As Integer
przycisk = MsgBox("Czy chcesz wyświetlić w arkuszu aktualną godzinę?", _
vbYesNo + vbQuestion, "Potwierdzenie")
If przycisk = 6 Then
Cells(1, 1) = Time
End If
End Sub
1
2
3
4
5
6
7
8
9
10
Sub wyswietlanieDaty()
Dim przycisk As Integer
przycisk = MsgBox("Czy chcesz wyświetlić w arkuszu aktualną godzinę?", _
vbYesNo + vbQuestion, "Potwierdzenie")
If przycisk = 6 Then
Cells(1, 1) = Time
End If
End Sub
W omawianym makrze zadeklarowana została jedna zmienna typu liczbowego - przycisk
, która będzie
przechowywała wartość liczbową wciśniętego przez użytkownika przycisku.
Do każdego typu przycisku, jaki może pojawić się w oknie MsgBox
przypisane są odpowiednie liczby,
które zostały przedstawione w poniższej tabelce:
PRZYCISK WARTOŚĆ
OK 1
Cancel 2
Abort 3
Retry 4
Ignore 5
Yes 6
No 7
PRZYCISK | WARTOŚĆ |
OK | 1 |
Cancel | 2 |
Abort | 3 |
Retry | 4 |
Ignore | 5 |
Yes | 6 |
No | 7 |