Ustawienia modułu
2017-03-08Dzisiaj coś szybkiego czyli ustawienia modułu VBA. Rzecz niby oczywista ale… czy wiecie:
- jak się chronić przed popełnianiem literówek?
- czym się różni Option Compare Binary od Option Compare Text?
- w jakiej sytuacji Option Base 1 nie rozpocznie nam tablicy od 1?
Zapraszam do czytania i oczywiście czekam na pytania od was na michal@hintmine.com :)
W tym poście postaram się odpowiedzieć na pytania:
1. Jakie są najpopularniejsze ustawienia modułu?
2. Podstawa podstaw czyli Option Explicit dlaczego jest tak ważne?
3. Gdzie się je wpisuje i czy mogą wpisywać się same?
4. Jak korzystać z Option Compare i jakie są alternatywy?
5. Do czego służy Option Base 1 i kiedy to ustawienie nie działa?
No to jedziemy :)
1. Ustawienia modułu
Żeby zastosować ustawienia dla modułu, trzeba wpisać jedno z poniższych poleceń na samym jego początku (przed wszystkimi procedurami)
Najczęściej używamy:
- Option Explicit – sprawia, że każda zmienna, której chcemy użyć w kodzie, musi być wcześniej zadeklarowana (np. Dim kogut). Ale zaraz zaraz, skoro to ustawienie wymusza na mnie deklarację każdej zmiennej to… po co mam to włączać i utrudniać sobie życie ? Czytajcie dalej to zobaczycie (będzie o tym w punkcie 2) :)
- Option Compare {Binary | Text | Database} – służy do ustawienia tego jak w naszym programie mają być porównywane teksty. Dokładne wyjaśnienie wraz z przykładami opisuje punkt 3
- Option Base 1 – powoduje, że elementy tablicy są domyślnie numerowane od 1 a nie od 0. Oczywiście z pewnymi wyjątkami :) (więcej na ten temat będzie w pkt 4)
2. Option Explicit dlaczego jest takie ważne?
Dzięki stosowaniu Option Explicita unikniemy wszystkich problemów związanych z tzw. „literówkami” :)
Literówki były, są i będą, nie unikniemy ich. KAŻDY popełniał, popełnia i będzie popełniał literówki ! No to co w nich złego ? Czemu mamy się ich obawiać ?
Ano literówki nie są dobre dlatego, że w VBA popełniając literówkę, automatycznie tworzy nam się z tej literówki nowa zmienna (tzw. niejawna deklaracja zmiennych). Najlepiej wyjaśni to przykład poniżej.
1 2 3 4 5 6 7 8 9 |
Sub prostokat() Dim boka Dim bokb Dim pole boka = 4 bokb = 5 pole = boka * bob MsgBox pole End sub |
Uruchamiając program spodziewaliście się pewnie, że w linijce z mnożeniem będziemy mieć błąd (bo przecież nie ma w kodzie deklaracji zmiennej bob). A tu… niespodzianka :)
Błędu nie ma, bo jak wspomniałem wyżej VBA obsługuje niejawną deklarację zmiennych czyli tak po naszemu VBA sam „stworzył” sobie zmienną bob. Co więcej zmienna ta nie ma żadnej wartości (jest empty), bo przecież nikt niczego nie przypisał do bob. W takim razie w mnożeniu bob potraktowany jest jak zero.
Linijka:
1 |
pole = boka * bob |
to tak naprawdę
1 |
pole = 4 * 0 |
Dlatego program wyświetla 0. Można to dobrze podejrzeć wykonując program krokowo (F8).
A teraz napiszcie na górze modułu słowa Option Explicit i spróbujcie odpalić go jeszcze raz…
NIE PRZESTRASZCIE SIĘ BŁĘDU tak właśnie ma być :) Jeżeli zobaczycie takie okienko z błędem TO ZNACZY ŻE WSZYSTKO DZIAŁA !
„Variable not defined” oznacza właśnie, że nasz edytor nie uruchomi nam programu, bo wykrył, że używamy w kodzie słowa, które nie zostało „zadeklarowane” za pomocą Dim.
Czyli:
- albo zapomnieliśmy zadeklarować jakiejś zmiennej
- albo mamy gdzieś literówkę (to właśnie nasz bob)
Skąd macie wiedzieć która z powyższych sytuacji się wydarzyła ? gdzie szukać naszej literówki ?
Spokojnie edytor VBA zrobi wszystko za nas :)
Na oknie z błędem naciskamy OK, okno zniknie a my zobaczymy zaznaczone na niebiesko DOKŁADNIE TO SŁOWO, które jest felerne (tj. ma literówkę lub nie zostało zadeklarowane) tak jak na obrazku:
Tutaj mała uwaga dla początkujących, w VBA można deklarować zmienne i nie trzeba podawać ich typów (opiszę to w innym poście). Czyli mówiąc prościej żeby zrobić deklarację zmiennej wystarczy napisać Dim i podać jej nazwę.
1 |
Dim kogut |
Dlatego osoby, które zaczynają przygodę z programowaniem mogą spokojnie korzystać z Option Explicit bez konieczności roztrząsania co to jest integer, czy na 2 bajtach można zapisać liczbę 32769 czy też nie i czym się różni liczba zmiennoprzecinkowa pojedynczej precyzji od liczby zmiennoprzecinkowej podwójnej precyzji :)
Czyli Option Explicit jest ważne i używamy go żeby nie tracić czasu na szukanie literówek w programie. Czy musimy zawsze pisać go ręcznie ? Na to pytanie odpowie pkt 3.
3. Gdzie się je wpisuje i czy mogą wpisywać się same?
Jak już wspominałem klauzule Option pisze się na samej górze modułu, nad jakąkolwiek procedurą. Ale edytor VBA może dodawać Option Explicit (i tylko Option Explicit) za nas, za każdym razem jak tworzymy moduł. Gdzie to włączyć ?
W edytorze VBA wchodzimy w Tools –> Options i zaznaczamy ptaszka przy „Require Variable Declaration” (vide obrazek poniżej).
UWAGA !!! po zaznaczeniu tego ptaszka…. NIC SIĘ NIE STANIE, tzn. chodzi o to, że prawo nie działa wstecz. Jak zaznaczymy ptaszka, to dopiero każdy NOWO DODANY moduł będzie miał automatycznie wstawioną klauzulę Option Explicit, stare moduły, które Option Explicita nie miały, nadal nie będą go miały (trzeba go im dopisać ręcznie :)
4. Jak korzystać z Option Compare i jakie są alternatywy?
Tak naprawdę raczej rzadko kiedy będziecie zmuszeni używać tych ustawień. Do czego one służą ? Pozwalają nam kontrolować w jaki sposób VBA sortuje/porównuje teksty.
A co tam jest do ustawiania ? :)
Już odpowiadam a czy „a” to to samo co „A” ? (pewnie już wiecie że nie, bo… rozmiar ma znaczenie ;) A mając wpisy „Arkusz1” i „arkusz1”, który z tych tekstów będzie „pierwszy” ? Tym właśnie pozwalają nam sterować ustawienia Option Compare.
Po pierwsze jak wygląda porównywanie tekstów jeżeli nie używamy żadnego ustawienia Option Compare ? Tak naprawdę zawsze jakiegoś używamy ;)
Jeżeli widzicie pusty czysty moduł (ewentualnie z Option Explicit patrz pkt 2.) to mało kto zdaje sobie sprawę, że używamy Option Compare Binary :)
• Option Compare Binary – wielkość ma znaczenie
Czyli teksty są porównywane następująco:
Najpierw litery duże…. potem litery małe
A, b, C, D,…. Z, a, b, c, d,… z
Przykład:
wykonaj poniższy kod. Zobaczysz wynik False
1 2 3 |
Sub Test01 MsgBox ”Arkusz1”=”arkusz1” End Sub |
• Option Compare Text – rozmiar nie ma znaczenia
Litery są ustawiane w kolejności bez względu na ich wielkość czyli mamy:
Aa, Bb, Cc, Dd,…Zz
Przykład:
Do programu z poprzedniego przykładu, dodaj nad słowem Sub na samej górze klauzulę Option Compare Text i zobaczysz, że ten sam program zwróci True :)
1 2 3 4 |
Option Compare Text Sub Test02 MsgBox ”Arkusz1”=”arkusz1” End Sub |
• Option Compare Database – ustawienie stosowane tylko przy makrach w Accessie. Oznacza, że to baza danych zarządza sortowaniem tekstów (teksty sortowane są jak rekordy w bazie)
Alternatywą dla ustawień odnoszących się do całego modułu, jest używanie funkcji StrComp, w której możemy każdorazowo wybierać jak mają być porównywane teksty.
Jej składnia wygląda następująco:
StrComp(”tekscik1”, ”tekscik2”,[opcjonalnie sposob_porownywania])
Mamy tam następujące sposoby porównywania tekstów:
- vbBinaryCompare – już wiemy :)
- vbTextCompare – również opisane powyżej
- vbDatabaseCompare – tylko w Accessie
- vbUseCompareOption – makra korzystają z ustawień Option Compare, które wpisaliśmy na samej górze modułu (tylko co wtedy korzystać z funkcji strComp? :)
5. Do czego służy Option Base 1 i kiedy to ustawienie nie działa?
Najprościej mówiąc Option Base 1 sprawia, że ”wiersze” w tablicy zaczynają się od 1 a nie od 0. Tak wiem powinienem pisać indeksy w tablicy a nie wiersze w tablicy ale… to jest poradnik dla początkujących będę pisał ”wiersze” :P
Czyli Option Base 1, to niby rzecz przydatna bo…wiersze w Excelu też zaczynają się od 1, więc deklarując tablicę np. tak:
1 |
Dim zbiorek(2) |
Mamy w niej ”wiersze” o numerach 1 i 2
1 2 |
zbiorek(1) zbiorek(2) |
itd. co samo w sobie nie jest złe ALE…
Ja osobiście nie korzystam z tego ustawienia bo jak coś się pisze na samej górze modułu to potem, w ferworze walki łatwo o tym zapomnieć… i wysyłając komuś kod (jedną konkretną procedurę) mailem możemy łatwo doprowadzić do sytuacji że ów ktoś ma o jeden ”wiersz” w tablicy więcej niż my.
Bez ustawienia Option Base 1 powyższa deklaracja zbiorku
1 |
Dim zbiorek(2) |
da nam taką tablicę:
1 2 3 |
zbiorek(0) zbiorek(1) zbiorek(2) |
Jak chcę mieć tablicę, która zaczyna się od 1 czy od ile tam potrzebuję to deklaruję ją tak:
1 |
Dim zbiorek(1 to 2) |
i mam taki zbiorek
1 2 |
zbiorek(1) zbiorek(2) |
bez żadnego kombinowania z ustawieniami modułu. I mam pewność, że jak zaznaczę procedurę, dam kopiuj wklej kod do maila to tablica zbiorek wszędzie i każdemu będzie działała tak samo :)
Jak kogoś nie przekonałem co do ”śliskości” Option Base 1 to podam wam jeszcze jeden przykład. Deklaruję sobie tablicę dynamiczną i podaję jej rozmiar.
1 2 3 4 5 6 7 8 |
Option Base 1 Sub test04() Dim zbiorek() As String ReDim zbiorek(4) MsgBox "zbiorek zaczna się w wierszu " & LBound(zbiorek) & _ Chr(10) & _ "a kończy się na wierszu " & UBound(zbiorek) End Sub |
Bez wpisanego Option Base 1 czyli w wersji ”standard” wynik to:
”zbiorek zaczyna się w wierszu 0 a kończy w wierszu 4”
Po dopisaniu Option Base 1 wyświetli się:
”zbiorek zaczyna się w wierszu 1 a kończy w wierszu 4”
To teraz z włączonym Option Base 1 odpalcie sobie program test05
Funkcję Split, której tam używam omówię w kolejnym poście, w skrócie dzieli ona tekst na elementy i wrzuca każdy element do jednego wiersza tablicy (takie Excelowe tekst jako kolumny tylko zamiast do kolumn rozdziela teksty do wierszy w tablicy :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Option Base 1 Sub test05() Dim zbiorek() As String Dim tekst As String tekst = "Ala ma kota" 'tu nie trzeba ReDim bo split sam sobie ustawi 'w zbiorku tyle wierszy ile bedzie potrzebowal 'czyli tyle ile jest w tekscie wyrazow oddzielonych spacja zbiorek = Split(tekst, " ") MsgBox "zbiorek zaczna się w wierszu " & LBound(zbiorek) & _ Chr(10) & _ "a kończy się na wierszu " & UBound(zbiorek) End Sub |
Wszystko jedno czy mamy Option Base 1 czy nie wyświetli się wynik:
”zbiorek zaczyna się w wierszu 0 a kończy w wierszu 2”
Czyli… ubaw po pachy… dlatego wolę nie stosować Option Base 1 :)
A jakie są Wasze przemyślenia ?
Pozdrawiam
Michał Dąbrowski