Lekcja została podzielona na następujące części:
Stosowanie w kodzie zmiennych
Przypomnij sobie przykładowy kod z poprzedniej lekcji, który wypisywał do arkusza poszczególne potęgi dwójki i trójki:
1
2
3
4
5
6
7
8
9
10
11
12
Sub wypisywaniePoteg()
Worksheets("Arkusz1").Cells(1, 1) = 1
Worksheets("Arkusz1").Cells(2, 1) = 2
Worksheets("Arkusz1").Cells(3, 1) = 4
Worksheets("Arkusz1").Cells(4, 1) = 8
Worksheets("Arkusz1").Cells(5, 1) = 16
Worksheets("Arkusz2").Cells(1, 1) = 1
Worksheets("Arkusz2").Cells(2, 1) = 3
Worksheets("Arkusz2").Cells(3, 1) = 9
Worksheets("Arkusz2").Cells(4, 1) = 27
Worksheets("Arkusz2").Cells(5, 1) = 81
End Sub
1
2
3
4
5
6
7
8
9
10
11
12
Sub wypisywaniePoteg()
Worksheets("Arkusz1").Cells(1, 1) = 1
Worksheets("Arkusz1").Cells(2, 1) = 2
Worksheets("Arkusz1").Cells(3, 1) = 4
Worksheets("Arkusz1").Cells(4, 1) = 8
Worksheets("Arkusz1").Cells(5, 1) = 16
Worksheets("Arkusz2").Cells(1, 1) = 1
Worksheets("Arkusz2").Cells(2, 1) = 3
Worksheets("Arkusz2").Cells(3, 1) = 9
Worksheets("Arkusz2").Cells(4, 1) = 27
Worksheets("Arkusz2").Cells(5, 1) = 81
End Sub
Jak widzisz, w każdej linijce powyższego kodu wartość poszczególnych potęg jest obliczana w pamięci i ręcznie przypisywana do kolejnych komórek arkusza.
Oczywiście w poważnych aplikacjach taki sposób programowania nie ma racji bytu, chociażby dlatego, że bardzo łatwo się pomylić przy liczeniu czegokolwiek w pamięci. Zresztą przy większych potęgach trzeba byłoby niewątpliwie sięgnąć po kalkulator, a przecież nie po to piszemy programy, aby korzystać przy tym z kalkulatora lub obliczać coś w pamięci.
Sposobem na obejście tego problemu jest zastosowanie zmiennych.
Zmienna to taki element programu, do którego można przypisać jakąś wartość.
Po przeanalizowaniu poniższego przykładu, zrozumiesz jak działają zmienne i jak się z nich korzysta.
Najpierw zmodyfikuj kod z poprzedniej lekcji do postaci takiej, jak przedstawiono w poniższej ramce. Pod ramką z kodem znajdziesz jego szczegółową analizę.
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
Sub wypisywaniePoteg()
Dim potega As Long
potega = 1
Worksheets("Arkusz1").Cells(1, 1) = potega
potega = potega * 2
Worksheets("Arkusz1").Cells(2, 1) = potega
potega = potega * 2
Worksheets("Arkusz1").Cells(3, 1) = potega
potega = potega * 2
Worksheets("Arkusz1").Cells(4, 1) = potega
potega = potega * 2
Worksheets("Arkusz1").Cells(5, 1) = potega
'========================
potega = 1
Worksheets("Arkusz2").Cells(1, 1) = potega
potega = potega * 3
Worksheets("Arkusz2").Cells(2, 1) = potega
potega = potega * 3
Worksheets("Arkusz2").Cells(3, 1) = potega
potega = potega * 3
Worksheets("Arkusz2").Cells(4, 1) = potega
potega = potega * 3
Worksheets("Arkusz2").Cells(5, 1) = potega
End Sub
Na pierwszy rzut oka po wprowadzeniu zmiennej cała procedura wydaje się być o wiele bardziej skomplikowana, a kod znacznie dłuższy. (Kod rzeczywiście jest znacznie dłuższy, ale wynika to po części z pustych wierszy, wstawionych dla zwiększenia czytelności).
Jeżeli przyjrzysz się jednak uważniej powyższej procedurze, zauważysz, że większość linijek kodu jest do siebie bardzo podobna, a czasem wręcz identyczna (Powtarzanie kilka razy podobnych poleceń to bardzo zła praktyka, ale na razie nie posiadasz jeszcze wiedzy pozwalającej na uniknięcie tego błędu. W kolejnych lekcjach nauczysz się korzystać m.in. z funkcji i pętli, dzięki którym cała powyższa procedura zostanie skrócona do maksymalnie kilku linijek).
Pierwszą i ostatnią linijkę powyższego kodu znasz już z poprzedniej lekcji. Jest to po prostu Function" title="Jak otwierać i zamykać procedury?"> otwarcie i zamknięcie procedury.
W wierszu 2 pojawia się już jednak niespotykane dotychczas polecenie:
2
Dim potega As Long
2
Dim potega As Long
Przedstawiona linijka kodu odpowiada za deklarację zmiennej. Termin deklaracja zmiennej oznacza poinformowanie kompilatora VBA, że w tej procedurze pojawi się zmienna o takiej nazwie i takim typie, jak podano w wierszu deklaracji.
Kompilator VBA możesz sobie wyobrazić jako nadzorcę przepływu danych w kodzie. W momencie zadeklarowania zmiennej
(czyli wierszu 2) kompilator zapisuje sobie w pamięci, że w tej procedurze pojawi się zmienna
potega
.
Czy deklarowanie zmiennych jest konieczne?
Zasadniczo zadeklarowanie zmiennej nie jest koniecznością i procedura równie dobrze zadziałałaby, gdyby ten wiersz został pominięty.
W takiej sytuacji kompilator nie wie jednak o istnieniu tej zmiennej, aż do momentu jej pojawienia się w kodzie (więc w powyższym
przykładzie dopiero w linijce 4 zapisałby sobie w pamięci, że w programie istnieje zmienna
potega
i równocześnie dopisałby do niej wartość).
Na pierwszy rzut oka może się to wydawać wygodne - po co marnować czas na pisanie dodatkowej linijki i wcześniejsze informowanie kompilatora o zmiennych, skoro równie dobrze można tę część pominąć?
Pomijanie deklaracji zmiennych może jednak prowadzić do istotnych i trudnych do wychwycenia pomyłek!
Temat ten zostanie dokładniej omówiony w dalszej części tej lekcji.
Błędy wynijakące z braku deklaracji zmiennych są trudne do wykrycia, dlatego warto, żebyś już od początku swojej nauki programowania wyrobił w sobie nawyk deklarowania zmiennych.
Postać ogólna deklaracji zmiennej wygląda następująco:
Dim nazwa [As typ_zmiennej]
Dim nazwa [As typ_zmiennej]
Słowem kluczowym odpowiedzialnym za deklarowanie zmiennej jest Dim
.
Po tym słowie następuje nazwa zmiennej. Jeżeli chodzi o przyjęte reguły nazewnictwa, obowiązują podobne zasady jak przy
nazywaniu funkcji i procedur,
omówione w poprzedniej lekcji).
Po nazwie zmiennej powinno się pojawić słowo kluczowe As
, po którym zostaje określony typ zmiennej.
Dostępne typy zmiennych poznasz w kolejnej lekcji, która w całości będzie poświęcona
typom zmiennych.
Na potrzeby tej lekcji wprowadzimy tylko jeden typ zmiennej - Long
.
Jeżeli zmienna zostaje zadeklarowana z typem Long
, oznacza to, że może ona jako swoją wartość przyjmować liczby całkowite
z zakresu od -2 147 483 648 do 2 147 483 647.
Określenie typu zmiennych może zostać pominięte, jednak w takiej sytuacji zmienna zostaje domyślnie zadeklarowana
jako zmienna typu Variant
, co, jak dowiesz się w kolejnej lekcji, nie jest dobrą praktyką.
Język VBA umożliwia również deklarowanie kilku zmiennych w jednej linijce, co zostało przedstawione w poniższej ramce z kodem:
Dim zmienna1 As Long,
zmienna2 As Long,
zmienna3 As Long
Dim zmienna1 As Long,
zmienna2 As Long,
zmienna3 As Long
Chociaż wszystkie zadeklarowane w tej linijce zmienne posiadają ten sam typ danych - Long
- zwróć uwagę,
że do każdej z nich został on oddzielnie przypisany.
Gdyby powyższa deklaracja zmiennych została zapisana w takiej postaci:
Dim zmienna1, zmienna2, zmienna3 As Long
to wbrew pozorom, zmienne zmienna1
i zmienna2
nie posiadałyby typu Long
.
Każde przypisanie typu dotyczy tylko tej zmiennej, przy której bezpośrednio się znajduje (w tym przypadku zmienna3
),
a nie całej linijki. W rzeczywistości do zmiennych zmienna1
oraz zmienna2
nie byłby więc przypisany
żaden typ danych i, jak wspomniałem przed momentem, otrzymałyby one domyślny typ danych Variant
, czego zdecydowanie
powinno się unikać.
Dim zmienna1, zmienna2, zmienna3 As Long
zmienna1
i zmienna2
nie posiadałyby typu Long
.Każde przypisanie typu dotyczy tylko tej zmiennej, przy której bezpośrednio się znajduje (w tym przypadku
zmienna3
),
a nie całej linijki. W rzeczywistości do zmiennych zmienna1
oraz zmienna2
nie byłby więc przypisany
żaden typ danych i, jak wspomniałem przed momentem, otrzymałyby one domyślny typ danych Variant
, czego zdecydowanie
powinno się unikać.
W jednej procedurze nie mogą być zadeklarowane dwie zmienne o takiej samej nazwie.
Wróćmy do analizy przedstawionego wcześniej kodu.
Kiedy wykonywanie kodu dociera do wiersza 4, w programie jest już zadeklarowana zmienna typu liczbowego
o nazwie potega
(została zadeklarowana w wierszu 3). Na razie jednak kompilator otrzymał
tylko informację o istnieniu takiej zmiennej, nie przechowuje ona jeszcze żadnej wartości (a w zasadzie przechowuje wartość domyślną, czyli 0).
Taki stan rzeczy nie potrwa jednak długo, bo już w czwartym wierszu kodu zostaje do niej przypisana wartość:
4
potega = 1
4
potega = 1
Tak jak zostało przed chwilę wspomniane, w tej linijce kodu do zmiennej potega
zostaje przypisana wartość 1.
Kompilator zapisuje więc w swojej pamięci przy zmiennej potega
wartość 1.
Od tej pory, kiedy kompilator napotka w kodzie zmienną potega
, będzie ją interpretował jako liczbę 1,
tak długo, aż do tej zmiennej zostanie przypisana jakaś inna wartość.
Jak więc widzisz, przypisywanie wartości do zmiennej jest bardzo proste.
Wystarczy napisać nazwę zmiennej, postawić znak równości =
, a następnie napisać wartość,
jaka ma zostać do tej zmiennej przypisana.
W wierszu 5 znajduje się znana Ci już z poprzedniej lekcji operacja wyprintowania wartości
do komórki arkusza:
5
Worksheets("Arkusz1").Cells(1, 1) = potega
5
Worksheets("Arkusz1").Cells(1, 1) = potega
W tej operacji, w komórce A1 arkusza Arkusz1 zostaje wyświetlona wartość znajdująca się po znaku równości. Zwróć jednak uwagę, że tym razem po znaku równości nie występuje liczba, lecz nazwa zmiennej. Na pierwszy rzut oka mogłoby się wydawać, że kompilator VBA wypisze w arkuszu tekst potega. Tak się jednak nie stanie.
Pomiędzy nazwami zmiennych, a tekstami istnieje zasadnicza różnica w zapisie i interpretacji. Występujący w kodzie tekst można rozpoznać po tym, że jest ujęty w cudzysłów. Nazwy zmiennych są natomiast zapisane bez cudzysłowia.
Aby w powyższym przykładzie w arkuszu pojawił się napis potega, tekst ten musiałby być ujęty w kodzie w cudzysłów,
tak jak poniżej:
Worksheets("Arkusz1").Cells(1, 1) = "potega"
Worksheets("Arkusz1").Cells(1, 1) = "potega"
W naszym przykładzie słowo potega
znajduje się bez cudzysłowia, w związku z czym oznacza
odniesienie do zmiennej o takiej właśnie nazwie. Jak już wcześniej wspomniałem, kompilator interpretuje
zmienną jako wartość, która jest w tej zmiennej aktualnie przechowywana. Zmienna potega
aktualnie
przechowuje wartość 1, która została do niej przypisana w wierszu 4, dlatego też
wyświetlenie w komórce A1 zmiennej potega
jest równoznaczne z wyświetleniem w niej liczby 1.
W kolejnym wierszu arkusza ma zostać wyświetlona kolejna potęga dwójki.
Dlatego też w linii 7 kodu:
7
potega = potega * 2
zmienna potega
zostaje pomnożona przez 2.
Ponieważ dotychczas zmienna ta przechowywała wartość 1, teraz przyjmie wartość 2.
7
potega = potega * 2
potega
zostaje pomnożona przez 2.
Ponieważ dotychczas zmienna ta przechowywała wartość 1, teraz przyjmie wartość 2.
W kolejnych wierszach (8-18), wartość zmiennej potega
jest na przemian wyświetlana
w arkuszu i mnożona przez 2, tak by uzyskać kolejną potęgę dwójki.
Po wyświetleniu pięciu kolejnych potęg dwójki przyszedł czas na zajęcie się potęgami liczby 3.
Zwróć uwagę, że zmienna potega
posiada w tym momencie wartość 16, dlatego aby przygotować ją na przechowywanie
wartości poszczególnych potęg trójki, należy zresetować jej wartość do liczby 1
(dzieje się tak w wierszu 19).
W kolejnych wierszach kodu, wartość zmiennej potega
jest na przemian wyświetlana w arkuszu i mnożona przez 3,
aby uzyskać kolejne potęgi trójki (a więc operacje analogiczne do tych, omówionych przed chwilą przy okazji tworzenia i wyświetlania
kolejnych potęg dwójki).
Konsekwencje niedeklarowania zmiennych
Przy okazji omawiania kodu przedstawionego na początku lekcji, wspomniałem o niebezpieczeństwach wynikających z niedeklarowania zmiennych.
Przeanalizuj teraz poniższy kod, który na pierwszy rzut oka niczym nie różni się od tego, który został przed chwilą omówiony.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Sub wypisywaniePoteg()
Dim potega As Long
potega = 1
Worksheets("Arkusz1").Cells(1, 1) = potega
potega = potega * 2
Worksheets("Arkusz1").Cells(2, 1) = potega
potega = ptoega * 2
Worksheets("Arkusz1").Cells(3, 1) = potega
potega = potega * 2
Worksheets("Arkusz1").Cells(4, 1) = potega
potega = potega * 2
Worksheets("Arkusz1").Cells(5, 1) = potega
End Sub
Jeżeli jednak przyjrzysz się uważnie temu fragmentowi kodu, zauważysz, że w linijce 10 zamiast
zmiennej potega
, wpisano ptoega
.
Co dzieje się w takiej sytuacji?
W drugim wierszu tego kodu kompilator napotyka na deklarację zmiennej potega
,
zapisuje ją więc w swojej pamięci, a w kolejnym wierszu (4) przypisuje do niej wartość 1.
W następnych linijkach (5-9) wszystko odbywa się dokładnie tak, jak w omówionym wcześniej przykładzie -
kompilator na przemian przypisuje do zmiennej potega
wartość działania potega * 2
, a potem wyświetla
wartość tej zmiennej w arkuszu.
Jednak w kolejnej linijce (10) sytuacja się komplikuje. Otóż kompilator otrzymuje informację,
że ma przypisać do zmiennej potega
nie jej wartość pomnożoną razy dwa, lecz wartość zmiennej
ptoega
pomnożoną przez dwa.
Dla każdej osoby czytającej ten kod byłoby oczywiste, że chodzi o zmienną potega
i jest to po prostu zwykła
literówka. Komputer jednak nie jest tak bystry i traktuje ją jako zupełnie nową zmienną. Stwierdza więc, że w swojej
pamięci nie ma jeszcze zmiennej o nazwie ptoega
, dlatego dopisuje ją do listy występujących w
programie zmiennych (tak jak wspomniano wcześniej w tej lekcji - jeżeli kompilator napotka na zmienną, która nie była
zadeklarowana, sam ją sobie automatycznie deklaruje).
Zwróć uwagę, że zmienna ta dopiero co pojawiła się w programie i nie przypisano do niej jeszcze żadnej wartości
(ma więc domyślną wartość - 0). Tak więc zgodnie z tą instrukcją:
10
potega = ptoega * 2
kompilator wykona działanie 0*2
, a wynik (0
) przypisze do zmiennej potega
.
10
potega = ptoega * 2
0*2
, a wynik (0
) przypisze do zmiennej potega
.