W poprzedniej lekcji zostało wprowadzone pojęcie zmiennej, nauczyliśmy się je deklarować i zadeklarowaliśmy pierwszą zmienną typu
Long
. W tej lekcji poznamy inne typy zmiennych i dowiemy się czym różnią się one od siebie.
Oprócz wymienionych wyżej typów, zmienna może być także zadeklarowana jako obiekt (w tym przypadku liczba możliwych typów jest
nieskończona, ponieważ sam możesz tworzyć swoje własne typy obiektów), ale ten temat zostanie poruszony w dalszej części kursu.
Zmienne tekstowe (String)
Tekstowy typ zmiennych nosi w języku Visual Basic nazwę String
.
Deklaracja zmiennej jako tekstowej wygląda więc tak:
Wartością domyślną dla zmiennych tekstowych jest pusty ciąg znaków - "".
Na wstępie rozważań o zmiennych tekstowych należy wspomnieć kilka słów o tekstach w programowaniu VBA.
Temat ten był już wstępnie poruszany
w poprzedniej lekcji, ale poniżej znajdziesz jego dokładniejsze omówienie.
Kompilator VBA rozpoznaje czy jakiś kawałek kodu jest tekstem, na podstawie tego, czy jest on umieszczony w cudzysłowie.
Załóżmy, że chcesz wyświetlić w komórce A1 arkusza Arkusz1 tekst Polska.
Nie można zrobić tego w taki sposób, jak poniżej:
Worksheets("Arkusz1").Cells(1,1) = Polska
gdyż w takiej sytuacji słowo Polska nie jest ujęte w cudzysłów i kompilator traktuje je tak, jakby było nazwą zmiennej.
W tej sytuacji możliwe są dwa zakończenia, niestety żadne z nich nie jest happy endem.
Jeżeli w Twoim programie w ogóle nie ma zadeklarowanej zmiennej o nazwie Polska
to program nawet się nie uruchomi.
Kompilator zgłosi błąd przed rozpoczęciem działania, gdyż znajdzie wewnątrz kodu zmienną, która nie została zadeklarowana
(zagadnienie to zostało omówione w lekcji poświęconej
deklarowaniu zmiennych).
Jeżeli natomiast jakimś cudem miałbyś w programie zadeklarowaną zmienną o nazwie Polska
(to bardzo piękna, ale jednak nietypowa
nazwa zmiennej), wówczas w arkuszu i tak nie wyświetliłby się napis Polska lecz wartość, jaką zawiera w sobie zmienna
Polska
(chyba, że byłaby to zmienna typu tekstowego i miała przypisany właśnie tekst Polska).
Dokładnie w ten sposób postępowaliśmy w poprzedniej lekcji, wyświetlając w arkuszu wartość przechowywaną przez zmienną potega
-
wpisywaliśmy wówczas w kodzie nazwę potega
bez cudzysłowu.
Mniej wątpliwości budzi sytuacja, gdy tekst, który chcesz wypisać w arkuszu (lub wykonać z nim jakąś inną operację) zawiera więcej niż
jedno słowo, np:
Worksheets("Arkusz1").Cells(1,1) = Tekst do wyświetlenia
Taka konstrukcja nawet przed próbą uruchomienia programu podświetli się na czerwono i od razu zorientujesz się, że coś jest nie tak.
Powyższy zapis jest dla kompilatora równoznaczny z wypisaniem jednym ciągiem 3 nazw zmiennych (tekst
, do
,
wyświetlenia
), co byłoby złamaniem co najmniej dwóch zakazów obowiązujących przy programowaniu, ponieważ nie powinno się
używać polskich znaków w nazwach zmiennych, a ponadto nigdy żadne dwie nazwy zmiennych nie mogą znaleźć się koło siebie oddzielone
tylko spacją.
W omawianych wyżej sytuacjach prawidłowymi zapisami byłyby:
Worksheets("Arkusz1").Cells(1,1) = "Polska"
Worksheets("Arkusz1").Cells(1,1) = "Tekst do wyświetlenia"
Ogólna zasada jest więc taka, aby wszystko, co jest przypisywane do zmiennej String
, znajdowało się w cudzysłowie.
Jest jednak od tej reguły kilka odstępstw, które zostały opisane poniżej.
Pierwszą z nich jest bardzo popularna sytuacja, kiedy do zmiennej tekstowej chcesz przypisać inną zmienną tekstową.
Przyjrzyj się poniższemu przykładowi:
1
2
3
4
5
6
7
Sub przypisanieZmiennejTekstowej()
Dim a As String
Dim b As String
a = "Polska"
b = a
End Sub
W drugiej i trzeciej linijce powyższego kodu deklarowana jest obecność dwóch zmiennych typu tekstowego: a
i b
.
W piątej linijce do zmiennej a
przypisany zostaje tekst Polska.
W linijce 6 do zmiennej b
zostaje przypisana taka sama wartość, jaką zawiera w sobie zmienna a
.
W tej sytuacji a
ma oznaczać nazwę zmiennej, a nie przypisywany tekst, dlatego też nie dodajemy do tej nazwy cudzysłowu.
W ten sposób osiągnięty został zamierzony cel - najpierw do zmiennej a
przypisany został tekst Polska,
a następnie do zmiennej b
przypisano wartość zmiennej a
, więc po tej operacji zmienna b
również będzie miała wartość Polska.
Gdyby przypisując zmienną a
do zmiennej b
, jej nazwa została ujęta w cudzysłów, kompilator zinterpretowałby
to tak, jakbyś chciał do niej przypisać jednoliterowy tekst a. Po tej operacji zmienna a
miałaby więc wartość
Polska, natomiast zmienna b
przechowywałaby tekst a, czyli zupełnie niezgodnie z początkowymi intencjami.
Drugą sytuacją, w której wartość przypisywana do zmiennej tekstowej nie jest ujęta w cudzysłów,
jest przypisywanie do zmiennej tekstowej wartości nie będącej w rzeczywistości tekstem.
Typ String
jest najbardziej elastycznym ze wszystkich typów zmiennych, ponieważ można do niego przypisać w
zasadzie każdą dowolną wartość typu prymitywnego, nie powodując przy tym żadnego błędu w trakcie wykonywania programu.
Niezależnie od tego czy jest to ciąg znaków, liczba czy data, wszystko, co jest przypisywane do zmiennej tekstowej jest
traktowane przez kompilator jak tekst. Możesz więc przypisać do zmiennej typu String
liczbę 1, ale wartość
przechowywana przez tę zmienną nie będzie liczbą 1 lecz tekstem, składającym się tylko z pojedynczego znaku - cyfry 1.
Możesz mieć wątpliwości, czy jest jakaś różnica pomiędzy liczbą 1, a tekstem 1, dlatego poniżej został przytoczony
przykład, który powinien je rozwiać (przykład będzie wykorzystywał wszystkie omówione dotychczas elementy, dlatego przy
okazji będziesz mógł je sobie utrwalić):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Sub zmienneTekstowe()
Dim s As String
Dim t As String
Dim a As Long
Dim b As Long
s = 1
t = 2
a = 1
b = 2
Worksheets("Arkusz1").Cells(1,1) = s + t
Worksheets("Arkusz1").Cells(2,1) = a + b
End Sub
W wierszach 2-5 tego przykładu zadeklarowane zostały cztery zmienne: dwie zmienne typu tekstowego
(s
, t
) oraz dwie zmienne typu liczbowego (a
, b
).
W wierszach 8-9 do zmiennych tekstowych zostały przypisane liczby 1 i 2, natomiast w wierszach
12-13 te same liczby przypisano do zmiennych liczbowych. Pozornie więc zmienne tekstowe s
i t
oraz zmienne liczbowe a
i b
przechowują te same wartości - 1 i 2.
Jak się jednak za chwilę okaże nie do końca jest to prawdą.
W dwóch ostatnich wierszach przed zamknięciem procedury (15-16) wyświetlone zostają sumy poszczególnych
zmiennych - najpierw sumę zmiennych s
i t
, a potem zmiennych a
i b
.
Jeżeli uruchomisz powyższy kod, a potem zajrzysz do arkusza, zobaczysz, że w komórce A1 wyświetlona została liczba 12,
natomiast w komórce A2 liczba 3.
Wynika to oczywiście z różnych typów zmiennych, w których były przechowywane te wartości.
Kiedy dodajesz do siebie teksty (tak jak teksty 1 i 2 przechowywane w zmiennych s
i t
),
kompilator po prostu wypisuje je jeden za drugim (w tym przypadku wypisał więc obok siebie liczby 1 i 2, tworząc liczbę 12).
Kiedy natomiast zsumowałeś liczby 1 i 2 przechowywane w zmiennych liczbowych a
i b
, zostały one
zwyczajnie do siebie dodane, dając w wyniku 3.
Jak więc widać na powyższym przykładzie, mimo że zmienne typu String
są tak elastyczne i mogą przyjąć wszystkie
inne typy zmiennych, nie powinno się ich używać do celów innych niż przechowywanie tekstów, ponieważ może to doprowadzić do
niezamierzonych rezultatów.
Zmienne liczbowe (Byte, Integer, Long, Single, Double, Currency)
Liczbowe typy zmiennych omawiane są łącznie, ponieważ ich działanie jest niemal identyczne, a różnią się jedynie dopuszczalnym zakresem
wartości oraz ilością zajmowanej pamięci komputera.
W Visual Basic możesz korzystać z następujących typów zmiennych liczbowych: Byte
, Integer
, Long
,
Single
, Double
oraz Currency
.
Deklaracje poszczególnych typów zmiennych wyglądają następująco:
Wartością domyślną dla wszystkich typów liczbowych jest 0.
Zmienne liczbowe nie są już tak elastyczne jak zmienne tekstowe String
. Jak się już dowiedziałeś,
do zmiennej tekstowej bez problemu można przypisać zmienną liczbową, jednak operacja w odwrotną stronę nie
zawsze zadziała.
Niemożliwe jest na przykład przypisanie do zmiennej liczbowej wartości tekst. Kompilator w żaden sposób
nie będzie potrafił przełożyć słowa tekst na liczbę i wyświetli błąd Run-time error '13':
Type mismatch.
Zresztą możesz przekonać się o tym sam, wklejając i uruchamiając poniższy kod:
1
2
3
4
Sub blednePrzypisanie
Dim a As Long
a = "tekst"
End Sub
Są jednak sytuacje, w których przypisanie tekstu do zmiennej liczbowej nie spowoduje żadnego błędu. Dzieje się tak w sytuacji,
gdy tekst, który ma być przypisany, jest po prostu tekstową reprezentacją jakiejś liczby.
Spójrz na poniższy fragment kodu:
1
2
3
4
Sub przypisanieTekstuDoZmiennejLiczbowej
Dim a As Long
a = "1"
End Sub
W trzeciej linii tego kodu do zmiennej typu Long
przypisana zostaje wartość tekstowa "1". Jak dowiedziałeś
się w poprzednim podrozdziale, poświęconym zmiennym tekstowym, wszystko, co zawarte jest w cudzysłowie, jest tekstem. Nie
inaczej jest w tym przypadku - wartość "1" nie jest liczbą, lecz tekstem, ponieważ znajduje się w cudzysłowie. Jednak
w tym przypadku kompilator potrafi przełożyć sobie tekst 1 na liczbę, dlatego przypisuje do zmiennej a
liczbę 1, nie zgłaszając przy tym żadnego błędu.
Przejdźmy teraz do szczegółowego omówienia każdego z liczbowych typów zmiennych. Jak już wcześniej wspomniałem we wstępie
podrozdziału poświęconego zmiennym liczbowym, różnią się one między sobą jedynie dopuszczalnym zakres wartości, szczegółowością
przedstawiania części ułamkowych oraz wielkością pamięci, którą zajmują.
Byte
Zmienna typu Byte
obsługuje tylko liczby naturalne od 0 do 255.
Powinieneś jej używać tylko w sytuacji, kiedy masz pewność, że nie przyjmie ona wartości spoza tego zakresu.
Jeżeli w trakcie wykonywania Twojego programu dojdzie do próby przypisania do zmiennej typu Byte
liczby większej niż 255 lub liczby ujemnej, kompilator przerwie działanie programu i wyświetli błąd Run-time error '6' Overflow.
Jeżeli przypiszesz do zmiennej typu Byte
liczbę, która nie jest liczbą naturalną, zostanie ona zaokrąglona, np. przy
próbie przypisania liczby 1.2 zmienna przybierze wartość 1, natomiast przypisując liczbę 1.5 nadasz zmiennej wartość 2.
Pojedyncza zmienna typu Byte
zajmuje w pamięci tylko jeden bajt i jest to najmniej pamięciożerny typ zmiennej.
Dlatego jeśli jesteś pewien, że zmienna liczbowa nie przekroczy zakresu 0-255, warto zadeklarować ją jako typ Byte
aby
zaoszczędzić trochę pamięci i przyspieszyć tym samym działanie programu. Oczywiście w omawianych dotychczas niewielkich programach,
korzystających tylko z jednej zmiennej, różnica w prędkości działania programu nie byłaby zauważalna, ale w bardziej rozbudowanych
aplikacjach, gdzie znajdują się setki czy nawet tysiące takich zmiennych, korzyści ze stosowania odpowiednich rodzajów zmiennych
mogą być całkiem znaczne.
Integer
Zmienna typu Integer
obsługuje liczby całkowite z zakresu od -32 768 do 32 767.
Jeżeli w trakcie wykonywania Twojego programu dojdzie do próby przypisania do zmiennej typu Integer
liczby spoza podanego zakresu, kompilator przerwie działanie programu i wyświetli błąd Run-time error '6' Overflow.
Zaokrąglanie ułamków odbywa się identycznie jak w przypadku opisanej powyżej zmiennej typu Byte
.
Pojedyncza zmienna typu Integer
zajmuje dwa bajty pamięci.
Long
Zmienna typu Long
obsługuje liczby całkowite z zakresu od -2 147 483 648 do 2 147 483 647.
Jeżeli w trakcie wykonywania Twojego programu dojdzie do próby przypisania do zmiennej typu Long
liczby spoza podanego zakresu,
kompilator przerwie działanie programu i wyświetli błąd Run-time error '6' Overflow.
Zaokrąglanie ułamków odbywa się identycznie jak w przypadku zmiennych typu Byte
i Integer
.
Pojedyncza zmienna typu Long
zajmuje cztery bajty pamięci.
Single
Zmienna typu Single
obsługuje liczby rzeczywiste i obejmuje wartości z zakresu od -3.4⋅1038
do -1.4⋅10-45 dla wartości ujemnych oraz od 1.4⋅10-45 do 3.4⋅1038
dla wartości dodatnich.
Jeżeli w trakcie wykonywania Twojego programu dojdzie do próby przypisania do zmiennej typu Single
liczby spoza podanego zakresu,
kompilator przerwie działanie programu i wyświetli błąd Run-time error '6' Overflow.
Pojedyncza zmienna typu Single
zajmuje cztery bajty pamięci.
Double
Zmienna typu Double
obsługuje liczby rzeczywiste i obejmuje wartości z zakresu od -1.80⋅10308
do -4.94⋅10-324 dla wartości ujemnych oraz od 4.94⋅10-324 do 1.80⋅10308
dla wartości dodatnich..
Pojedyncza zmienna typu Double
zajmuje osiem bajtów pamięci.
Currency
Zmienna typu Currency
obsługuje liczby z zakresu od -922 337 203 685 477.5808 do 922 337 203 685 477.5807.
Pojedyncza zmienna typu Currency
zajmuje osiem bajtów pamięci.
Głównym zastosowaniem typu Currency
jest wykonywanie obliczeń, w których niezbędne jest uzyskanie dokładnych wyników,
takich jak np. wyliczenia finansowe.
Zmienne typu Single
i Double
mają tę wadę, że nie zawsze zwracają nieprecyzyjne wyniki, przykładowo dla działania
2 + 2 zamiast wyniku 4, możesz czasem otrzymać 3.99999995. Stosując zmienne typu Currency
zawsze uzyskasz dokładny wynik,
jednak mogą one znacznie spowolnić działanie aplikacji w przypadku wykonywania wielu obliczeń.
Zmienne daty i czasu (Date)
Zmienne daty i czasu, jak sama nazwa wskazuje, służą do przechowywania informacji o dacie i czasie.
Deklaracja zmiennej jako zmiennej daty i czasu wygląda następująco:
Zmienna typu Date
obsługuje daty z zakresu 1 stycznia 100 do 31 grudnia 9999.
Próba przypisania daty spoza tego zakresu zakończy się wyświetleniem błędu Run-time error 5: Invalid procedure
Call or argument
Jeżeli do zmiennej typu Date
chcesz ręcznie przypisać określoną datę, musisz otoczyć ją z obu stron
znakiem #, a poszczególne składniki daty oddzielić od siebie znakiem myślnika (-) lub slasha (/).
Poniżej znajdują się przykłady przypisania do zmiennej daty 21 kwietnia 2010:
Podobnie należy postępować z przypisywaniem do zmiennej typu Date
czasu - przypisywana wartość musi być z obu stron otoczona
znakiem #, a poszczególne składniki czasu powinny być od siebie oddzielone dwukropkiem (:).
Obowiązkowym składnikiem czasu przypisywanego do zmiennej są godziny i minuty. Wartość sekundowa może zostać pominięta, w takiej sytuacji
sekundy domyślnie otrzymają wartość 0.
Poniżej znajdują się przykłady przypisania czasu do zmiennej typu datowego:
Do zmiennej typu datowego możesz też przypisać wartość będącą połączeniem daty i czasu. Tak jak w omówionych wyżej przypadkach
przypisywana wartość musi być otoczona znakiem #, obowiązują też opisane wyżej reguły zapisywania dat i czasu.
Poniżej znajdują się przykłady równoczesnego przypisania do zmiennej typu datowego daty i czasu:
czas = #21-04-2010 12:00#
czas = #2010/4/21 13:14:15#
Bądź ostrożny przy ręcznym wpisywaniu dat!
Edytor postępuje bardzo nielogicznie przy interpretowaniu ich formatu dat.
Jeżeli rozpoczniesz wpisywanie daty od roku, kolejna podana liczba jest interpretowana jako numer miesiąca, a ostatnia liczba jako numer dnia -
tu akurat wszystko przebiega logiczne i bez żadnych wątpliwości.
Gorzej wygląda sprawa z zapisywaniem dat w formacie, w którym rok podany jest na końcu. Po wpisaniu daty w takim właśnie formacie,
edytor sprawdza najpierw pierwszą podaną liczbę i jeżeli mieści się ona w zakresie 1-12, a więc może odpowiadać numerowi miesiąca,
to tak jest właśnie interpretowana. Druga podana liczba jest w takiej sytuacji numerem dnia. Jeżeli natomiast pierwsza podana liczba
jest większa niż 12, wówczas edytor VBA interpretuje ją jako numer dnia, a dopiero druga liczba jest traktowana jako numer miesiąca.
Niestety, widać tu pewną niekonsekwencję, więc trzeba zachować czujność przy ręcznym wpisywaniu dat, ponieważ moment nieuwagi może
doprowadzić do błędów w działaniu programu.
Dziwne sytuacje dzieją się też, przy próbie określenia roku poprzez wpisanie tylko jego dwóch ostatnich cyfr.
Omówienie wszystkich możliwych sytuacji zajęłoby zbyt wiele miejsca, dlatego nie będziemy się nad tym rozwodzić.
Najbezpieczniej jest po prostu wpisywać zawsze pełny numer roku, co pozwoli uniknąć niepotrzebnych kłopotów.
Pamiętaj, że zawsze po ręcznym wpisaniu daty w edytorze VBA, jej format zostanie automatycznie zmieniony do postaci #mm/dd/yyyy#.
Jest to moment, w którym możesz sprawdzić, czy sposób, w jaki edytor zinterpretował wpisaną przez Ciebie datę, odpowiada Twoim
oczekiwaniom.
Podobnie, po ręcznym wpisaniu czasu, edytor VBA automatycznie zmieni jej format do postaci #hh:mm:ss (AM/PM)#, gdzie data zapisana
jest w systemie 12-godzinnym, a dopisek po dacie informuje czy godzina dotyczy pierwszej czy drugiej części doby (AM - godziny między
00:00 a 12:00; PM - godziny między 12:00 a 24:00).
Jeżeli wpiszesz w edytorze datę, która nie ma prawa istnieć (np. podasz 13 jako numer miesiąca lub 32 jako numer dnia), zostanie
ona podświetlona na czerwono, a makro nie zadziała, ponieważ przy próbie jego uruchomienia kompilator zgłosi błąd
Compile error: Syntax error.
Bardzo ważną cechą zmiennych typu Date
jest to, że każda z nich posiada swoją reprezentację liczbową.
W liczbie reprezentującej daną datę część całkowita określa ile dni upłynęło od 30 grudnia 1899 do
tej daty, natomiast część ułamkowa jest reprezentacją czasu i określa jaka część doby upłynęła od północy.
Dlatego też, do zmiennych typu datowego bez problemu można przypisać liczby i wykonywać na nich operacje arytmetyczne.
Należy jednak wziąć pod uwagę to, co zostało powiedziane na wstępie omawiania typu datowego - typ ten obsługuje tylko daty z
zakresu 01.01.100 - 31.12.9999. Dlatego też liczby, które mogą zostać przypisane do zmiennej tego typu, również
mają ograniczony zakres i muszą mieścić się w przedziale od -657 434 do 2 958 465. Próba przypisania
do zmiennej typu Date
liczby spoza tego zakresu spowoduje wyświetlenie błędu Run time error '6': Overflow.
W poniższej tabelce znajduje się kilka przykładów dat i reprezentujących ich liczb:
DATA | LICZBA |
30 grudnia 1899 | 0 |
6 lipca 2009 | 40 000 |
13 sierpnia 1872 | -10 000 |
6 lipca 2009, 6:00 | 40 000.25 |
13 sierpnia 1872, 6:00 | -10 000.25 |
Zmienne logiczne (Boolean)
Zmienna logiczna określana jest w VBA słowem kluczowym Boolean
.
Deklaracja tej zmiennej wygląda następująco:
Zmienne typu Boolean
mogą przyjmować dwie wartości: True
oraz
False
.
Domyślną wartością dla zmiennych typu Boolean
jest False
.
Oprócz wartości True
i False
, do zmiennej typu Boolean
można też przypisywać liczby.
W takiej sytuacji kompilator traktuję liczbę 0 jako wartość False
, natomiast każdą inną liczbę (także ujemne)
jako równowartość True
.
Do zmiennej typu Boolean
można też przypisać teksty True oraz False. Próba przypisania
jakiegokolwiek innego tekstu zakończy się wyświetleniem błędu Run-time error '13': Type mismatch.
Zmienne ogólne (Variant)
Typ Variant
jest jak dżoker w kartach - zastępuje wszystkie inne typy zmiennych. Do zmiennej typu Variant
możesz przypisać dowolną wartość.
Deklaracja zmiennej typu ogólnego wygląda następująco:
Możesz sobie w tym miejscu pomyśleć - skoro typ Variant
jest taki uniwersalny, zastępuje wszystkie inne,
wszystko można do niego przypisać - dlaczego nie wykorzystywać go dla każdej zmiennej, zamiast bawić się w
jakieś rozdzielanie zmiennych na tekstowe, liczbowe czy logiczne.
Owszem, przy zastosowaniu takiej zasady pisanie programów mogłoby być bardzo wygodne, ale ich późniejsze utrzymywanie i
korzystanie z nich już niekoniecznie.
Zmienne typu Variant
zajmują o wiele więcej pamięci (np. dla pojedynczej liczby 16 bajtów, podczas
gdy zmienna typu Integer
tylko 2 bajty), co znacznie obciążą programy i zwalnia prędkość ich działania.
Drugą istotną wadą deklarowania zmiennych jako Variant
jest utrata kontroli typów. Jeżeli deklarujemy jakąś
zmienną z określonym typem, pracując nad kodem na pierwszy rzut oka widać jakie wartości mogą być przypisane do tej zmiennej.
Jeżeli przypadkowo przypiszemy do tej zmiennej wartość innego typu, zostaniemy o tym poinformowaniu już na etapie kompilacji.
W przypadku zmiennych typu Variant
kompilator nie zgłosi żadnych zastrzeżeń, bo zmienne tego typu akceptują
wszystkie wartości, więc istnieje duże ryzyko, że o błędzie dowiemy się bardzo późno.
Oczywiście zdarzają się też sytuacje, w których zmienne typu Variant
są najlepszym lub nawet jedynym rozwiązaniem.
Przykłady takich sytuacji będziemy omawiać w dalszych lekcjach kursu.