Zespół Szkół Technicznych
im. Ignacego Mościckiego
Tarnów - Mościce
Specjalność: Systemy komputerowe.
PRACA
DYPLOMOWA
Temat: Makropolecenia używane w Microsoft Word.
Konsultant: Wykonał:
mgr Janusz Sadowski Marcin Waśniowski
Klasa V TSK
Tarnów 2003
Spis treści:
Wiadomości wstępne ............................................................................... 3
Co to jest język programowania? ......................................................... 3
Styl programowania .............................................................................. 5
Język programowania VBA ..................................................... 10
Zmienne, typy danych i stałe .................................................................. 10
Komentarze ........................................................................................... 10
Znak kontynuacji wiersza kodu ............................................................ 10
Stałe ....................................................................................................... 11
Zmienne i typy danych .......................................................................... 14
Operatory języka VBA .......................................................................... 31
Funkcje i podprogramy ............................................................................. 32
Wywoływanie funkcji ............................................................................ 32
Wywoływanie podprogramów ............................................................... 35
Parametry i argumenty ........................................................................... 36
Wychodzenie z procedury ...................................................................... 41
Procedury publiczne i prywatne ............................................................. 41
Dodawanie odwołań do projektu ............................................................ 41
Pełne nazwy procedur ............................................................................. 42
Funkcje i instrukcje wbudowane ............................................................... 43
Funkcja MsgBox ..................................................................................... 44
Funkcja InputBox .................................................................................... 47
Funkcje umożliwiające operacje na łańcuchach znaków ........................ 48
Różne funkcje i instrukcje ....................................................................... 52
Instrukcje kontrolujące przepływ programu ............................................ 54
Instrukcja If... Then .................................................................................. 54
Pętla For ................................................................................................... 55
Pętla For Each .......................................................................................... 56
Pętla Do .................................................................................................... 57
Instrukcja Select Case .............................................................................. 61
Ostatnie uwagi o VBA ............................................................................. 62
BHP ................................................................................................................ 63
Wstęp......................................................................................................... 63
Działanie prądu na organizm ludzki ......................................................... 67
Środki ochrony przeciw pożarowej .......................................................... 68
Wiadomości wstępne
Należy od kilku ogólnych faktów związanych z programowaniem i językami programowania, co pozwoli spojrzeć na materię poruszaną w tej pracy z pewnej perspektywy. VBA jest jednym z wielu języków programowania i wszyscy potencjalni programiści powinni wiedzieć, jaką pozycję zajmuje on wśród innych języków. Rozdział ten zawiera informacje ogólne na temat programowania i używanych w nim języków, które zainteresują zarówno użytkowników początkujących, jak i doświadczonych w programowaniu.
Co to jest język programowania?
Mówiąc prosto, język programowania to bardzo wyspecjalizowany i ograniczony język rozumiany przez komputer na pewnym poziomie. Języki programowania można podzielić na trzy grupy w zależności od ich przeznaczenia.
- Języki zaprojektowane do sterowania komputerem na niskim poziomie - czyli do manipulowania systemem operacyjnym (Windows lub DOS) albo nawet sprzętem są nazywane językami niskiego poziomu. Przykładem jest asembler.
- Języki zaprojektowane do tworzenia samodzielnych programów, takich jak Microsoft Word, są językami wysokiego poziomu. Należą do nich BASIC, COBOL, FORTRAN, C, C++ i Visual Basic.
- Języki zaprojektowane do manipulowania aplikacjami, takimi jak Microsoft Word, to języki poziomu aplikacji. Należy do nich VBA dla Worda, Excela i PowerPointa. Każdy z nich jest odmianą języka VBA i służy do sterowania konkretną aplikacją.
Powyższe określenia nie są obowiązujące i mogą być również używane w innym znaczeniu. Nie sposób jednak zaprzeczyć, że niektóre języki są używane na poziomie niższym niż inne.
Świat komputerowy jest pełen setek języków programowania. Niektóre z nich zostały stworzone dla konkretnych komputerów; inne - dla konkretnych typów aplikacji. Tabela 2.1 przedstawia przykłady języków programowania i ich ogólne zastosowanie.
Tabela 1.1. Niektóre języki programowania
Język |
Ogólne zastosowanie |
BASIC |
Prosty, łatwy w nauce język dla początkujących |
Visual Basic |
Wersja BASIC-a służąca do tworzenia aplikacji dla Windows |
C, C++ |
Języki o ogromnych możliwościach, bardzo szybkie i dające dużą kontrolę nad komputerem |
Visual C++ |
Wersja języka C++ zaprojektowana do tworzenia aplikacji dla Windows |
Pascal |
Język edukacyjny, przeznaczony do nauki poprawnego programowania |
COBOL |
Język programowania do zastosowań w biznesie |
FORTRAN |
Język programowania naukowego, niezrównany w skomplikowanych obliczeniach |
Lisp |
Język do przetwarzania list (używany w omawianiu zagadnień sztucznej inteligencji)
|
ALGOL |
Próba stworzenia języka uniwersalnego |
SIMULA |
Język symulacyjny, służący do modelowania zjawisk fizycznych |
SmallTalk |
Język programowania zorientowanego obiektowo |
Języki programowania różnią się składnią. Niektóre języki są znacznie łatwiejsze w czytaniu niż inne (podobnie jest z językami naturalnymi). Tabela 2.2 przedstawia sposób, w jaki w różnych językach programowania można przypisać wartość (w tym przypadku 5) zmiennej o nazwie X. Warto zwrócić uwagę na różnorodność metod wykonania nawet tak prostego zadania.
Tabela 1.2. Operacja przypisania w różnych językach.
Język |
Instrukcja przypisania |
APL |
X <- 5
|
BASIC |
LET X = 5 lub X = 5 |
BETA |
5 -> X
|
C, C++ |
X = 5;
|
COBOL |
MOVE 5 TO X |
FORTRAN |
X = 5 |
J |
X =. 5
|
Lisp |
(SETQ X 5) |
Pascal |
X : =5
|
Visual Basic |
X=5 |
Styl programowania
Dobry styl programowania, podobnie jak dobry styl pisania, jest sprawą w znacznej mierze subiektywną. Prawdopodobnie najlepiej nauczyć się go poprzez studiowanie przykładów.
Nie ma tu miejsca na szczegółowe rozważania na temat stylu programowania. Trzeba jednak wspomnieć o dwóch najważniejszych być może zasadach dobrego programowania. Są to:
sensowne komentowanie programów;
przedkładanie czytelności kodu nad oryginalność i efektowność.
Komentarze
Nie sposób przecenić znaczenia sensownych komentarzy w programach - przynajmniej tych nieco dłuższych.
Dobre programy są intensywnie używane na przestrzeni stosunkowo długiego czasu, mierzonego w miesiącach, a nawet latach. Siłą rzeczy programista będzie chciał wrócić do swojego kodu, aby dokonać zmian (na przykład dodać nowe funkcje) lub usunąć błędy. Mimo wszystkich starań języki programowania nie są tak czytelne, jak języki naturalne. Może się więc okazać, że programista nie będzie w stanie zrozumieć (a nawet rozpoznać!) kodu napisanego kilka miesięcy lub kilka lat wcześniej i w celu ponownego zaznajomienia się w własnym kodem będzie musiał polegać na precyzyjnie napisanym komentarzu .
Należy tu podkreślić, że pisanie komentarzy jest prawie taką samą sztuką, jak pisanie samego kodu. Często można spotkać komentarze podobne do poniższego:
'Przypisz zmiennej x wartość5
x=5
Komentarz ten jest bezużyteczny, ponieważ kod objaśnia się sam. Jest to zwykłe marnowanie czasu i miejsca. Warto tu zauważyć, że w pracach dydaktycznych, takich jak ta praca, można znaleźć komentarze, których nie powinno być w profesjonalnie napisanych programach.
Przeczytanie komentarza (bez kodu) powinno wystarczyć do zrozumienia nie tylko zadania, które program ma wykonać, ale również etapów prowadzących do osiągnięcia celu. Oto komentarze z programu napisanego w języku BASIC :
'Program napisany w języku BASIC
'obliczający średnią nie więcej niż 100 liczb
'Poproś o liczby
'Jeżeli Liczba należy do przedziału od 1 do 100, kontynuuj
'Wykonaj pętlę pobierającą liczby
'Poproś o następną liczbę
'Dodaj liczbę do sumy liczb
'Oblicz średnią
'Wyświetl średnią
Czytelność
Czytelność jest sprawą subiektywną. To, co jest czytelne dla jednej osoby, może nie być czytelne dla innej. To, co jest czytelne dla autora programu, prawdopodobnie jest mniej czytelne dla wszystkich innych osób, przynajmniej do pewnego stopnia. Dobrze jest o tym pamiętać przed przystąpieniem do programowania (zakładając, że chcemy, aby inni potrafili czytać nasze programy).
Instrukcja GOTO, której różne wcielenia wchodzą w skład wielu języków (w tym VBA), należy do tych instrukcji, które najbardziej psują czytelność kodu. Nie będzie się tu rozwodzić się nad instrukcją GOTO, ale pomoże ona zilustrować sprawę dobrego stylu programowania.
Instrukcja GOTO jest bardzo prosta - przenosi ona wykonywanie programu w inne miejsce. Na przykład następujący kod napisany w języku BASIC prosi użytkownika o podanie liczby dodatniej. Jeżeli użytkownik poda liczbę ujemną, instrukcja GOTO przenosi wykonywanie kodu do pierwszego wiersza programu (oznaczonego etykietą PonowProbe). Spowoduje to ponowne wykonanie całego programu. Krótko mówiąc, program będzie wykonywany do momentu podania liczby dodatniej przez użytkownika:
PonowProbe:
INPUT "Wpisz liczbę dodatnią: ", x
IF x <=0 TREN GOTO PonowProbe
Chociaż powyższy program nie reprezentuje dobrego stylu programowania, jest przynajmniej czytelny. Jednak kod poniższy jest znacznie trudniejszy do czytania:
PonowProbe
INPUT "Wpisz liczbę z przedziału od 1 do 100: ", x
IF x > 100 THEN GOTO ZbytDuza
IF x <=0 THEN GOTO ZbytMala
PRINT "Podana liczba to: ", x
GOTO Zrobione
ZbytDuza:
PRINT "Podana liczba jest zbyt duża"
GOTO PonowProbe
ZbytMala:
PRINT "Podana liczba jest zbyt mała"
GOTO PonowProbe
Zrobione:
END
Taki rodzaj kodowania jest nazywany kodem spaghetti, ponieważ zmusza do przeskakiwania z miejsca na miejsce, kiedy chce się prześledzić przepływ programu. Trudno sobie wyobrazić taki styl programowania w programie zawierającym tysiące wierszy. Wersja podana poniżej jest znacznie czytelniejsza, choć nie jest to jeszcze styl najlepszy:
PonowProbe:
INPUT "Wpisz liczbę z przedziału od 1 do 100: ", x
IF X > 100 TREN
PRINT "Podana liczba jest zbyt duża"
GOTO PonowProbe
ELSEIF x <=0 THEN
PRINT "Podana liczba jest zbyt mała"
GOTO PonowProbe
END IF
PRINT "Podana liczba to: ",
END
Poniższy kod wykonuje tę samą pracę, ale unika użycia instrukcji GOTO i większość programistów uznałoby go za napisany lepszym stylem:
DO
INPUT "Wpisz liczbę z przedziału od 1 do 100: ", x
IF x > 100 THEN
PRINT "Podana liczba jest zbyt duża "
ELSEIF x <= 0 THEN
PRINT "Podana liczba jest zbyt mała "
END IF
LOOP UNTIL x >=1 AND x<=100
PRINT "Podana liczba to: ", x
END
Niektórzy programiści chcą, aby ich kod był „oryginalny" lub „efektowny", ale w rzeczywistości okazuje się on trudny do czytania i podatny na powstawanie błędów. Szczególnie łatwo o to w języku C. Rozważając na przykład następujące trzy wiersze napisane w języku C:
x = x + 1;
x = x + i;
i = i - 1;
Pierwszy wiersz dodaje 1 do x, drugi dodaje i do x, a trzeci odejmuje 1 od i. Taki kod jest z pewnością czytelny (chociaż niezbyt sensowny). Jednak można go również napisać tak:
x = ++ x + i--,
Niektórzy programiści mogą uznać to za oryginalne programowanie, ale taki kod jest nie do przyjęcia. Właśnie dlatego rozważny programista przedkłada czytelność kodu nad „oryginalność" i „efektowność".
Programowanie modułowe
Innym ważnym zagadnieniem związanym z czytelnością jest programowanie modułowe. We wczesnym etapie rozwoju programowania komputerów osobistych (jak również rozwoju języka BASIC) większość programów składało się tylko z jednego modułu zawierającego czasem setki, a nawet tysiące wierszy kodu. Czytanie takiego programu nie jest łatwe, zwłaszcza w sześć miesięcy po jego napisaniu. Programy te używały tych samych segmentów kodu wielokrotnie, co było marnowaniem czasu i miejsca.
Ilustruje to poniższy przykład napisany w języku BASIC. Dla ułatwienia dodano numery wierszy. (Zrozumienie znaczenia każdego wiersza kodu nie jest konieczne dla zrozumienia samego zagadnienia, które on ilustruje).
10 'Program odwracający kolejność liter w nazwisku
20 'Czytaj wspak imię
30 INPUT "Wpisz imię: ", nazwisko$
40 CzytajWspak$ _ ""
50 FOR i = LEN(nazwisko$) TO 1 STEP -1
60 CzytajWspak$= CzytajWspak$ + MID$(nazwisko$, i, 1)
70 NEXT i
80 PRINT "Imię czytane wspak: " + Czytajwspak$
90 'Czytaj wspak drugie imię
100 INPUT "Wpisz drugie imię: ", nazwisko$
110 CzytajWspak$ _ ""
120 FOR i = LEN(nazwisko$) TO 1 STEP -1
130 Czy tajWspak$= Czytaj Wspak $ + MID$(nazwisko$, i, 1)
140 NEXT i
150 PRINT "Drugie imię czytane wspak: " + CzytajWSpak$
160 'Czytaj wspak nazwisko
170 INPUT "Wpisz nazwisko: ", nazwisko$
180 Czytaj Wspak$ _ ""
190 FOR i = LEN(nazwisko$) TD 1 STEP -1
200 CzytajWspak$= Czy tajWspak$ + MID$(nazwisko$, i, 1)
210 NEXT i
220 PRINT "Nazwisko czytane wspak: " + CzytajWspak $
Należy zwrócić uwagę, że wiersze 40-70, 110-140 i 180-210 są identyczne. Jest to marnowanie miejsca. Lepszym rozwiązaniem byłoby wpisanie kodu, który odwraca łańcuch znaków (nazwisko), do oddzielnego modułu kodu i wywoływanie tego modułu trzy razy, jak pokazuje poniższy przykład:
'Program czytający wspak nazwisko
DECLARE FUNCTION CzytajWspak$(nazwisko$)
'Czytaj wspak imię
INPUT "Wpisz imię: ", nazwisko$
PRINT "Imię czytane wspak: " + CzytajWspak$(nazwisko$)
'Czytaj wspak drugie imię
INPUT "Wpisz drugie imię: ", nazwisko$
PRINT "Drugie imię czytane wspak: " + CzytajWspak$(nazwisko$)
'Czytaj wspak nazwisko
INPUT "Wpisz nazwisko: ", nazwisko$
PRINT "Nazwisko czytane wspak: " + CzytajWspak$(nazwisko$)
Oto oddzielny moduł kodu odwracający łańcuch znaków:
'Kod czytający łańcuch znaków wspak
FUNCTION CzytajWspak$(nazwisko$)
LancuchZnakow$= ""
FOR i = LEN(nazwisko$) TO 1 STEP -1
LancuchZnakow$ = LancuchZnakow$ + MID$(nazwisko$, i, 1)
NEXT i
CzytajWspak$ = LancuchZnakow$
END FUNCTION
Oczywiście w tym przykładzie nie zaoszczędzono zbyt dużo miejsca, ale można sobie wyobrazić, co się stanie, jeżeli zamieni się procedurę odwracającą łańcuch znaków na taką, która zawiera kilkaset wierszy kodu, i wykona się ją kilkaset razy w głównym programie. Dzięki modularyzacji można zaoszczędzić dosłownie tysiące wierszy kodu.
Istnieje inna ważna zaleta programowania modułowego. Jeżeli zdecyduje się na napisanie innego programu wymagającego odwracania łańcuchów znaków, można po prostu dodać moduł kodu odwracający łańcuch znaków do nowego programu, bez konieczności pisania nowego kodu. Profesjonalni programiści często tworzą biblioteki kodu zawierające użyteczne moduły kodu, które w razie potrzeby można dodać do nowych aplikacji.
Trudno przecenić ważność programowania modułowego. Na szczęście VBA ułatwia tworzenie programów modułowych.
Ogólnie mówiąc, istnieją dwie grupy modułów kodu: funkcje i procedury typu sub. Różnią się one tym, że funkcja zwraca wartość, a procedura typu sub - nie zwraca (oczywiście można nie użyć wartości zwracanej przez funkcję.) Na przykład, funkcja Czytaj Wspak opisana wyżej zwraca odwrócony łańcuch znaków. Natomiast poniższy moduł kodu coś robi, ale nie zwraca wartości - po prostu zawiesza działanie na pewną liczbę sekund (podanych w argumencie sekunda):
SUB ChwilaPrzerwy(sekunda)
`Odczytaj bieżący czas
Start = TIMER
`Stwórz pętlę, która nic nie robi
`przez liczbę sekund podaną w argumencie sekunda
DO
LOOP UNTIL TIMER - Start > sekunda
END SUB
Funkcje i procedury typu sub są niezwykle często używane w nowoczesnym programowaniu. Jedne i drugie są nazywane procedurami.
Język programowania VBA
Zmienne, typy danych i stale
W tym rozdziale zostaną omówione podstawy języka VBA używanego we wszystkich aplikacjach pakietu Microsoft Office. Będzie zaprezentowane wiele krótkich fragmentów kodu.
Komentarze
Wspomniane już zostało ważnej roli, jaką odgrywają komentarze. Komentarzem jest każdy tekst poprzedzony znakiem apostrofu. W trybie działania programu, Word ignoruje komentarze. W poniższym przykładzie komentarzem jest pierwszy wiersz, jak również tekst w trzecim wierszu, znajdujący się na prawo od apostrofu:
'Zadeklaruj zmienną typu String
Dim NazwaDokumentu As String
NazwaDokumentu = ActiveDocument.Name 'Odczytaj nazwę dokumentu
W czasie usuwania błędów fragment kodu, który chwilowo ma być niewidoczny dla Worda w trybie działania programu, można zaznaczyć jako komentarz. Jeżeli chce się, aby kod był ponownie wykonywany, należy usunąć znaki komentarza. Przyciski CommentBlock, i UncommentBlock znajdujące się na pasku narzędzi Edit, służą do wstawiania i usuwania znaku komentarza (apostrofu) we wszystkich zaznaczonych wierszach, co ułatwia wstawianie znaku komentarza w wielu wierszach jednocześnie. Chociaż przyciski te nie mają klawiszy skrótów, można dodać je do menu i przypisać im klawisze dostępu.
Znak kontynuacji wiersza kodu
Długie wiersze kodu napisane w języku VBA mogą być trudne do czytania, szczególnie kiedy musi się korzystać z poziomego paska przewijania edytora kodu, aby zobaczyć cały wiersz. Z tego powodu Microsoft wprowadził znak kontynuacji wiersza kodu, którym jest znak podkreślenia (_). Przed znakiem kontynuacji wiersza kodu należy postawić znak spacji. Należy zwrócić uwagę, że na prawo od znaku kontynuacji wiersza nie można postawić żadnego znaku (w tym również komentarza). Oto przykład:
ActiveDocument.Paragraphs(1).Alignment = _
WdAlignParagraphCenter
Word traktuje powyższy kod jak jeden wiersz.
WSKAZÓWKA! Znaku kontynuacji wiersza kodu nie można umieścić w łańcuchu znaków wziętym w cudzysłów.
Stałe
Język VBA posiada dwa typy stałych. Literał to konkretna wartość - taka jak liczba, data lub łańcuch znaków - która się nie zmienia i jest używana tak, jak została zadeklarowana. Należy zwrócić uwagę, że stałe łańcuchów znaków są wzięte w cudzysłów, na przykład:
"Stefania Szybki"
natomiast stałe dat są umieszczone między dwoma znakami numeru, na przykład:
#21/4/2000#
Następujący kod przypisuje datę zmiennej MojaData:
Dim MojaData As Date
MojaData = #4/21/2000#
Drugi typ stałej to stała symboliczna.
Aby zdefiniować lub zadeklarować stałą symboliczną w programie, należy użyć słowa kluczowego Const, na przykład:
Const NazwaPliku = "c:\Test.doc"
W trybie działania programu Word zastępuje wyrażenie NazwaPliku łańcuchem "c:\Test.doc". Oznacza to, że "c:\Test.doc" jest stałą, ponieważ się nie zmienia, ale nie literałem, ponieważ zamiast łańcucha znaków "c:\ Test.doc" wpisuje się w kodzie NazwaPliku.
Zaletą stałych symbolicznych jest to, że jeżeli zdecyduje się zmienić łańcuch znaków "c:\ Test.doc" na "c:\Moje dokumenty\Test.doc", nie musi się wyszukiwać w kodzie każdego wystąpienia łańcucha znaków "c:\Test.doc" i zastępować go nowym. Wystarczy jedynie zmienić deklarację stałej NazwaPliku:
Const NazwaPliku = "c:\ Moje dokumenty\Test.doc"
Stałe symboliczne należy deklarować na początku każdej procedury, w której mają one być użyte (lub w sekcji deklaracji modułu kodu). Poprawia to czytelność kodu.
Oprócz stałych symbolicznych, które definiuje się za pomocą instrukcji Const, VBA posiada wiele wbudowanych stałych symbolicznych (około 700) o nazwach zaczynających się od liter vb. VBA dla Worda posiada dodatkowe stałe symboliczne (około 2000) o nazwach rozpoczynających się od liter wd.
Do najczęściej używanych stałych VBA należą vbCrLf - równoznaczna z naciśnięciem klawisza Enter, vbTab - równoznaczna z naciśnięciem klawisza Tab. Word używa również stałej vbCr jako znaku akapitu.
Enumeracje
Enumeracja (w skrócie Enum) to struktura służąca do definiowania grupy stałych symbolicznych. Na przykład, wśród 192 enumeracji Worda znajduje się enumeracja definiująca ustawienia akapitu:
Enum WdParagraphAlignment
wdAlignParagraphLeft = 0
wdAlignParagraphCenter = 1
wdAlignParagraphRight = 2
wdAlignParagraphJustify = 3
End Enum
Zatem poniższy wiersz kodu wyśrodkuje pierwszy akapit w aktywnym dokumencie:
ActiveDocument.Paragraphs(1).Alignment = wdAlignParagraphCenter
Enumeracje są wbudowane, więc nie musi się ich deklarować przed użyciem stałych symbolicznych. Można stworzyć własne enumeracje, ale najczęściej nie jest to konieczne z powodu ogromnej liczby enumeracji wbudowanych.
Innym przykładem jest wbudowana enumeracja definiująca wartości zwracane, kiedy użytkownik klika przycisk okna komunikatów:
Enum VbMsgBoxResult
vbOK = 1
vbCancel = 2
vbAbort = 3
vbRetry = 4
vbIgnore = 5
vbYes = 6
vbNo = 7
End Enum
Na przykład, kiedy użytkownik klika przycisk OK w oknie komunikatu, VBA zwraca wartość vbOK. Łatwiej zapamiętać, że VBA zwraca stałą symboliczną vbOK, niż zapamiętać, że zwraca stałą 1. W dalszej części zostanie omówione , jak odczytać i wykorzystać zwracane wartości.
VBA definiuje również stałe symboliczne, które decydują o typie przycisków pojawiających się w oknie komunikatów. Oto fragment enumeracji zawierającej te stałe symboliczne:
Enum VbMsgBoxStyle
vbOKOnly = 0
vbOKCancel = 1
vbAbortRetryIgnore = 2
vbYesNoCancel = 3
vbYesNo = 4
vbRetryCancel = 5
End Enum
Poniższy przykład ilustruje użycie omawianych stałych :
If MsgBox("Kontynuować?", vbOKCancel) = vbOK Then
'Tu wpisz kod wykonywany, kiedy użytkownik
'klika przycisk OK
Else
'Tu wpisz kod wykonywany,kiedy użytkownik
'klika przycisk Anuluj
End If
Pierwszy wiersz kodu:
MsgBox("Kontynuować?", vbOKCancel)
sprawia, że Word wyświetla okno komunikatu z dwoma przyciskami - OK i Anuluj - oraz wiadomość „Kontynuować?" (Rysunek 5.1).
Rysunek 5.1. Proste okno komunikatu.
Jeżeli użytkownik klika przycisk OK, Word zwraca wartość vbOK. W innym przypadku zwróci wartość vbCancel. Zatem instrukcja If w pierwszym wierszu rozróżnia te dwie odpowiedzi. Instrukcja If jest omawiana trochę później ,w Instrukcje kontrolujące przeplyw programu.
Wyraźnie widać, że pierwszy wiersz omawianego fragmentu kodu jest czytelniejszy niż wiersz:
If MsgBox("Kontynuować?", 1) = 1 Then
Aby jeszcze bardziej docenić wartość stałych symbolicznych, należy spojrzeć na enumerację definiującą stałe kolorów:
Enum ColorConstants
vbBlack = 0
vbBlue = 16711680
vbMagenta = 16711935
vbCyan = 16776960
vbWhite = 16777215
vbRed = 255
vbGreen = 65280
vbYellow = 65535
End Enum
Który z poniższych wierszy jest czytelniejszy:
PoleTekstowe.ForeColor = vbBlue
czy
PoleTekstowe.ForeColor = 16711680
Zmienne i typy danych
Zmienna jest zarezerwowanym miejscem w pamięci, które przechowuje wartości określonego typu. Wartość zmiennej może zmieniać się w czasie wykonywania programu - stąd nazwa „zmienna".
W VBA zmienna posiada określony typ danych, który wskazuje, jaki rodzaj danych może ona przechowywać. Na przykład zmienna typu String przechowuje łańcuchy znaków (tekst). Zmienna typu Integer przechowuje liczby całkowite. Tabela 5.1 przedstawia typy danych, ich zakres wartości oraz ilość pamięci, którą one zajmują. Za chwilę zostaną omówione zmienne stosowane najczęściej.
Tabela 5.1. Typy danych VBA.
Typ |
Rozmiar |
Zakres wartości |
Byte |
1 bajt |
0 do 255
|
Boolean |
2 bajty |
True i False
|
Integer |
2 bajty |
-32 768 do 32 767 |
Long |
4 bajty |
od -2147483648 do 2147483747
|
Single |
4 bajty |
w przybliżeniu od -3,4E38 do 3,4E38 3,4E38
|
Double |
8 bajtów |
W przybliżeniu od -1,8E308 do 4,9E324
|
Currency |
8 bajtów |
W przybliżeniu od -922337203685477,5808 do 922337203685477,5807
|
Date |
8 bajtów |
od 1/1/100 do 12/31/9999
|
Object |
4 bajty |
Odwołanie do obiektu
|
String |
Zmiennej długości: 10 bajtów + długość łańcucha znaków |
Łańcuchy zmiennej długości: <= około 2 miliardy (65 400 dla win 3.1); Łańcuchy stałej długości: do 65 400
|
Variant |
16 bajtów dla liczb 22 bajty+ długość łańcucha znaków
|
Liczba: tyle co Double Łańcuch znaków: tyle co String |
Zdefiniowany przez programistę
|
Różne |
|
Deklarowanie zmiennych
Deklarowanie zmiennej oznacza zdefiniowanie jej typu danych. Zmienne deklaruje się za pomocą słowa kluczowego Dim (lub słów kluczowych Private i Public). Oto kilka przykładów:
Dim Nazwisko As String
Dim Wakacje As Date
Dim Wiek As Integer
Dim Wzrost As Single
Dim Pieniądze As Currency
Dim dok As Document
Dim Akapit as Paragraph
Zmienne deklaruje się zgodnie z następującym wzorem:
Dim NazwaZmiennej As TypDanych
Jeżeli użyje się zmiennej, która nie była zadeklarowana lub która została zadeklarowana bez podania jej typu, na przykład:
Dim Wiek
VBA przypisze jej typ Variant. Będzie to oznaczać zmarnowanie pamięci, ponieważ, jak wynika z tabeli 5.2, zmienna typu Variant wymaga więcej pamięci niż większość innych typów zmiennych.
Na przykład zmienna typu Integer (przechowująca liczby całkowite) wymaga 2 bajtów, podczas gdy zmienna typu Variant przechowująca tę samą liczbę całkowitą wymaga 16 bajtów, co oznacza, że 14 bajtów zostało zmarnowanych. W złożonych programach zawierających setki lub nawet tysiące zmiennych spowodowałoby to znaczące straty pamięci. Z tego powodu zaleca się deklarowanie wszystkich zmiennych.
Można umieścić więcej deklaracji w jednym wierszu. Na przykład wiersz kodu:
Dim Wiek As Integer, Nazwisko As String, Pieniądze As Currency
deklaruje trzy zmienne. Należy zwrócić uwagę, że wiersz:
Dim Wiek, Wzrost, Waga As Integer
deklaruje zmienne Wiek i Wzrost jako typ Variant, nie Integer. Innymi słowy, należy określić typ dla każdej zmiennej.
Można również dodać do nazwy zmiennej specjalny znak określający jej typ. Tabela 5.2 zawiera zestawienie tych znaków.
Tabela 5.2. Znaki określające typ zmiennej.
Znak |
Typ
|
% |
Integer
|
& |
Long
|
! |
Single
|
# |
Double
|
@ |
Currency
|
$
|
String |
Na przykład wiersz:
Dim Nazwisko$
deklaruje zmienną o nazwie Name$ typu String. Można użyć jej w kodzie w następujący sposób:
Name$ _ "Alicja"
Chociaż można deklarować zmienne i stałe w dowolnym miejscu procedury, do zasad dobrego programowania należy deklarowanie zmiennych na początku procedury. Ułatwia to czytanie kodu.
Jawne deklarowanie zmiennych
Powiedziane zostało, że używanie typu Variant oznacza zwykle marnowanie pamięci. Istnieje jeszcze jeden, ważniejszy powód, dla którego warto deklarować zmienne jawnie (tj. przed ich użyciem). Jeżeli popełni się błąd wpisując nazwę zadeklarowanej zmiennej, VBA „pomyśli", że chce się stworzyć nową zmienną.
Procedura NowyList (wydruk 5.1) ilustruje, jak może to być niebezpieczne. Procedura NowyList ma w pierwszy otwartym dokumencie zmieniać zawartość, poprosić użytkownika o nazwę, pod którą ma być zapisany zmieniony dokument, i zapisać dokument pod nową nazwą.
Wydruk 5.1. Procedura z błędem typograficznym.
Public Sub NowyList()
Dim List As Document Dim NazwaListu As String
'Weź pierwszy otwarty dokument
Set List = Documents(1)
'Odczytaj nazwę dokumentu
NazwaListu = List.Name
'Zmień zawartość dokumentu
List.Content = "Kocham Cię!"
'Poproś użytkownika o nową nazwę dla dokumentu
NazwaList =InputBox("Wpisz nową nazwę dla dokumentu"& NazwaListu)
'Zapisz dokument
List.SaveAs NazwaListu
End Sub
Należy zwrócić uwagę, że wiersz
NazwaList =InputBox("Wpisz nową nazwę dla dokumentu"& NazwaListu)
zawiera błąd typograficzny. Ponieważ zmienna NazwaList nie została zadeklarowana, Word potraktuje ją jak nową zmienną i nada jej typ Variant. Co więcej, VBA uzna, że chce się, aby nowa nazwa pliku została przypisana zmiennej NazwaList i zapisze zmieniony dokument pod jego oryginalną nazwą, przechowywaną w zmiennej NazwaListu. Spowoduje to utratę oryginalnego dokumentu, który zostanie nadpisany bez ostrzeżenia!
Option Expllcit
Aby uniknąć problemu opisanego w powyższym przykładzie, w sekcji deklaracji każdego modułu kodu należy wpisać wiersz:
Option Explicit
Dzięki temu Word nie wykona żadnego programu, w którym zauważy niezadeklarowane zmienne. Aby VBA automatycznie wpisywał instrukcję Option Explicit do każdego nowego modułu kodu, trzeba zaznaczyć pole wyboru Reguire Variable Declaration w oknie Options. Namawia się do zaznaczenia tej opcji.
Teraz omówione zostaną niektóre typy danych przedstawione w tabeli 5.1.
Numeryczne typy danych
Do numerycznych typów danych należą: Integer, Long, Single, Double i Currency. Programiści VBA stosują najczęściej zmienne typu Integer i Long. Na przykład liczbę znaków w dokumencie Worda można zapisać w zmiennej typu Long.
Nawiasem mówiąc, dokumentacja VBA informuje czasem, że dana wartość jest typu Integer, kiedy tak naprawdę jest ona typu Long. Jest to prawdopodobnie spowodowane tym, że w czasach Windows 3.11 (16-bitowego systemu operacyjnego) wiele z tych wartości posiadało typ Integer. Jednak wraz z pojawieniem się systemu Windows 95 i wersji późniejszych, wartościom tym przypisano typ Long.
Dane typu Boolean
Zmienna typu Boolean może przyjąć jedną z dwóch wartości: True lub False. Ten bardzo pomocny typ został wprowadzony do VBA stosunkowo niedawno. Przed wprowadzeniem typu Boolean, VBA rozpoznawał 0 jako False, a każdą wartość różną od zera jako True.
Dane typu String
String to łańcuch znaków. Pusty String nie zawiera żadnych znaków. Łańcuch znaków może zawierać zwykły tekst (litery, cyfry, znaki interpunkcji), jak również znaki takie jak vbCrLf (powrót karetki/wysunięcie wiersza) lub vbTab (znak tabulacji). Stała typu String musi być wzięta w cudzysłów. Pusty String (łańcuch znaków) zapisuje się jako pusty cudzysłów:
PustyString = ""
Są dwa rodzaje łańcuchów znaków: łańcuchy o stałej długości i łańcuchy o zmiennej długości. Zmienną przechowującą łańcuch znaków o stałej długości deklaruje się w następujący sposób:
Dim NazwaZmiennej As String * DługośćŁańcuchaZnaków
Na przykład poniższy wiersz kodu deklaruje zmienną przechowującą łańcuch 10 znaków:
Dim Nazwisko As String * 10
Należy zwrócić uwagę, że kod:
Dim s As String *10
s = "test"
Debug.Print s & "/"
wyświetli w oknie Immediate następujący wiersz:
test /
Oznacza to, że puste miejsca w łańcuchu znaków o stałej długości są wypełniane spacjami.
Drugi rodzaj zmiennych typu String to zmienne przechowujące łańcuchy znaków o zmiennej długości. Deklaruje się je w następujący sposób:
Dim NazwaZmiennej As String
Kod:
Dim s As String
s = "test"
Debug.Print s & "/"
s = "inny test"
Debug.Print s & "/"
wyświetli w oknie Immediate następujące wiersze:
test/
inny test/
Łańcuchy znaków o zmiennej długości są używane znacznie częściej niż łańcuchy znaków o stałej długości, chociaż te ostatnie mają swoje ważne zastosowania.
Typ Date
Zmienne typu Date wymagają 8 bajtów pamięci i są przechowywane jako liczby dziesiętne reprezentujące daty między 1 stycznia 100 a 31 grudnia 9999 (nie występuje tu problem Y2K) i godziny między 00:00:00 a 23:59:59.
Aby zmiennej typu Date przypisać datę, można ją umieścić między znakami numeru lub wziąć ją w cudzysłów. Oto przykłady przypisania daty i czasu:
Dim dt As Date
dt = #22/4/2000#
dt = "22 kwietnia 2000"
dt = #1/1/99#
dt = #12:50:00 PM#
dt = #2/12/99 12:50:00 AM#
VBA posiada dużą ilość funkcji służących do operacji na datach i czasie. Dokumentacja VBA zawiera dokładne informacje, jak użyć tych funkcji do manipulowania datami i czasem w tworzonych programach.
Typ Variant
Zmienna typu Variant może przechowywać wszystkie rodzaje danych z wyjątkiem łańcuchów znaków o stałej długości oraz danych o typach zdefiniowanych przez programistę. W poprzedniej części tego rozdziału omówiono już zalety i wady typu Variant i wyjaśniono, dlaczego generalnie należy unikać stosowania tego typu.
Typy obiektów Worda
VBA Worda posiada wiele dodatkowych typów danych, które można ogólnie określić jako typy obiektów Worda. Oto lista typów obiektów modelu obiektowego Worda:
Border
Document
Font
Options
PageSetup
Paragraph
ParagraphFormat
Selection
Styl e
Table, Cell, Row, Column
Template
Window
Można zatem zadeklarować następujące zmienne:
Dim dok As Document
Dim czcionka As Font
Dim opcja As Options
Dim akapit As Paragraph
Dim zaznaczenie As Selection
Dim tabela As Table
Dim szablon As Template
Deklarowanie zmiennej za pomocą słów kluczowych As Object
Można również zadeklarować dowolny obiekt Worda za pomocą instrukcji As Object, jak pokazuje następujący przykład:
Dim akapit As Object
Należy jednak unikać deklarowania zmiennych w ten sposób. Preferowany sposób to:
Dim akapit As Paragraph
ponieważ do momentu uruchomienia programu, Word nie wie, z jakim typem obiektu ma do czynienia i dopiero w trybie wykonywania programu musi to określić, co spowalnia wykonanie programu. Deklarowanie zmiennej za pomocą instrukcji As Object jest nazywane late binding.
Instrukcja Set
Zmienne obiektowe deklaruje się podobnie jak inne zmienne. Oto przykład deklaracji dwóch zmiennych:
Dim LiczbaCałkowita As Integer 'deklaracja zmiennej nieobiektowej Dim dok As Document 'deklaracja zmiennej obiektowej
Jednak przypisanie wartości do zmiennej wygląda inaczej dla obiektów, a inaczej dla innych zmiennych. Aby przypisać wartość do zmiennej obiektowej, należy użyć instrukcji Set. Poniższy kod przypisuje aktywny dokument Worda do zmiennej dok:
Set dok = ActiveDocument
Tablice
Tablica jest kolekcją zmiennych o identycznych nazwach, ale o różnych wartościach indeksu. Na przykład, aby zapisać pierwszych 100 akapitów dokumentu, można by zadeklarować tablicę w następujący sposób:
Dim Akapit(1 To 100) As Paragraph
Tablica nosi nazwę Akapit i zawiera 100 elementów. Dolny indeks tablicy wynosi 1, a górny 100. Każda ze zmiennych:
Akapit(1), Akapit(2),...,Akapit(100)
ma typ Paragraph. Jeżeli pominie się pierwszy indeks tablicy w deklaracji:
Dim Akapit (100) As Paragraph
VBA automatycznie ustawi dolny indeks na 0, dzięki czemu tablica będzie zawierać 101 elementów.
Łatwo zauważyć zalety tablicy: deklarowanie 100 oddzielnych zmiennych (zamiast jednej 100-elementowej tablicy) nie jest przyjemną perspektywą. Poza tym, jak wkrótce będzie pokazane, można wykonywać operacje na wszystkich elementach tablicy jednocześnie za pomocą kilku prostych programistycznych technik. Na przykład poniższy kod pogrubia wszystkie 100 akapitów tablicy:
For i = 1 To 100
Akapit(i).Range.Bold = True
Next i
Wymiar tablicy
Tablica Akapit zdefiniowana w poprzednim podrozdziale jest jednowymiarowa. Można również definiować tablice wielowymiarowe. Na przykład poniższy wiersz kodu:
Dim Komórki (1 To 10, 1 To 100) As String
deklaruje tablicę dwuwymiarową o indeksach od 1 do 10 i od 1 do 100. Zatem tablica ma rozmiar I 0 x 100 = 1000.
Tablice dynamiczne
Jeżeli zadeklarujemy tablicę w następujący sposób:
Dim Pliki (1 To 10) As String
zarówno dolny, jak i górny indeks są określone, dzięki czemu rozmiar tablicy jest stały. Istnieją jednak sytuacje, kiedy w czasie deklarowania tablicy nie wie się, jaki powinna mieć ona rozmiar. W takich przypadkach można zastosować tablicę dynamiczną oraz instrukcję ReDim.
Tablicę dynamiczną deklaruje się bez podania indeksu (nawiasy są puste), jak pokazuje poniższy wiersz kodu:
Dim Pliki() As String
Rozmiar tablicy dynamicznej ustala się za pomocą instrukcji ReDim:
ReDim Pliki (1 To 10)
Rozmiar tej samej tablicy można zmienić ponownie:
ReDim Pliki (1 To 100)
Warto zwrócić uwagę, że zmiana rozmiaru tablicy usuwa jej zawartość - chyba że użyje się słowa kluczowego Preserve:
ReDim Preserve Pliki (1 To 200)
Kiedy używamy Preserve, możemy zmienić tylko górny indeks tablicy (i tylko ostatni wymiar wielowymiarowej tablicy).
Funkcja Ubound
Funkcja UBound zwraca bieżący górny indeks tablicy. Przydaje się do określenia, kiedy rozmiar tablicy powinien zostać zmieniony. Można założyć, że w tablicy o nazwie Pliki chce się zapisać nazwy nieznanej liczby plików. Jeżeli numer następnego pliku wynosi iNastępnyPlik, poniższy kod sprawdza, czy górny indeks jest mniejszy od iNastępnyPlik. Jeżeli tak, górny indeks tablicy zostaje zwiększony o 10, aby zrobić miejsce na nazwę nowego pliku (bieżąca zawartość tablicy zostaje zachowana dzięki słowu kluczowemu Preserve):
If UBound(Pliki) < iNastępnyPlik Then
ReDim Preserve Pliki(UBound(Pliki) + 10)
End If
Zmiana rozmiaru tablicy wymaga czasu. Należy zatem unikać częstych zmian rozmiaru tablicy, ustalając wystarczająco wysoki indeks górny. W powyższym przykładzie do indeksu górnego dodano od razu 10, a nie 1. Należy wyważyć, co jest korzystniejsze: częste zmiany rozmiarów tablicy czy zadeklarowanie tablicy o takim rozmiarze, aby nie trzeba go było zmieniać. Pamiętać trzeba, że częsta zmiana rozmiaru tablicy może oznaczać marnowanie czasu, natomiast zadeklarowanie zbyt dużej tablicy może oznaczać marnowanie pamięci, jeżeli nie zostaną wykorzystane jej wszystkie elementy.
Konwencje stosowane w nazywaniu zmiennych
Ponieważ pisane programy mogą stać się z czasem coraz bardziej skomplikowane, powinno się uczynić wszystko, aby były one jak najbardziej czytelne. W jakiś czas po napisaniu programu można nie pamiętać wszystkich jego niuansów, dlatego dodawanie komentarzy jest tak ważne.
Można również ułatwić czytanie kodu dzięki stosowaniu jednolitych nazw stałych, zmiennych, procedur i innych elementów kodu. Ogólnie mówiąc, nazwa powinna mieć dwie cechy. Po pierwsze powinna przypominać cel albo zadanie, jakie dany element realizuje. Można założyć, że zmiennym typu Document chce się przypisać kilka dokumentów zawierających faktury. Poniższy kod:
Dim dokl As Document
Dim dok2 As Document
Set dokl = Documents.Open("c:\FakturaZaKsiążki.doc")
Set dok2 = Documents.Open("c:\FakturaZaPłyty.doc")
jest zupełnie poprawny, ale 1000 wierszy kodu dalej i 6 miesięcy później, czy będzie się w stanie odróżnić dok1 od dok2? Ponieważ został zadany sobie trud nadania plikom opisowych nazw, to samo powinno się zrobić ze zmiennymi:
Dim dokKSiążki As Document
Dim dokPłyty As Document
Set dokKsiążki = Documents.Open("c:\FakturaZaKsiążki.doc")
Set dokPłyty = Documents.Open("c:\FakturaZaPłyty.doc")
Oczywiście istnieją wyjątki od każdej reguły, ale generalnie lepiej nadać zmiennym nazwy opisowe. To samo dotyczy innych elementów wymagających nazw - stałych, procedur, kontrolek, formularzy i modułów kodu.
Po drugie, nazwa zmiennej powinna zawierać informację o swoich cechach, na przykład o swoim typie. Wielu programistów stosuje konwencję, w myśl której kilka pierwszych znaków nazwy zmiennej wskazuje jej typ. Konwencja ta jest nazywana notacją węgierską na cześć węgierskiego programisty Charlesa Simonyi, któremu przypisuje się jej wymyślenie.
Tabele 5.3 i 5.4 zawierają przedrostki stosowane w nazwach zmiennych standardowych i obiektowych występujących w tej pracy. Oczywiście każdy programista może stworzyć własną konwencję. Trzeba tylko pamiętać, aby nazwy były konsekwentne. Przedrostki mają przypominać programiście typ danych, ale niełatwo je stworzyć używając jedynie kilku znaków - im przedrostki dłuższe, tym mniejsze prawdopodobieństwo, że będzie się je stosować. Należy zwrócić uwagę, że przedrostek c jest używany dla typu Integer i Long.
Tabela 5.3. Przedrostki używane w nazwach zmiennych standardowych.
Zmienna |
Przedrostek
|
Boolean |
b lub f |
Byte |
b lub bt
|
Currency |
cur
|
Date |
dt
|
Double |
d lub dbl
|
lnteger |
i, c lub int
|
Long |
1, c lub lng
|
Single |
s lub sng
|
String |
s lub str
|
Typ zdefiniowany przez programistę |
u lub ut
|
Variant |
v lub var
|
Tabela 5.4. Przedrostki używane w nazwach zmiennych obiektowych.
Zmienna |
Przedrostek
|
Bookmark
|
bmk |
Dialog |
dial
|
Document |
doc
|
Field
|
fld |
Font
|
fnt |
Frame |
fra
|
Paragraph |
para
|
Range
|
rng |
Selection
|
sel |
Table
|
tbl |
Word |
wrd |
Oprócz typu danych, zmienna posiada zakres i okres życia. Niektórzy programiści w nazwie zmiennej zawierają informację o jej zakresie. Na przykład, g oznacza zakres globalny, m - zakres modułu. A zatem, giRozmiar jest zmienną globalną o typie Integer. Zakres i okres życia zmiennej omawiany jest w następnych podrozdziałach (ale nie stosuje się nazw zmiennych, które zawierają informację o ich zakresie).
Zakres zmiennych
Zmienne i stałe posiadają zakres, który wskazuje, w jakim miejscu programu są one rozpoznawane widoczne). Zmienna lub stała może mieć zakres lokalny, modułowy lub publiczny.
Zmienne lokalne
Zmienną - lub stałą - lokalną deklaruje się w procedurze. Na rysunku 5.2 ZmiennaLokalna jest zmienną lokalną, StalaLokalna jest stałą lokalną. Zmienna - lub stała lokalna - nie jest widoczna poza procedurą, w której została zadeklarowana. Jeżeli spróbuje się uruchomić procedurę B przedstawioną na rysunku 5.2, otrzyma się komunikat o błędzie, informujący, że nie zdefiniowano zmiennej, i nazwa ZmiennaLokalna zostanie wyróżniona.
Rysunek 5.2. Przykłady zakresu zmiennych.
Jedną z zalet zmiennych lokalnych jest to, że można używać tej samej nazwy w różnych procedurach, ponieważ każda zmienna lokalna jest widoczna tylko w swojej procedurze.
Zmienne modułowe
Zmienną - lub stałą - modułową deklaruje się w sekcji deklaracji modułu kodu (standardowego, klasy lub formularza). Zmienne - i stałe - modułowe mogą być prywatne (private) lub publiczne (public). Mówiąc najprościej, publiczne zmienne - i stałe - modułowe są widoczne we wszystkich procedurach wszystkich modułów projektu. Prywatne zmienne - i stałe - modułowe są widoczne w procedurach modułu, w którym zostały zadeklarowane.
Zmienne i stałe publiczne deklaruje się za pomocą słowa kluczowego Public:
Public Liczba As Integer
Public Const Pi = 3.14
Zmienne i stałe prywatne deklaruje się za pomocą słowa kluczowego Private:
Private Liczba As Integer
Private Const Pi = 3.14
Deklarując zmienną modułową, zamiast słowa Private można użyć słowa Dim. Może to jednak uczynić kod mniej czytelnym, dlatego zmienne o zakresie modułowym należy deklarować za pomocą słowa Private.
Warto jeszcze wspomnieć o jednej rzeczy. Zmienna - lub stała - publiczna zadeklarowana w module standardowym lub module klasy (ale nie w module formularza) jest widoczna w każdym projekcie posiadającym odwołanie do projektu, w którym została ona zadeklarowana. Ponieważ projekt zawierający dokument zawsze posiada odwołanie do projektu zawierającego dołączony szablon, wszystkie publiczne zmienne i stałe zadeklarowane w projekcie zawierającym szablon są widoczne w projekcie zawierającym dokument. Poza tym wszystkie publiczne zmienne i stałe zadeklarowane w projekcie zawierającym szablon Normal są widoczne we wszystkich projektach.
Zmienne publiczne są czasem nazywane zmiennymi globalnymi, ale określenie to wychodzi z użycia.
Okres życia zmiennej
Zmienne charakteryzują się okresem życia. Różnica między okresem życia a zakresem jest prosta: okres życia określa, jak długo (i kiedy) zmienna zwraca wartość, natomiast zakres określa miejsce, którym zmienna jest dostępna lub widoczna.
Kiedy rozważyć następujący przykład:
Sub ProceduraA ( )
Dim ZmiennaLOkalna As Integer
ZmiennaLokalna = 0
Call ProceduraB
ZmiennaLokalna = 1
End Sub
Należy zwrócić uwagę, że ZmiennaLokalna jest zmienną lokalną. Po wykonaniu wiersza kodu:
Call ProceduraB
następuje przejście do procedury B. W czasie wykonywania procedury B, zmienna ZmiennaLokalna jest poza zasięgiem, ponieważ jest ona lokalną zmienną procedury A - jednak nadal żyje (jest w stanie zwrócić wartość). Innymi słowy, zmienna ciągle istnieje i posiada wartość, ale nie jest dostępna dla kodu procedury B. W procedurze B mogłaby również znajdować się zmienna o nazwie ZmiennaLokalna, która nie miałaby nic wspólnego ze zmienną o tej samej nazwie w procedurze A.
Po wykonaniu procedury B, następuje powrót do procedury A, a konkretnie do wiersza:
ZmiennaLokalna = 1
Jest to poprawna instrukcja, ponieważ zmienna ZmiennaLokalna znowu jest w zasięgu.
Zatem okres życia zmiennej lokalnej ZmiennaLokalna trwa od momentu, kiedy VBA wchodzi do procedury A, aż do momentu, kiedy VBA z niej wychodzi. Okres życia zmiennej ZmiennaLokalna obejmuje również czas wykonywania procedury B wywołanej z procedury A, mimo że w tym czasie zmienna ZmiennaLokalna jest poza zasięgiem.
Nawiasem mówiąc, dokumentacja VBA czasem miesza zakres z widocznością zmiennej. Wydaje się, że twórcy plików pomocy rozumieją różnicę, ale nie zawsze używają tych terminów poprawnie.
Zmienne statyczne
Należy przypomnieć, iż zmienna może znajdować się w zasięgu lub poza nim i nadal zachowywać swoją wartość. Kiedy jednak okres życia zmiennej dobiega końca, zmienna zostaje zniszczona, a jej wartość utracona. Okres życia określa istnienie zmiennej; zakres zmiennej określa jej dostępność.
Rozważając następujące procedury:
Sub ProceduraA()
Call ProceduraB
Call ProceduraB
Call ProceduraB
Call ProceduraB
Call ProceduraB
End Sub
Sub ProceduraB()
Dim x As Integer
x = 5
...
End Sub
Procedura A pięć razy wywołuje procedurę B. W momencie wywołania procedury B, VBA tworzy zmienną lokalną x; kiedy wykonanie procedury B dobiega końca, VBA usuwa zmienną lokalną. Zatem zmienna x jest tworzona i usuwana pięć razy.
Zwykle o to właśnie chodzi. Zdarzają się jednak sytuacje, kiedy chce się, aby okres życia zmiennej lokalnej trwał dłużej niż okres życia procedury, w której została ona zadeklarowana. Można założyć, że chce się stworzyć procedurę, która wykona coś specjalnego, kiedy wywoła się ją po raz pierwszy. Na przykład, poniższe makro zmienia czcionkę zaznaczonego tekstu na Comic Sans:
Sub ZmienNaComic()
Selection.Font.Name = "Comic Sans"
End Sub
Przypuszczając, że chce się ostrzec użytkownika, że Comic Sans jest czcionką nieformalną, i zapytać, czy naprawdę chce dokonać zmian. Chce się to ostrzeżenie i pytanie wyświetlić tylko raz, aby nie naprzykrzać się użytkownikowi. W takiej sytuacji potrzebuje się zmiennej lokalnej, która pamięta, czy procedura ZmienNaComic jest wywoływana po raz pierwszy. Taką zmienną jest zmienna statyczna.
Zmienna statyczna jest zmienną lokalną żyjącą tak długo, jak długo żyje moduł - a nie tylko procedura - w której została zadeklarowana. Zmienna statyczna zachowuje swoją wartość dopóty, dopóki jest aktywny dokument lub szablon zawierający moduł kodu (nawet gdy żaden kod nie jest wykonywany).
Zatem zmienna statyczna posiada zakres zmiennej lokalnej, ale okres życia zmiennej modułowej.
Modyfikując teraz makro ZmienNaComic, aby wyglądało tak, jak przedstawia wydruk 5.2. Najpierw należy zadeklarować zmienną statyczną typu Boolean o nazwie NiePierwszyRaz. Użycie zmiennej o nazwie PierwszyRaz może wydawać się prostsze, jednak problem polega na tym, że VBA automatycznie inicjalizuje zmienne typu Boolean na wartość False. Oznacza to, że w momencie pierwszego wywołania procedury ZmienNaComic zmienna PierwszyRaz miałaby wartość False, a nie o to chodzi. Inicjalizowanie zmiennych zostanie omówione za chwilę.
Wydruk 5.2. Zmodyfikowana procedura ZmienNaComic używająca zmiennej statycznej.
Sub ZmienNaComic()
'Zadeklaruj zmienną statyczną typu Boolean
Static NiePierwszyRaz As Boolean
'Jeżeli użytkownik dokonuje zmiany
'po raz pierwszy, zapytaj o potwierdzenie
If NiePierwszyRaz = False Then
If MsgBox("Comic Sans jest czcionką nieformalną. Kontynuować?", _
vbYesNo) = vbYes Then
'Dokonaj zmiany
Selection.Font.Name = "Comic Sans"
End If
'Uaktualnij wartość zmiennej
NiePierwszyRaz = True
Else
'Jeżeli użytkownik dokonuje zmiany
'po raz kolejny, po prostu dokonaj zmiany Selection.FOnt.Name = "Comic Sans"
End If
End Sub
Instrukcja If sprawdza, czy wartość zmiennej NiePierwszyRaz wynosi False - tak będzie w momencie pierwszego wywołania procedury ZmienNaComic. W takim przypadku VBA wyświetla okno komunikatu przedstawione na rysunku 5.3. Jeżeli użytkownik kliknie przycisk Tak, czcionka zostanie zmieniona. Zmiennej statycznej NiePierwszyRaz typu Boolean zostaje przypisana wartość True. Zmienna NiePierwszyRaz - jako zmienna statyczna - zachowuje swoją wartość nawet po wykonaniu procedury ZmienNaComic.
Rysunek 5.3.Okno komunikatu, wyświetlane, kiedy wartość zmiennej NiePierwszyRaz wynosi False
W czasie następnego wykonywania makra wartość zmiennej NiePierwszyRaz będzie wynosić True, dzięki czemu warunek If:
If NiePierwszyRaz = False Then
będzie fałszywy i funkcja MsgBox nie zostanie wykonana. Wykonana zostanie natomiast klauzula Else: czcionka zostanie zmieniona bez wyświetlania jakiegokolwiek komunikatu. Zmienne statyczne nie są stosowane zbyt często, ale w niektórych sytuacjach mogą okazać się bardzo pomocne.
Chociaż lokalną zmienną statyczną można zastąpić zmienną modułową, lepiej używać zmiennej statycznej, ponieważ jej zakres jest bardziej ograniczony niż zakres zmiennej modułowej. Dzięki stosowaniu zmiennej lokalnej o zwiększonym okresie życia, można uniknąć przypadkowej zmiany wartości zmiennej spoza procedury, w której została zadeklarowana. Należy pamiętać, że procedura może być fragmentem znacznie większego modułu kodu, w którym dzieje się wiele różnych rzeczy. Lepiej więc ukryć zmienną NiePierwszyRaz przed innymi procedurami.
Inicjalizacja zmiennych
Kiedy VBA rozpoczyna wykonywanie procedury, wszystkie jej zmienne są automatycznie inicjalizowane, czyli przypisywane są im wstępne wartości. Generalnie nie należy polegać na inicjalizacji, ponieważ program jest mnie czytelny i podatny na powstawanie błędów logicznych. Należy więc inicjalizować zmienne lokalne samodzielnie jak pokazuje poniższy wydruk:
Sub Inicjalizuj()
Dim x As Integer
Dim s As String
x = 0 'Zmiennej x przypisz 0
s = "" 'Zmiennej s przypisz pusty łańcuch znaków
'W tym miejscu dodaj kod...
End Sub
Należy zwrócić uwagę, że nie można zainicjalizować zmiennych statycznych. Należy więc zapoznać się z zasadami, według których VBA inicjalizuje zmienne:
• zmiennym numerycznym (Integer, Long, Single, Double i Currency) VBA przypisuje wartość zero;
• łańcuchowi znaków o zmiennej długości VBA przypisuje pusty łańcuch znaków;
• łańcuch znaków o stałej długości VBA wypełnia znakiem reprezentowanym przez znak ASCII 0 lub Chr(0);
• zmiennej typu Variam VBA przypisuje wartość Empty;
• zmiennej obiektowej VBA przypisuje wartość Nothing.
Słowo kluczowe Nothing spełnia kilka funkcji w VBA. Nothing służy do usuwania odwołania do obiektu. Służy też jako wartość zwracana przez niektóre funkcje, z reguły do wskazania, że operacja się nie powiodła. Wreszcie, służy do inicjalizowania zmiennych obiektowych.
Operatory języka VBA
VBA używa garści operatorów i znaków porównań - niektóre z nich przedstawia tabela 5.5.
Tabela 5.5. Operatory i znaki porównań.
Typ |
Nazwa |
Symbol
|
Operatory arytmetyczne |
Dodawanie Odejmowanie Mnożenie Dzielenie Dzielenie bez reszty Potęgowanie Modulo
|
+ - * / \ ^ Mod |
Operator łańcucha znaków |
Konkatenacja |
&
|
Operatory logiczne |
AND OR NOT
|
And Or Not
|
Operatory porównania |
Równy Mniejszy od Większy od Mniejszy lub równy Większy lub równy Różny
|
= < > <= lub =< >= lub => <> lub >< |
Operator Mod zwraca resztę z dzielenia. Na przykład:
8 Mod 3
zwraca 2, ponieważ reszta z dzielenia 8 przez 3 wynosi 2.
Konkatenacja oznacza połączenie łańcuchów znaków. Na przykład wyrażenie:
"Być albo " & "nie być"
jest tożsame z wyrażeniem:
"Być albo nie być"
Funkcje i podprogramy
VBA pozwala na definiowanie trzech typów procedur. Są to: funkcja, podprogram (subroutine) i Property. Różnica między funkcją a podprogramem polega na tym, że funkcja zwraca wartość, a podprogram nie zwraca.
Wywoływanie funkcji
Funkcję deklaruje się według następującego wzoru:
[Public lub Private] Function NazwaFunkcji (Parametrl As TypDanychl, _
Parametr2 As TypDanych2, ...) As TypZwracanejWartości
Należy podać typ danych nie tylko każdego parametru, ale i zwracanej wartości. W przeciwnym razie VBA przypisze im typ Variant.
Opcjonalne słowa kluczowe Public i Private omówione zostaną za chwilę, ale nietrudno się domyślić, że podobnie jak w deklaracjach zmiennych - wskazują one zakres funkcji. Na przykład funkcja DodajJeden, przedstawiona w wydruku 6.1, dodaje 1 do oryginalnej wartości.
Wydruk 6. 1. Funkcja DodajJeden.
Public Function DodajJeden(Wartość As Integer) As Integer DodajJeden = Wartość + 1
End FunCtion
Aby użyć wartości zwracanej przez funkcję, należy wywołać funkcję w miejscu, w którym ta wartość ma zostać odczytana. Na przykład wiersz kodu:
MsgBox "1 + 5 = " & DodajJeden(5)
wyświetla okno komunikatu pokazane na rysunku 6.1. Wyrażenie
DodajJeden(5)
zostaje zastąpione przez wartość zwracaną przez funkcję DodajJeden - w tym przypadku 6.
Należy zwrócić uwagę, że generalnie parametry przekazywane funkcji w czasie jej wywoływania muszą znajdować się w nawiasach.
Aby funkcja mogła zwrócić wartość, w treści funkcji należy przypisać tę wartość do nazwy funkcji. Wydruk 6.2 pokazuje bardziej złożony przykład funkcji.
Rysunek 6.1. Okno komunikatu wygenerowane za pomocą instrukcji MsgBox.
Wydruk 6.2. Przypisywanie zwracanej wartości do nazwy funkcji.
Function Policz (Co As String) As Long
'Zwróć liczbą znaków lub liczbę wyrazów
'w aktywnym dokumencie
'Zwróć -1, jeżeli funkcji nie przekazano
'ani wartości "Znaki", ani "Wyrazy"
If Co = "Znaki" Then
'Zwróć liczbę znaków
Policz = ActiveDocument.Characters.Count
ElseIf Co = "wyrazy" Then
'Zwróć liczbę słów
Policz = ActiveDocument.Words.Count
Else
'Zwróć -1
Policz = -1
End If
End Function
Funkcja Policz zwraca liczbę znaków lub liczbę wyrazów w aktywnym dokumencie w zależności od wartości parametru przekazywanego funkcji. Parametry zostaną omówione w dalszej części tego rozdziału. Warto zwrócić uwagę, że do nazwy funkcji przypisane są różne wartości w zależności od wartości parametru. Przypisania wzajemnie się wykluczają; tylko jedno z nich zachodzi w czasie danego wywołania funkcji.
Ignorowanie zwracanej wartości
Może się zdarzyć, że chce się wywołać funkcję, ale nie potrzebuje się wartości, którą ona zwraca. Można założyć, że fragment jest zmienną reprezentującą fragment (Range) tekstu dokumentu Worda. Można przesunąć koniec fragmentu tekstu za pomocą metody MoveEnd. Jest to funkcja, która przesuwa koniec fragmentu tekstu o podaną liczbę jednostek i zwraca liczbę jednostek, o którą koniec tego fragmentu został rzeczywiście przesunięty. Liczba przesuniętych jednostek może być mniejsza od liczby podanych jednostek, jeżeli fragment tekstu „zderzy się" z początkiem lub końcem dokumentu przed zakończeniem zdania.
Na przykład kod:
Dim odległość As Long
odległość = fragment.MoveEnd(wdCharacter, 5)
próbuje przesunąć koniec fragmentu tekstu fragment o pięć znaków w prawo. Jeżeli próba zakończy się sukcesem, funkcja zwraca liczbę 5. Jeżeli jednak na prawo od bieżącej pozycji końcowej znajduje się mniej niż 5 znaków, fragment tekstu zostanie przesunięty w prawo o tyle znaków, o ile to możliwe i funkcja zwróci liczbę znaków, o którą fragment został przesunięty.
Chociaż wartość zwracana przez metodę MoveEnd często jest użyteczna, są sytuacje, kiedy nie jest ona potrzebna. Na przykład poniższy kod zaznacza pierwszy akapit aktywnego dokumentu, w tym również znak akapitu:
Dim fragment As Range
Set fragment = ActiveDocument.Paragraphs(1).Range
fragment.Select
Jeżeli nie chce się zaznaczyć znaku akapitu, można przed zaznaczeniem fragmentu tekstu użyć metody MoveEnd, aby przesunąć koniec fragmentu tekstu o jeden znak w lewo:
Dim odległość As Long
Dim fragment As Range
Set fragment = ActiveDocument.Paragraphs(1).Range
odległość = fragment.MoveEnd(wdCharacter, -1)
fragment.Select
Na lewo od bieżącego punktu końcowego znajduje się co najmniej jeden znak - znak akapitu jest zawsze obecny, więc fragment tekstu (Range) zawiera co najmniej jeden znak - dlatego funkcja MoveEnd zwróci wartość -1. Przesunięcie odbywa się w lewo, więc wartość jest negatywna..
W poprzednich wersjach VBA nie byłoby innego wyboru jak tylko zadeklarować zmienną odległość, a następnie zignorować jej wartość, jak to zostało zrobione w powyższym przykładzie. Obecna wersja VBA pozwala na wyszczuplenie kodu w następujący sposób:
Dim fragment As Range
Set fragment = ActiveDocument.Paragraphs(1).Range fragment.MoveEnd wdCharacter, -1
fragment.Select
Należy podkreślić, że wywołana została funkcja bez określania zwracanej wartości i nie zostały umieszczone parametry w nawiasach. W ten sposób informuje się VBA, że nie interesuje programistę wartość zwracana przez funkcję.
Wywoływanie podprogramów
Podprogram deklaruje się według następującego wzoru:
[Public lub Private] Sub NazwaPodprogramu (Parametrl As TypDanychl, _ Parametr2 As TypDanych2, ...)
Deklaracja podprogramu w przeciwieństwie do deklaracji funkcji nie zawiera fragmentu As TypZwracanejWartości. Należy zwrócić również uwagę na użycie słowa kluczowego Sub zamiast słowa Function.
Ponieważ podprogramy nie zwracają wartości, nie można używać ich w wyrażeniach. Aby wywołać podprogram o nazwie PodprogramA, można napisać:
Call PodprogramA(parametry, ...)
lub po prostu
PodprogramA parametry
Kiedy używa się słowa kluczowego Call, parametry muszą być umieszczone w nawiasach.
Parametry i argumenty
Kiedy rozważyć następujący prosty podprogram, który nie robi nic poza wyświetleniem okna komunikatu zawierającego nazwisko osoby:
Sub WyświetlNazwisko(sNazwisko As String)
MsgBox "Nazywam się " & sNazwisko
End Sub
Aby wywołać ten podprogram, napisanoby na przykład:
WyświetlNazwisko "Kowalski"
lub
Call WyświetlNazwisko("Kowalski")
Zmienna sNazwisko w deklaracji procedury:
Sub WyświetlNazwisko(sNazwisko As String)
jest nazywana parametrem. Generalnie, kiedy wywołuje się procedurę, parametr musi zostać wypełniony. Wartość przekazywana do procedury jest nazywana argumentem. A zatem w powyższym przykładzie argumentem jest łańcuch znaków „Kowalski".
Warto zauważyć, że wielu programistów używa słów „parametr" i „argument" zamiennie. Należy jednak pamiętać, że parametr jest jak zmienna, natomiast argument jest jak wartość zmiennej. Dlatego nieodróżnianie parametru od argumentu jest jak nieodróżnianie zmiennej od jej wartości.
Argumenty opcjonalne
Za pomocą słowa kluczowego Optional można określić argument jako opcjonalny. Nie można powiedzieć, że parametr jest opcjonalny: opcjonalne jest przypisanie wartości. Można rozważyć procedurę przedstawioną w wydruku 6.3. Procedura ta zmienia nazwę i rozmiar czcionki zaznaczonego tekstu.
Wydruk 6.3. Stosowanie argumentu opcjonalnego.
Sub ZmienFormatowanie(NazwaCzcionki As String, _
Optional RozmiarCzcionki As Variant)
'Zmień nazwę czcionki
Selection.Font.Name = NazwaCzcionki
'Zmień rozmiar czcionki,
'jeżeli zostanie podany
If Not IsMissing(RozmiarCzcionki) Then Selection.Font.Size = CInt(RozmiarCzcionki)
End If
End Sub
Drugi parametr został zadeklarowany za słowem kluczowym Optional. Dzięki temu wywołując procedurę, można podać argument dla tego parametru lub go nie podawać:
ZmienFormatowanie "Arial Narrow", 24
lub
ZmienFormatowanie "Arial Narrow"
Warto podkreślić, że funkcja IsMissing użyta w treści procedury służy do określania, czy argument jest obecny. Jeżeli argument jest obecny, rozmiar czcionki zostaje zmieniony. Należy zwrócić również uwagę, że parametr RozmiarCzcionki posiada typ Variant, ponieważ funkcja IsMissing działa tylko z parametrami typu Variant. Za pomocą funkcji Clnt przekonwertowany zostałby typ Variant na typ Integer.
Procedura może mieć dowolną liczbę argumentów opcjonalnych, ale muszą się one znajdować na końcu listy parametrów. Poniższa deklaracja nie jest zatem poprawna:
Sub ZmienFormatowanie(Optional NazwaCzcionki As String, _ RozmiarCzcionki As Single)
Jeżeli w czasie wywoływania procedury opuści się argument w środku listy, musi się dodać spację. Na przykład, jeżeli zadeklarowana została następująca procedura:
Sub ZmienFormatowanie(
Optional NazwaCzcionki As String, _
Optional RozmiarCzcionki As Single, _
Optional PogrubienieCzcionki As Boolean)
End Sub
i wywołując ją chce się podać argumenty jedynie dla parametrów NazwaCzcionki i PogrubienieCzcionki, powinno się zrobić to w następujący sposób:
ZmienFormatowanie "Arial", , True
Warto zauważyć, że niektóre procedury wbudowane Worda mają argumenty opcjonalne, a inne nie. Oczywiście można opuścić tylko te argumenty, które w deklaracji są oznaczone jako opcjonalne.
Argumenty predefiniowane
Niektóre procedury wbudowane mogą zawierać dużą liczbę parametrów. Oto na przykład deklaracja funkcji ConvertToTable, która konwertuje zaznaczony tekst do postaci tabeli:
ConvertToTable( _
Separator, NumRows, NumColumns, _
InitialColumnWidth, Format, ApplyBorders, _ ApplyShading, ApplyFont, ApplyColor, _
ApplyHeadingRows, ApplyLastRow, _
ApplyFirstColumn, ApplyLastColumn, AutoFit, _ AutoFitBehavior, DefaultTableBehavior)
Wszystkie parametry tej funkcji są opcjonalne i posiadają typ Variant. Oto przykład wywołania tej procedury:
ConvertToTable wdSeparateByTabs, 5, 7, , ,True, True, True, _ ,,True, , ,True
Niezbyt czytelny wiersz, prawda?
Argumenty przedstawione w powyższym wywołaniu funkcji ConvertToTable są nazywane argumentami pozycyjnymi, ponieważ ich pozycja informuje VBA, jakie parametry one zastępują. Właśnie dlatego brakujący argument musi być wskazany przez spację.
VBA może również używać argumentów predefiniowanych, co pozwala wywołać procedurę ConvertToTable w następujący sposób:
ConvertToTable _
Separator:=wdSeparateByTabs, NumRows:=5, _
NumColumns:=7, ApplyBorders:=True, _
ApplyShading:=True, ApplyFont:=True, _
ApplyLastRow:=True, AutoFit:=True
Należy zwrócić uwagę na składnię stosowaną dla argumentów predefiniowanych - zwłaszcza na dwukropek przed znakiem równości.
Ten rodzaj wywołania jest znacznie lepszy od poprzedniego (z argumentami pozycyjnymi). Argumenty predefiniowane są nie tylko czytelniejsze, ale mają dwie inne zalety: nie trzeba wpisywać spacji w miejsce brakujących argumentów i można wpisywać argumenty w dowolnej kolejności. Zaleca się stosowanie argumentów predefiniowanych, ze względu na to, że znacznie poprawiają czytelność kodu. Jednak wymagają one więcej miejsca, dlatego w krótkich przykładach omawianych w tej pracy nie będzie się ich zwykle stosować.
Przekazywanie argumentów przez referencję i przez wartość
Argumenty można przekazywać przez referencję (ByRef) lub przez wartość (ByVal).
Aby zrozumieć różnicę, należy rozważyć dwie procedury pokazane w wydruku 6.4. Procedura A przypisuje zmiennej modułowej x wartość 5, wyświetla tę wartość, wywołuje procedurę DodajJeden z argumentem x i ponownie wyświetla wartość x..
Wydruk G 4. Testowanie stów kluczowych ByVal i ByRef
Sub ProceduraA()
x = 5
MsgBox x
Call DodajJeden(x)
MsgBox x
End Sub
Sub DodajJeden(ByRef i As Integer)
i = i + 1
End Sub
Należy zwrócić uwagę na obecność słowa kluczowego ByRef w deklaracji procedury DodajJeden. Słowo ByRef sprawia, że VBA przekazuje procedurze DodajJeden referencję do zmiennej x. Oznacza to, że procedura DodajJeden zastępuje swój parametr i zmiennąx, dzięki czemu wiersz:
i = i + 1
staje się wierszem:
x = x + 1
A zatem, po wywołaniu procedury DodajJeden zmienna x ma wartość 6
Kiedy zmienić słowo kluczowe ByRefna słowo ByVal:
Sub DodajJeden(ByVal i As Integer)
i = i + 1
End Sub
W tym przypadku VBA nie przekazuje procedurze DodajJeden referencji do zmiennej x, ale wartość zmiennej. Dzięki temu zmienna i w procedurze DodajJeden po prostu przyjmuje wartość 5. Po dodaniu 1 do tej wartości otrzymuje się 6. Zatem i wynosi 6, ale wartość argumentu x nie zmienia się. Dlatego obydwa okna komunikatów w procedurze A wyświetlają dla zmiennej x wartość 5.
Oba sposoby przekazywania argumentów mają swoje zastosowania. Aby zmienić wartość argumentu, należy zadeklarować odpowiadający mu parametr za pomocą słowa kluczowego ByRef, dzięki czemu wywoływana procedura ma dostęp do tego argumentu.
Kiedy nie chce się, aby argument został zmieniony, przekazuje się go przez wartość za pomocą słowa kluczowego ByVal. W tym przypadku wywoływana procedura otrzymuje jedynie wartość argumentu.
Zilustruje to poniższy przykład. Procedura A w wydruku 6.5 otrzymuje tekst aktywnego dokumentu i przekazuje go jako argument funkcji PoliczZnaki. Zwrócona wartość (liczba znaków aktywnego dokumentu) jest wyświetlona w oknie komunikatu.
Wydruk 6.5. Przekazywanie argumentu przez wartość.
Sub ProceduraA()
Dim sTekst As String
sTekst = ActiveDocument.Content.Text
MsgBox PoliczZnaki(sTekst)
End Sub
Function PoliczZnaki(ByVal sTxt as String)
PoliczZnaki = Len(sTxt)
End Function
Funkcja PoliczZnaki nie musi - i nie powinna - zmieniać tekstu. Jej zadaniem jest tylko policzenie liczby znaków w tekście. Dlatego przekazany został argument przez wartość. W ten sposób zmienna sTxt otrzymuje wartość tekstu przechowywaną w argumencie sTekst, czyli otrzymuje kopię tekstu.
Jeśli wyobrazić sobie, że funkcję PoliczZnaki zastąpi się procedurą zawierającą setki lub tysiące wierszy kodu napisanego przez kogoś, na kim nie można zbytnio polegać. Naturalnie ma się obawę, że ta procedura może zmienić nasz tekst. Nie musi się sprawdzać kodu wiersz po wierszu, ponieważ widać, że parametr sTxt jest wywoływany przez wartość, dzięki czemu procedura nie ma nawet dostępu do programowanego tekstu - jedynie do kopii tekstu.
Jest jedna wada przekazywania argumentów przez wartość. W powyższym przykładzie, VBA musi pobić kopię tekstu przekazywanego parametrowi sTxt. Zajmuje to dużo pamięci i czasu szczególnie w przypadku przekazywania zawartości całego dokumentu. Jeżeli dokument zawiera setki tysięcy znaków, procedura może okazać się zbyt wolna.
Podsumowując: jeżeli chce się, aby procedura zmodyfikowała argument, przekazuje się go przez referencję. Jeżeli argument ma pozostać niezmieniony, należy go przekazać przez wartość. Należy pamiętać, że przekazanie argumentu przez wartość może spowolnić program.
Warto zauważyć, że domyślnie argumenty są przekazywane przez referencję. Oznacza to, że wartości argumentów mogą być zmieniane przez wywoływane procedury, chyba że użyje się słowa kluczowego ByVal.
Wychodzenie z procedury
Aby wyjść z procedury, zanim procedura sama zakończy swoje działanie, należy użyć instrukcji Exit Sub i Exit Function. Na przykład, jeżeli wartość parametru nie jest poprawna, można wyświetlić komunikat informujący użytkownika o problemie, a następnie zakończyć działanie procedury (wydruk 6.6).
Wydruk 6.6 InstrukcjaExitSub.
Sub WyswietlNazwisko(sNazwisko As String)
If sNazwisko = "" Then
MsgBox "Wpisz nazwisko."
Exit Sub
End If
MsgBox "Wpisałeś nazwisko " & sNazwisko
End Sub
Procedury publiczne i prywatne
Procedury, podobnie jak zmienne i stałe, posiadają zakres. Można deklarować procedury za pomocą słów kluczowych Public lub Private:
Public Function DodajJeden(i As Integer) As Integer
lub
Private Function DodajJeden(i As Integer) As Integer
Procedura prywatna może być wywołana tylko z modułu, w którym została zdefiniowana; procedura publiczna może być wywołana z każdego modułu projektu.
Jeżeli w deklaracji procedury nie występuje ani słowo Public ani słowo Private, procedura jest uznawana za publiczną.
Dodawanie odwołań do projektu
Aby wywołać procedurę publiczną rezydującą winnym projekcie, projekt wywołujący musi mieć odwołanie (referencję) do projektu wywoływanego.
Ogólnie mówiąc, projekt związany z danym dokumentem widzi tylko procedury znajdujące się w tym projekcie, w szablonie dołączonym do dokumentu lub w szablonie Normal.
Aby z danego projektu wywołać procedurę rezydującą w tym samym projekcie, nie musi się dodawać żadnych odwołań. Również jeżeli z danego projektu chce się wywołać procedurę rezydującą w dołączonym szablonie, nie musi się dodawać żadnych odwołań, ponieważ Word automatycznie dodaje odwołanie do dołączonego szablonu.
Jeżeli natomiast dołączonym szablonem nie jest szablon Normal, a chce się wywołać procedurę rezydującą w tym szablonie lub jeżeli chce się wywołać procedurę z innego projektu, musi się dodać odwołanie do wywoływanego projektu. W tym celu korzysta się z okna References (dostępnego z menu Tools), przedstawionego na rysunku 6.2.
Rysunek 6.2. Okno References.
Warto zauważyć, że jeżeli dołączonym do dokumentu szablonem nie jest szablon Normal, Word nie dołącza automatycznie odwołania do projektu Normal w projekcie dokumentu. Jest to trochę dziwne, ponieważ z dokumentu można wykonać każdą makrodefinicję rezydującą w szablonie Normal (za pomocą podmenu Makra na przykład), ale nie można wywołać takich makr za pomocą kodu w projekcie dokumentu, bez dodania odwołania do projektu Normal.
Pełne nazwy procedur
W różnych modułach mogą znajdować się procedury o identycznych nazwach. W przypadku wywołania procedury o niejednoznacznej nazwie, VBA wykona tę, którą znajdzie jako pierwszą. Może się jednak okazać, że nie jest to ta, o którą chodzi programiście.
Rozwiązaniem tego problemu jest stosowanie pełnej nazwy procedury według poniższego wzoru:
NazwaModułu.NazwaProcedury
Na przykład, jeżeli procedura publiczna o nazwie DodajJeden rezyduje w module o nazwie MojeProcedury, można ją wywołać w następujący sposób:
MojeProcedury.DodajJeden
W razie potrzeby można podać również nazwę projektu:
NazwaProjektu.NazwaModułu.NazwaProcedury
Funkcje i instrukcje
wbudowane
VBA posiada wiele wbudowanych funkcji i podprogramów. W tym rozdziale i następnym omówione zostaną te z nich, które są używane najczęściej (przynajmniej w programach pisanych w Wordzie). Oto funkcje VBA:
Abs CVar GetAlISettings IsObject
Array CVDate GetAttr LBound
Asc CVErr GetAutoServerSettings LCase
AscB Date GetObject Left
Asc W DateAdd GetSetting LeftB
Atn DateDiff Hex Len
CBool DatePart Hour LenB
CByte DateSerial IIf LoadPicture
CCur DateValue IMEStatus Loc
CDate Day Impt LOF
CDbI DDB Input Log
CDec Dir InputB LTrim
Choose DoEvents InputBox Mid
Chr Environ InStr MidB
ChrB EOF InStrB Minute
ChrW Error Int MIRR
C Int Exp IRR Month
CLng FileAttr IsArray MsgBox
Command FileDateTime IsDate Now
Cos FileLen IsEmpty Nper
CreateObject Fix IsError NPV
CSng Format IsMissing Oct
CStr FreeFile IsNull Partition
CurDir FV IsNumeric Pmt
PPmt Seek StrConv Trim
PV Sgn String TypeName
QBColor Shell Switch UBound
Rate Sin SYD UCase
RGB SLN Tab Val
Right Space Tan VarType
RightB Spc Time Weekday
Rnd Sqr Timer Year
RTrim Str TimeSerial
Second StrComp TimeValue
Oto instrukcje VBA:
AppActivate Do...Loop Mid Reset
Beep End MidB Resume
Call Enum MkDir Return
ChDir Erase Name RmDir
ChDrive Error On Error RSet
Close Event On...GoSub SavePicture
Const Exit On...GoTo SaveSetting
Date FileCopy Open Seek
Declare For Each...Next Option Base Select Case
DefBool For...Next Option Compare SendKeys
DefByte Function Option Explicit Set
DefCur Get Option Private SetAttr
DefDate GoSub...Return Print# Static
DefDbl GoTo Private Stop
DefDec If...Then...Else Property Get Sub
Deflnt Implements Property Let Time
DefLng Input# Property Set Type
DefObj Kill Public Unload
DefSng Let Put Unlock
Defstr Line Input# RaiseEvent While... Wend
Def Var Load Randomize Width#
DeleteSetting Lock ReDim With
Dim LSet Rem Write#
Przyjęta zostało w tej pracy zasada, że opcjonalne parametry są wskazywane za pomocą nawiasów kwadratowych. Na przykład, drugi parametr w poniższej procedurze jest opcjonalny:
Sub ZmianaFormatu (NazwaCzcionki [, RozmiarCzcionki])
Funkcja MsgBox
Używana już była funkcja MsgBox kilkakrotnie. Nadszedł czas na oficjalną prezentację. Funkcja : MsgBox służy do wyświetlania okna komunikatu z przyciskami, które użytkownik może kliknąć. Oto najczęściej używana składnia tej funkcji:
MsgBox (komunikat [ ,przyciski] [ ,tytuł])
Poza wyżej podanymi parametrami funkcja MsgBox posiada parametry opcjonalne związane z pomocą kontekstową. Pełną informację na temat funkcji MsgBox można znaleźć w dokumentacji VBA. W podanym przykładzie komunikat jest parametrem typu String zawierającym tekst wyświetlany w oknie komunikatu. Warto zwrócić uwagę, że można stworzyć wielowierszowe komunikaty za pomocą stałej vbCrLf.
Parametr przyciski posiada typ Long i podaje sumę wartości określających różne właściwości okna komunikatów, w tym liczbę i typ wyświetlanych przycisków, styl użytej ikony, przycisk domyślny oraz modalność okna komunikatu. Systemowe okno modalne pozostaje na wierzchu wszystkich otwartych okien i jest gotowe do przyjmowania danych (posiada fokus). Okno modalne aplikacji zostaje na wierzchu okien danej aplikacji i jest gotowe do przyjmowania danych (posiada fokus). W tabeli 7.1 przedstawiono różne wartości przyjmowane przez parametr przyciski. Zostały one zdefiniowane w enumeracji VbMsgBoxStyle.
Tabela 7.1. Wartości przyjmowane przez parametr przyciski funkcji MsgBox.
Cel
|
Stała |
Wartość |
Opis |
Typy przycisków
|
vbOKOnly
vbOKCancel
vbAbortRetryIgnore
vbYesNoCancel
vbYesNo
vbRetryCancel |
0
1
2
3
4
5
|
Wyświetla tylko przycisk OK Wyświetla przyciski OK i Anuluj Wyświetla przyciski Przerwij, Ponów próbę i Zignoruj Wyświetla przyciski Tak, Nie i Anuluj Wyświetla przyciski Tak i Nie Wyświetla przyciski Ponów próbę i Anuluj Ponów próbę i Zignoruj
|
Typy ikon |
vbCritical
vbQuestion
vbExclamation
vbInformation |
16
32
48
64 |
Wyświetla ikonę wiadomości krytycznej Wyświetla ikonę przedstawiającą znak zapytania Wyświetla ikonę wiadomości ostrzegawczej Wyświetla ikonę wiadomości
|
Przycisk domyślny |
vbDefaultButtonl
vbDefaultButton2
vbDefaultButton3
vbDefaultButton4 |
0
256
512
768 |
Domyślnym jest przycisk pierwszy Domyślnym jest przycisk drugi Domyślnym jest przycisk trzeci Domyślnym jest przycisk czwarty
|
Modalność |
vbApplicationModal
vbSystemModal |
0
4096 |
Okno modalne aplikacji Systemowe okno modalne
|
Na przykład następujący wiersz kodu:
MsgBox "Kontynuować?", vbQuestion + vbYesNo
wyświetla okno komunikatu zawierające ikonę przedstawiającą znak zapytania oraz dwa przyciski: Tak i Nie (Rysunek 7.1).
Parametr tytuł jest łańcuchem znaków wyświetlanym w pasku tytułowym okna komunikatu. Jeżeli pominąć ten argument, w pasku tytułowym pojawi się napis Microsoft Word (Rysunek 7.1).
Rysunek 7.1. Okno komunikatu utworzone za pomocą funkcji MsgBox.
Funkcja MsgBox zwraca liczbę wskazującą przycisk kliknięty przez użytkownika. Wartości - zdefiniowane w enumeracji VBMsgBoxResult - zwracane przez funkcję MsgBox przedstawia tabela 7.2.
Tabela 7.2. Wartości zwracane przez funkcję MsgBox
Stała
|
Wartość |
Opis |
vbOK |
1 |
Naciśnięto przycisk OK
|
vbCancel |
2 |
Naciśnięto przycisk Anuluj
|
vbAbort |
3 |
Naciśnięto przycisk Przerwij
|
vbRetry |
4 |
Naciśnięto przycisk Ponów próbę
|
vbIgnore |
5 |
Naciśnięto przycisk Zignoruj
|
vbYes |
6 |
Naciśnięto przycisk Tak
|
vbNo |
7 |
Naciśnięto przycisk Nie
|
Funkcja InputBox
Funkcja InputBox umożliwia użytkownikowi wprowadzanie danych. Oto często używana (chociaż niepełna) składnia tej funkcji:
InputBOx (komunikat, [, tytuł] [, WartośćDomyślna])
W powyższym przykładzie komunikat jest tekstem wyświetlanym w okienku dialogowym, tytuł - tekstem wyświetlanym w jego pasku tytułowym, WartośćDomyślna - tekstem wyświetlanym w polu tekstowym. Na przykład wiersz kodu:
sNazwisko = InputBox("Wpisz nazwisko", "Nazwisko", "Malinowski")
wyświetli okno dialogowe przedstawione na rysunku 7.2.
Rysunek 7.2. Okno dialogowe wygenerowane za pomocą funkcji InputBox.
Funkcja InputBox zwraca łańcuch znaków wpisany w polu tekstowym przez użytkownika. A zatem w przykładzie łańcuch znaków będzie przechowywany w zmiennej sNazwisko.
Należy zwrócić uwagę, że funkcja InputBox umożliwia użytkownikowi wpisywanie liczb. W takim przypadku zwrócony przez funkcję łańcuch znaków (taki jak „12,55'') należy przekonwertować do postaci liczby (12,55) za pomocą funkcji Val, opisanej w dalszej części tego rozdziału.
Funkcje umożliwiające operacje na łańcuchach znaków
Oto garść użytecznych funkcji umożliwiających wykonywanie operacji na łańcuchach znaków (zarówno stałych, jak i zmiennych):
Funkcja Len
Funkcja Len zwraca długość łańcucha znaków, czyli liczbę znaków w łańcuchu. Wiersz kodu:
Len("Styczeń")
zwraca liczbę 7.
Funkcje UCase i LCase
Funkcje te konwertują łańcuch znaków odpowiednio na duże i małe litery. Składnia tych funkcji wygląda tak:
UCase(ŁańcuchZnaków)
LCase(ŁańcuchZnaków)
Na przykład wiersz kodu:
MsgBox UCase("Malinowski")
wyświetli łańcuch znaków „MALINOWSKI"
Funkcje Left, Right i Mid
Funkcje te zwracają fragment łańcucha znaków, a mianowicie funkcja:
Left(ŁańcuchZnaków, x)
zwraca x znaków z lewej strony łańcucha znaków, natomiast funkcja:
Right(ŁańcuchZnaków, x)
zwraca x znaków z prawej strony łańcucha znaków. Na przykład:
MsgBox Right("Alicja Kwiatkowska", 11)
wyświetla łańcuch znaków „Kwiatkowska". Funkcja Mid ma następującą składnię:
Mid(ŁańcuchZnaków, Początek, x)
Funkcja ta zwraca x znaków łańcucha znaków ŁańcuchZnaków, zaczynając od znaku podanego w parametrze Początek. Na przykład wiersz kodu:
Mid("Biblioteka.doc", 12, 3)
zwraca łańcuch „doc". Jeżeli nie podano wartości dla parametru x:
Mid("Biblioteka.doc", 12)
funkcja zwraca resztę łańcucha znaków rozpoczynając od znaku określonego w parametrze Początek.
Funkcja InStr
Oto składnia tej niezwykle pożytecznej funkcji:
InStr(Początek, ŁańcuchPrzeszukiwany, ŁańcuchDoZnalezienia)
Funkcja InStr zwraca liczbę określającą pozycję początku łańcucha ŁańcuchDoZnalezienia w łańcuchu ŁańcuchPrzeszukiwany. Przeszukiwanie rozpoczyna się od pozycji określonej w parametrze Początek. Jeżeli nie podano wartości tego parametru, funkcja rozpoczyna przeszukiwanie na początku łańcucha ŁańcuchPrzeszukiwany. Na przykład wiersz kodu:
MsgBox InStr(1, "Alicja Kwiatkowska", "Kwiatkowska")
wyświetla 8, ponieważ łańcuch znaków „Kwiatkowska" rozpoczyna się na ósmej pozycji w łańcuchu „Alicja Kwiatkowska".
Funkcje Str i Val
Funkcja Str konwertuje liczbę na łańcuch znaków. Na przykład kod:
Str(123)
zwraca łańcuch znaków „123". Funkcja Val konwertuje łańcuch znaków reprezentujący liczbę na liczbę, dzięki czemu można wykonywać na nim działania arytmetyczne. Na przykład, wiersz kodu:
Val("4.5")
zwraca liczbę 4,5, natomiast kod:
Val("1234 Ulica Szeroka")
zwraca liczbę 1234. Warto podkreślić, że funkcja Val nie rozpoznaje znaków dolara ($) i przecinka (,). A zatem wiersz kodu:
val("$12,00") zwraca 0, nie 12,00
Funkcje Trim, LTrim i RTrim
Funkcja LTrim usuwa wiodące spacje z łańcucha znaków. Funkcja RTrim usuwa spacje występujące po łańcuchu znaków. Funkcja Trim usuwa zarówno spacje wiodące, jak i występujące po łańcuchu znaków.
Oznacza to, że wiersz kodu:
Trim(" dodatkowe ")
zwraca łańcuch znaków „dodatkowe ".
Funkcje String i Space
Funkcja String umożliwia utworzenie łańcucha znaków składającego się z jednego znaku powtórzonego wielokrotnie. Na przykład wiersz kodu:
sTekst = String(25, "A")
przypisuje zmiennej sTekst łańcuch znaków składający się z 25 znaków „A". Funkcja Space zwraca łańcuch znaków składający się z danej liczby spacji. Na przykład kod:
sTekst = Space(25)
przypisuje zmiennej sTekst łańcuch znaków składający się z 25 znaków spacji.
Operator Like i funkcja StrComp
Operator Like służy do porównywania dwóch łańcuchów znaków. Można oczywiście użyć znaku równości:
ŁańcuchZnakówl = ŁańcuchZnaków2
Powyższe wyrażenie jest prawdziwe, jeżeli dwa łańcuchy znaków są identyczne. Jednak operator Like umożliwia porównywanie uwzględniające duże i małe litery oraz sprawdzanie zgodności łańcucha znaków ze wzorem.
Wyrażenie:
ŁańcuchZnaków Like Wzór
zwraca wartość True, jeżeli łańcuch znaków ŁańcuchZnaków jest zgodny ze wzorem, natomiast False - jeżeli nie jest. Właściwie wyrażenie może zwrócić Null, ale nie będzie się omawiać tego zagadnienia, ponieważ częściej występuje ono w aplikacji Access niż Word. Co to jest wzór (pattern), wyjaśnione zostanie za chwilę.
Typ porównywania łańcuchów znaków stosowany przez operator Like zależy od ustawienia instrukcji Option Compare. Są dwie możliwości:
Option Compare Binary
Option Compare Text
Jedną z powyższych instrukcji należy umieścić w sekcji deklaracji modułu kodu (tuż pod instrukcją Option Explicit). Należy zwrócić uwagę, że domyślną opcją jest Option Compare Binary. Kiedy stosuje się Option Compare Binary, porównywanie łańcuchów znaków odbywa się w porządku określonym przez kody znaków ANSI:
A<B<...<Z<a<b<...<z<Ą<...<Ó<ą<...<ó
Kiedy stosuje się Option Compare Text, porównywanie łańcuchów znaków nie jest wrażliwe na duże i małe litery i zależy od lokalnych ustawień systemu. Oznacza to, że znaki są sortowane w następującym porządku:
A=a<Ą=ą<B=b<...<Z=z<Ó=ó
Nawiasem mówiąc, ostatnim znakiem jest znak [ posiadający wartość ANSI 91. Oznacza to, że jeżeli chce się umieścić jakiś element jako ostatni w porządku alfabetycznym, należy umieścić go w nawiasach kwadratowych.
Używając operatora Like do sprawdzenia zgodności łańcucha znaków ze wzorem, można stosować symbole wieloznaczne, takie jak:
? zastępuje dowolny znak
* zastępuje zero lub więcej znaków # zastępuje dowolną cyfrę (0 - 9)
/charlist/ zastępuje pojedynczy znak w charlist
/charlist/ zastępuje pojedynczy znak nie znajdujący się w charlist
Więcej szczegółów można znaleźć w dokumentacji VBA.
Funkcja StrComp również porównuje dwa łańcuchy znaków. Oto jej składnia:
StrComp(ŁańcuchZnakówl, ŁańcuchZnaków2 [, compare])
Funkcja ta zwraca wartość wskazującą, czy ŁańcuchZnaków1 jest równy, większy lub mniejszy niż ŁańcuchZnaków2. Dokumentacja VBA zawiera więcej szczegółów na temat tego zagadnienia.
Różne funkcje i instrukcje
Funkcja Immediate If
Funkcja Immediate If ma następującą składnię;
IIf(Wyrażenie, CzęśćPrawdziwa, CzęśćFałszywa)
Funkcja ta zwraca jedną z dwóch części: jeżeli Wyrażenie ma wartość True, funkcja zwraca część CzęśćPrawdziwa; jeżeli Wyrażenie ma wartość False, funkcja zwraca część CzęśćFałszywa. Na przykład następujący kod wyświetla okno komunikatu informujące, czy pierwszy akapit w aktywnym dokumencie jest zbyt długi, tj. czy zawiera ponad 100 słów:
Dim cSłowa As Long
cSłowa = ActiveDocument.Paragraphs(1).Range.Words.Count MsgBox "Pierwszy akapit jest " & _
IIf(cSłowa > 100, "za długi", "w sam raz")
Należy pamiętać, że funkcja Ilf zawsze ocenia obie części, ale zwraca tylko jedną z nich. Musi się, zatem być przygotowani na niepożądane efekty uboczne. Na przykład, poniższy kod wywoła błąd dzielenia przez zero, ponieważ wyrażenie 1/x jest oceniane we wszystkich przypadkach, nawet gdy x = 0
x = 0
y = IIf (x = 0, x ^ 2, 1 / x)
Funkcja Switch
Oto składnia funkcji Switch:
Switch(wyrażl, wartośćl, wyraż2, wartość2,..., wyrażN, wartośćN)
gdzie wyrażX i wartośćX to wyrażenia. Wystarczy jedna para wyrażenie-wartość, ale stosowanie tej funkcji ma większy sens, jeżeli są przynajmniej dwie takie pary.
Funkcja Switch ocenia każde wyrażenie wyrażX. Kiedy napotyka pierwsze wyrażenie przyjmujące wartość True, zwraca odpowiadającą jej wartość. Podobnie jak funkcja Ilf, funkcja Switch zawsze ocenia wszystkie wyrażenia. Jeżeli żadne wyrażenie nie jest prawdziwe, funkcja zwraca Null. Aby sprawdzić, czy funkcja Switch zwraca Null, można skorzystać z funkcji IsNull.
Na przykład, procedura przedstawiona w wydruku 7.1 wyświetla typ dokumentu Worda (dokument czy szablon) w zależności od jego rozszerzenia.
Wydruk 7.1. Funkcja Switch.
Sub WyświetlTypDokumentu(RozszerzenieDokumentu As String) Dim TypDokumentu As Variam
TypDokumentu = Switch(RozszerzenieDokumentu = "dot", "Szablon", _
RozszerzenieDokumentu = "doc", "Dokument")
'Wyświetl rezultat
If Not IsNull(TypDokumentu) Then
MsgBox TypDokumentu
Else
MsgBox "Typ nieznany" End If
End Sub
Warto zwrócić uwagę na jedną rzecz w powyższym kodzie. Ponieważ funkcja Switch może zwrócić wartość Null, nie można przypisać zwracanej wartości do zmiennej typu String w następujący sposób:
Dim TypDokumentu As String
TypDokumentu = Switch(RozszerzenieDokumentu = "dot", "Szablon", _
RozszerzenieDokumentu = "doc", "Dokument")
Jeżeli RozszerzenieDokumentu przyjmie wartość inną niż dot lub doc, pojawi się komunikat o błędzie „Invalid use of Null” (niepoprawne użycie Null). Rozwiązaniem tego problemu jest zadeklarowanie zmiennej TypDokumentu jako typ Variant. Typ Variant może przechowywać każdy rodzaj danych, w tym również brak danych, co wskazuje słowo kluczowe Null. Można uniknąć całego tego problemu stosując instrukcję Select Case, która zostanie omówiona w następnym rozdziale.
Konwersja jednostek
Funkcja InchesToPoints konwertuje miarę podaną w calach na miarę podaną w punktach (punkt to jednostka drukarki; każdy cal to 72 punkty). Funkcja ta jest ważna, ponieważ wiele wartości Worda jest podawanych w punktach.
Na przykład właściwość LeftIndent służy do ustawiania wartości lewego wcięcia akapitu i wymaga wartości w punktach. Zatem aby ustawić lewe wcięcie pierwszego akapitu w aktywnym dokumencie Worda na 0,25 cala, należałoby napisać:
ActiveDocument.Paragraphs(1).LeftIndent = InchesToPoints(0.25)
Funkcja PointsTolnches natomiast służy do wyświetlania w calach wartości zwracanej przez funkcję w punktach.
Oprócz wyżej wymienionych, Word posiada następujące funkcje konwersji jednostek:
• CentimetersToPoints i PointsToCentimeters
• MillimetersToPoints i PointsToMillimeters
• LinesToPoints i PointsToLines (1 linia = 12 punktów = 1/6 cala)
• PicasToPoints i PointsToPicas (1 pica = 12 points = 1/6 cala)
Instrukcja Beep
Instrukcja Beep o prostej składni
Beep
generuje dźwięk za pomocą głośników komputera. Można użyć tej instrukcji, aby zwrócić uwagę użytkownika na coś ważnego. Nie należy jednak przesadzać ze stosowaniem instrukcji Beep. Jej efekt w głównej mierze zależy od sprzętu użytkownika i może się tak zdarzyć, że Beep nie wywoła żadnego dźwięku. Lepszym rozwiązaniem, nie kolidującym z wykonywaniem programu, jest wyświetlanie informacji w pasku stanu Worda.
Instrukcje kontrolujące przepływ programu
Omawianie VBA zostanie zakończone prezentacją instrukcji kontrolujących przepływ programu.
Instrukcja If ... Then
Instrukcja If...Then warunkowo wykonuje blok kodu. Oto jej składnia:
If Warunek Then
'blok instrukcji
ElseIf InnyWarunek Then
'blok instrukcji
Else
'blok instrukcji
End If
Należy zwrócić uwagę, że można użyć więcej części ElseIf i że zarówno części ElseIf, jak i Else są opcjonalne. Można również zmieścić wszystkie części tej instrukcji w jednym wierszu, ale z praktycznego punktu widzenia jest to możliwe tylko w przypadku braku części ElseIf i Else.
Za przykład niech posłuży poniższy kod, który usuwa bieżące zaznaczenie w aktywnym dokumencie jeżeli zawiera ono wyraz „Bartok"
Dim sTekst As String
sTekst = Selection.Text
If InStr(sTekst, "Bartok") Then Selection.Delete
Poniższy kod zmienia rozmiar czcionki zaznaczonego tekstu w zależności od jego stylu. Jeżeli styl jest różny od Nagłówek 1, Nagłówek 2 lub Nagłówek 3, rozmiar czcionki zostaje zmieniony na 11 punktów:
If Selection.Style = "Nagłówek 1" Then
Selection.Font.Size = 24
E1seIf Selection.Style = "Nagłówek 2" Then Selection.Font.Size = 18
E1seIf Selection.Style = "Nagłówek 3" Then Selection.Font.Size = 19
Else
Selection.Font.Size = 11
End If
Pętla For
Instrukcja For...Next umożliwia wielokrotne wykonanie bloku kodu (tj. jednego lub więcej wierszy kodu). Pętla ta jest nazywana po prostu pętlą For. Oto jej podstawowa składnia:
For licznik = start To koniec
'blok kodu
Next licznik
Kiedy blok kodu jest wykonywany po raz pierwszy, zmienna licznik (nazywana zmienną pętli) otrzymuje wartość start. Każde wykonanie pętli powoduje zwiększenie wartości zmiennej licznik o 1. Kiedy wartość zmiennej licznik jest większa od wartości koniec, wykonywanie pętli zostaje przerwane. Zatem pętla jest wykonywana koniec - start +l razy, za każdym razem z inną wartością zmiennej licznik.
Można opuścić słowo licznik w ostatnim wierszu pętli For (zastępując Next licznik wierszem Next). Dzięki temu wykonanie pętli może być szybsze, ale kod staje się mniej czytelny.
Poniższy kod przechodzi przez kolekcję wszystkich akapitów w aktywnym dokumencie Worda. Jeżeli akapit posiada styl Nagłówek 1, styl zostaje zmieniony na Nagłówek 2:
Dim i As Integer
Dim akapit As Paragraph
For i = 1 To ActiveDocument.Paragraphs.Count
'Weź następny akapit
Set akapit = ActiveDocument.Paragraphs(i)
'Zmień styl z Nagłówek 1 na Nagłówek 2
If akapit.Style = "Nagłówek 1" Then
akapit.Style = "Nagłówek 2" End If
Next i
Pętle For często są używane do inicjalizowania tablic. Poniższy kod:
For i = 0 To 10
iTablica(i) = 0
Next i
przypisuje wartość 0 każdemu z 11 elementów tablicy iTablica.
ExitFor
Instrukcja Exit For umożliwia wyjście z pętli, kiedy zostanie spełniony jakiś warunek. Na przykład, poniższy kod wyszukuje w aktywnym dokumencie pierwszy akapit, którego pierwszym wyrazem jest wyraz „Dziękuję". Po znalezieniu tego wyrazu, VBA opuszcza pętlę For, a akapit zostaje pogrubiony:
Dim i As Integer
Dim akapit As Paragraph
For i = 1 To ActiveDocument.Paragraphs.Count
'Weź następny akapit
Set akapit = ActiveDocument.Paragraphs(i)
'Jeżeli pierwszy wyraz to "Dziękuję",
'wyjdź z pętli For
If Trim(akapit.Range.Words(1)) _ "Dziękuję" Then Exit For
Next i
akapit.Range.Bold = True
Należy zwrócić uwagę na użycie funkcji Trim, ponieważ dla Worda wyraz zawiera również spacje, które występują po nim.
Pętla For Each
Pętla For Each, odmiana pętli For, służy do przechodzenia przez obiekty kolekcji (jak również elementy tablicy) i jest zwykle wydajniejsza niż tradycyjna pętla For. Jej podstawowa składnia to:
For Each ZmiennaObiektowa In NazwaKolekcji
'blok kodu
Next Zmienna0biektowa
W powyższym przykładzie ZmiennaObiektowa to zmienna tego samego typu, co obiekty kolekcji. Blok kodu zostanie wykonany dla każdego obiektu w kolekcji.
Oto jak wygląda kod zmieniający styl Nagłówek I na Nagłówek 2 z zastosowaniem z pętli For Each:
Dim akapit As Paragraph
For Each akapit In ActiveDocument.Paragraphs
'Zmień styl z Nagłówek 1 na Nagłówek 2
If akapit.Style = "Nagłówek 1" Then
akapit.Style = "Nagłówek 2"
End If
Next akapit
Jak można zauważyć, kod jest znacznie bardziej zwięzły.
Zatem w przypadku przechodzenia przez kolekcję obiektów są dwa rozwiązania:
For Each obiekt In Kolekcja
'blok kodu
Next obiekt
lub
For i = 1 To Kolekcja.Count
'blok kodu
Next i
Należy jednak podkreślić, że pętla For Each może być znacznie szybsza niż pętla For w przechodzeniu przez obiekty kolekcji Worda. Jest to więc preferowany sposób, z wyjątkiem małych kolekcji.
Instrukcji For Each można również używać do przejścia przez kolekcje elementów, które nie są obiektami. Na przykład, kolekcja FontNames zawiera nazwy wszystkich dostępnych czcionek. Jest to więc kolekcja łańcuchów znaków. Aby przejść przez tę kolekcję, należy napisać:
Dim NazwaCzcionki As Variam
For Each NazwaCzcionki In Application.FontNames
'blok kodu
Next NazwaCzcionki
Trzeba zwrócić uwagę, że zmienna NazwaCzcionki musi być zadeklarowana jako Variam, ponieważ zmienną pętli For Each może być tylko zmienna obiektowa lub zamienna typu Variam. Zmienna typu String byłaby najwydajniejsza, ale VBA nie pozwala na jej użycie w tym kontekście.
Pętla Do
Pętla Do posiada kilka odmian. Aby je opisać, używaj notacji:
{While I Until}
która reprezentuje albo słowo kluczowe While, albo słowo kluczowe Until, ale nie oba jednocześnie. Oto przykładowa składnia pętli Do:
Do {While I Until} warunek
'blok kodu
Loop
lub
Do
'blok kodu
Loop {While I Until} warunek
Można się też pozbyć części warunek:
Do
'blok kodu
Loop
Różnice między niektórymi odmianami pętli Do mogą być bardzo subtelne. Na przykład poniższy kod przechodzi przez akapity aktywnego dokumentu, dopóki akapity zawierają jakieś znaki (poza znakiem końca akapitu):
'Weź pierwszy akapit
Set akapit = ActiveDocument.Paragraphs(1)
Do While akapit.Range.Characters.Count
'Blok kodu
'Weź następny akapit
Loop
Rozważając następujący kod, którego cel jest podobny:
'Weź pierwszy akapit
Set akapit = ActiveDocument.Paragraphs(1)
Do
'Blok kodu
'Weź następny akapit
Loop While akapit.Range.Characters.Count > 1
Różnica między tymi dwoma odmianami polega na tym, że w pierwszym przypadku warunek jest sprawdzany zanim jakikolwiek kod pętli Do zostanie wykonany. Jeżeli pierwszy akapit nie zawiera żadnego tekstu (tj. zawiera tylko znak końca akapitu), liczba znaków w tym akapicie będzie wynosić 1 i warunek nie zostanie spełniony. A zatem żaden kod pętli Do nie zostanie wykonany.
W drugim przypadku warunek jest sprawdzany po każdym przejściu pętli, więc pętla zostanie wykonana co najmniej raz, nawet jeżeli akapit nie zawiera żadnego tekstu.
W poniższym przykładzie pętla Do została użyta, aby sformatować kursywą każdy wyraz akapitu aż do momentu dojścia do wyrazu pogrubionego (zadanie to można wykonać również za pomocą pętli For):
Dim akapit As Paragraph Dim fragment As Range
Dim iWyraz As Long
Dim iLicznikWyrazów As Long
'Inicjalizuj
iWyraz = 1
'Weź pierwszy akapit
Set akapit = ActiveDocument.Paragraphs(1)
'Oblicz liczbę wyrazów w akapicie
iLicznikWyrazów = akapit.Range.Words.Count
'Wykonuj pętlę, dopóki są wyrazy
Do While iWyraz <= iLicznikWyrazów
'Weź wyraz
Set fragment = akapit.Range.Words(iWyraz)
'Wyjdź z pętli, jeżeli wyraz jest pogrubiony
If fragment.Bold = True Then Exit Do
'Sformatuj wyraz kursywą
fragment.Italic = True
'Następny wyraz
iWyraz = iWyraz + 1
Loop
Należy zwrócić uwagę na instrukcję Exit Do, która jest analogiczna do instrukcji Exit For.
Pętle nieskończone
Powinno się zachować ostrożność kodując pętle Do, ponieważ źle napisana pętla Do może wykonywać się bez końca. Pętlę nieskończoną może spowodować użycie niewłaściwego warunku, który ma pętlę zakończyć.
Pętla nieskończona może powstać również w pętli For, ale zdarza się to znacznie rzadziej, ponieważ wymagałoby to zmiany licznika pętli. Natomiast stosunkowo łatwo popełnić błąd w pętli Do i wywołać w ten sposób pętlę nieskończoną.
Oto prosty przykład. Załóżmy, że każdy akapit w aktywnym dokumencie powinien mieć nagłówek wskazujący numer tego akapitu. Oznacza to, że poniższy dokument zawierający cztery wiersze:
Pierwszy wiersz dokumentu.
Drugi wiersz dokumentu.
Trzeci wiersz dokumentu.
Czwarty wiersz dokumentu.
powinien zostać przekształcony do postaci następującej:
Akapit 1:
Pierwszy wiersz dokumentu.
Akapit 2:
Drugi wiersz dokumentu.
Akapit 3:
Trzeci wiersz dokumentu.
Akapit 4:
Czwarty wiersz dokumentu.
Rozważmy poniższy kod, który ma wykonać to zadanie. Spróbujmy znaleźć błąd, który sprawia, że kod nigdy nie przerwie swojego działania.
iAkapit = 1
'Wykonuj pętlę, dopóki są akapity
Do While iAkapit <= ActiveDocument.Paragraphs.Count
'Weź n-ty akapit
Set akapit = ActiveDocument.Paragraphs(iAkapit)
'Dodaj nagłówek z numerem akapitu akapit.Range.InsertBefore "Akapit" _
& Format(iAkapit) & ":" & vbCrLf
'Następny akapit
iAkapit = iAkapit + 1
Loop
Problem polega na tym, że dodanie nagłówka powoduje dodanie nowego akapitu do dokumentu, co zwiększa wartość ActiveDocument.Paragraphs.Count, więc warunek:
iAkapit <= ActiveDocument.Paragraphs.Count
jest zawsze prawdziwy, ponieważ wartość lewej strony wzrasta wraz z prawą stroną.
Powyższy przykład ilustruje, jak niebezpieczne jest umieszczanie wartości podlegającej zmianie w części warunek pętli Do (i jakiejkolwiek innej pętli). Patrząc jeszcze raz na poprzedni przykład, który formatuje kursywą każdy wyraz do momentu dojścia do wyrazu pogrubionego. Można zauważyć następujący kod:
'Oblicz liczbę wyrazów w akapicie
iLicznikWyrazów = akapit.Range.Words.Count
'Wykonuj pętlę, dopóki są wyrazy
Do While iWyraz <= iLicznikWyrazów
Pierwszy wiersz oblicza liczbę wyrazów i umieszcza ją w zmiennej. Zmienna ta, której wartość kontroluje programista a nie VBA, nie zmienia się (ponieważ on jej nie zmienia), dzięki czemu może być bezpiecznie użyta w części warunek pętli Do.
Instrukcja Select Case
Instrukcja If...Then służy do wykonywania różnych zadań w zależności od różnych warunków. Alternatywną instrukcją, często znacznie czytelniejszą, jest Select Case o następującej składni:
Select Case wyrażenie
Case wartośćl
'blok instrukcji wykonywany, jeżeli wyrażenie = wartośćl
Case wartość2
'blok instrukcji wykonywany, jeżeli wyrażenie = wartość2
...
Case Else
'blok instrukcji wykonywany w innym przypadku
End Select
Należy zwrócić uwagę, że część Case Else jest opcjonalna. Jako ilustrację można rozważyć poniższy kod, który jest wersją wcześniejszego przykładu zmieniającego rozmiar czcionki różnych nagłówków, tym razem z zastosowaniem instrukcji Select Case. Jak widać, w tej wersji kod jest czytelniejszy niż w wersji poprzedniej:
Select Case Selection.Style
Case "Nagłówek 1"
Selection.Font.Size = 24
Case " Nagłówek 2"
Selection.Font.Size = 18
Case " Nagłówek 3"
Selection.Font.Size = 14
Case Else
Selection.Font.Size = 11
End Select
Ostatnie uwagi o VBA
Długo jeszcze można by omawiać VBA - podręcznik do VBA zawiera około 300 stron. Jednak odstawowe zagadnienia potrzebne do rozpoczęcia programowania w Wordzie zostały już wyjaśnione.
Na dobrą sprawę, wykonanie wielu programistycznych zadań w Wordzie wymaga poznania jedynie wybranych funkcji VBA. Prawdopodobnie więcej problemów sprawia model obiektowy Worda niż język VBA.
Funkcje związane z plikami i folderami
VBA posiada wiele funkcji umożliwiających operacje na plikach i folderach. Niektóre z nich to:
Dir - wyszukuje plik o podanej nazwie.
FileLen - odczytuje rozmiar pliku.
FileTimeDate - odczytuje datę pliku.
FileCopy - kopiuje plik.
Kill - usuwa plik.
Name - zmienia nazwę pliku lub folderu.
RmDir - usuwa folder.
MkDir - tworzy nowy folder.
VBA posiada również funkcje i instrukcje służące do tworzenia plików tekstowych, w których można zapisywać dane. Oto uproszczona składnia instrukcji Open:
Open ScieżkaPliku For Tryb As [#]NumerPliku
Kiedy plik jest otwarty, można z niego odczytać dane jak również je w nim zapisać. Warto podkreślić, że instrukcja Open otwiera i tworzy pliki tekstowe, a nie dokumenty Worda.
Funkcje związane z datą i czasem
Oto niektóre funkcje VBA, dzięki którym można manipulować datami i czasem:
Date, Now, Time - odczytują bieżącą datę i czas.
DateAdd, DateDiff, DatePar t- obliczają daty.
DateSerial, DateValue - zwracają datę.
TimeSerial, TimeValue-zwracajączas.
Date, Time - zwracają datę lub czas.
Timer - mierzy trwanie procesu.
Funkcja Format
Funkcja Format służy do formatowania łańcuchów znaków, liczb i dat. Tabela 8.1 zawiera kilka przykładów zastosowania tej funkcji.
Tabela 8.1. Przykłady zastosowania funkcji Format.
Wyrażenie |
Zwracana wartość
|
Format(Date, "Long Date")
|
czwartek, kwiecień 29, 2000 |
Format(Time, "Long Time")
|
15:24:45
|
Format(Date, "mm/dd/yy hh:mm:ss")
|
04/29/00 15:25:56 |
Format(1234,5 "$##,##0.00")
|
$1 234,50 |
Format("WITAJCIE", "<")
|
witajcie |
Błędy
Programista piszący programy profesjonalne powinien koniecznie zapoznać się z technikami stosowanymi w obsłudze błędów. Można zaproponować książkę Concepts of Object-Oriented Programming in Visual Basic wydawnictwa Springer-Verlag, która zawiera rozdział poświęcony temu zagadnieniu. Jeżeli jednak pisze się programy na własny użytek, kod obsługujący błędy nie ma tak wielkiego znaczenia. Kiedy wystąpi błąd, VBA zatrzyma wykonywanie programu, wyświetli komunikat o błędzie i wyróżni wiersz, który wywołał błąd. Wtedy można przystąpić do usuwania błędu. Nie można jednak oczekiwać, że użytkownicy programów napisanych przez programistę będą usuwać błędy z jego kodu.
BHP
WSTĘP
Rewolucja informatyczna sprawiła, że miliony ludzi z hal fabrycznych przenoszą się przed monitory komputerowe. Nie grozi im już śmierć w trybach maszyny, ale pojawiają się inne zagrożenia dla zdrowia. Tym większe, że mało kto zdaje sobie z nich sprawę.
Najbardziej znany jest problem uciążliwości wpływu monitora na oczy (patrz: CHIP 4/99, s. 40). Problemy ze wzrokiem to najpowszechniejsza dolegliwość, dokuczająca jednak nie tylko miłośnikom pecetów. "Wśród osób pracujących przy komputerach dominują schorzenia oczu, głównie przewlekłe zapalenia spojówek. Jednak na tę dolegliwość cierpi większość naszego społeczeństwa - czy pracuje przy komputerze, czy nie" - wyjaśnia dr Anna Wróblewska, specjalista medycyny pracy. W ostatnich latach sytuacja użytkowników komputerów pod tym względem uległa olbrzymiej poprawie.
Praktycznie wszystkie współczesne monitory spełniają surowe międzynarodowe standardy, określające dopuszczalne promieniowanie elektromagnetyczne i gamma oraz minimalną częstotliwość poziomego odświeżania obrazu. Użytkownik Windows musi jedynie sprawdzić, czy system poprawnie rozpoznał model monitora i optymalnie ustawił istotne parametry pracy. Warto tu przypomnieć, że zgodnie z najnowszą szwedzką normą TCO 99 zalecane, uznane za nie psujące wzroku odświeżanie obrazu wynosi 85 herców (patrz: CHIP 3/99, s. 73). Zdaniem prof. Marii Konarskiej, szefowej Zakładu Ergonomii
Centralnego Instytutu Ochrony Pracy, wysokie standardy bezpieczeństwa, spełniane przez niemal wszystkie obecne na rynku modele monitorów, sprawiają, że stosowanie dodatkowych filtrów staje się niepotrzebne. Filtry mogą być wręcz szkodliwe! "Monitory powinny spełniać normy bezpieczeństwa, które czynią filtry zbędnymi. Na nałożonym filtrze osadza się kurz, co pogarsza ostrość oraz efektywną rozdzielczość obrazu i przyczynia się do szybszego zmęczenia wzroku" - tłumaczy dr Wróblewska.-";Najlepsze są filtry wbudowywane w ekran, bo są one hermetycznie zamknięte, co niweluje możliwość rozpraszania obrazu. Klasyczny filtr może jedynie poprawiać samopoczucie użytkownika, który ma wówczas wrażenie, że jest lepiej zabezpieczony". Wiele osób korzystających z dodatkowych filtrów pamięta o wycieraniu kurzu tylko z ich zewnętrznej części, zapominając o stronie wewnętrznej i szybie monitora.
Bez ekwilibrystyki przy pracy! Poprawne ustawienie dłoni i przedramion podczas pracy przy komputerze może uchronić przed przewlekłymi schorzeniami. W zachowaniu właściwej pozycji mogą pomóc klawiatury ergonomiczne.
Jak wynika z badań CIOP, nie ma sensu stosowanie modnych ostatnio okularów antyrefleksyjnych i antyradiacyjnych. Odblaskom należy zapobiegać właściwym ustawieniem stanowiska pracy. Promieniowanie nowych monitorów jest znikome, a w przypadku starszych urządzeń niezbędne są filtry. Wbrew obiegowym opiniom zakład pracy nie ma obowiązku refundacji takich okularów - rozporządzenie Ministra Pracy nakłada natomiast na pracodawcę obowiązek zwrotu części kosztów okularów korekcyjnych.
PIERWSZA OFIARA RSI
Choć zagrożenie dla wzroku jest mniejsze niż kilka lat temu, nie znaczy to jednak, że komputer stał się narzędziem bezpiecznym. Dopiero teraz zaczynają się ujawniać długotrwałe negatywne skutki wieloletniej pracy przy klawiaturze. Ofiarą takiej bomby z opóźnionym zapłonem padł jeden ze współpracowników CHIP-a. Po kilku latach pracy przy komputerze zauważył, że rano drętwieją mu palce wskazujące. W ciągu następnych miesięcy cierpnięcie objęło całe dłonie, a wreszcie sięgnęło barków. Towarzyszyła temu pogarszająca się sprawność kończyn górnych: coraz mniejszy zakres ruchów palców i słabnąca siła chwytu. W końcu prowadzenie samochodu stało się niemożliwe, a do rangi problemu urosło nawet spożycie posiłku.
Dzięki przeprowadzonym w Internecie poszukiwaniom nasz współpracownik zaraz po wystąpieniu pierwszych objawów ustalił nazwę schorzenia. Nazywa się ono fachowo "zespół cieśni nadgarstka", znane też pod nazwą RSI (Repetitive Strain Injury) oraz Cumulative Trauma Disorder. Pojawia się, gdy dłonie przez wiele godzin są odgięte do góry - np. podczas szybkiego wprowadzania danych za pomocą klawiatur wymagających minimalnej siły nacisku, a więc pozwalających nie poruszać przedramionami. Także korzystanie z myszki bez oparcia nadgarstka na specjalnej podkładce może prowadzić do opisanych kłopotów zdrowotnych. Pojawia się wówczas postępujące podrażnienie głównego nerwu dłoni.
Jednak właściwe leczenie naszego współpracownika nie rozpoczęło się szybko. Kolejni lekarze-specjaliści nie wierzyli, że ich pacjenta dotknęło mało znane schorzenie. Następujące po sobie, wielotygodniowe sesje lasero- i krioterapii nie przynosiły poprawy. Gdy po dwóch latach, w 1997, roku przeprowadzono badania z użyciem elektromiografu, które wykazały, że po raz pierwszy w Polsce wystąpił wywołany pracą przy komputerze przypadek RSI, na wszelkie formy terapii było za późno. Jedynym ratunkiem był nóż chirurga.
Przypadek ten pokazuje, że ofiary schorzeń pojawiających się wraz z postępującymi zmianami cywilizacyjnymi i technologicznymi, nawet znając źródło problemów i zwracając się do specjalistów, mogą mieć trudności z uzyskaniem pomocy medycznej. Strach pomyśleć, co stałoby się, gdyby był on nieświadomym źródła swych kłopotów mieszkańcem prowincji, skazanym na pomoc gminnego ośrodka zdrowia.
UWAGA NA RĘCE
"Zespół cieśni nadgarstka był dotychczas w naszym kraju chorobą zawodową malarzy, pianistów i maszynistek" - tłumaczy prof. Konarska. Schorzenie to ujawnia się po ok. 10-12 latach codziennej wielogodzinnej pracy w warunkach niezgodnych z zasadami ergonomii. Ponieważ masowa komputeryzacja rozpoczęła się w naszym kraju po 1989 roku, można się spodziewać, że w najbliższych latach pojawiać się będzie coraz więcej ofiar RSI oraz innych schorzeń, których źródło leży w niezgodnej z zaleceniami specjalistów pracy z klawiaturą i myszą.
W początkowych stadiach schorzenia można mu zaradzić serią zabiegów fizjoterapii. Jeśli kolejne objawy zostaną zlekceważone lub - jak w opisanym przypadku - źle zdiagnozowane, niezbędne staje się chirurgiczne nacięcie tzw. wiązadła przedniego nadgarstka. Konsekwencją operacji jest kilkutygodniowe unieruchomienie ręki w gipsie oraz wielomiesięczna rekonwalescencja. Tymczasem aby uniknąć problemów, wystarczy dobrze przygotować stanowisko pracy oraz robić przerwy na prostą gimnastykę palców i nadgarstka. "Skuteczną profilaktyką jest przeciągnięcie się, strzepnięcie dłoni i krótki spacer, podczas którego odpoczywają napięte w czasie pracy mięśnie przedramion i dłoni" - mówi szefowa Zakładu Ergonomii CIOP. Co kilka minut warto zrobić krótką przerwę na rozluźnienie dłoni, ramion i barków, a co godzinę - dłuższą na bardziej kompleksową gimnastykę. Zalecane jest także uprawianie sportów ogólnorozwojowych, np. pływania. Może to stanowić skuteczną profilaktykę zapobiegającą nie tylko RSI, ale także innym "komputerowym" dolegliwościom. Niewskazany jest natomiast tenis ziemny czy stołowy.
Zespół cieśni nadgarstka to tylko jedno z wielu groźnych schorzeń rąk, które stanowią zagrożenie dla osób pracujących przy klawiaturze. Dzięki właściwej pozycji przy pracy i odpowiednio częstym przerwom na gimnastykę można jednak tych wszystkich chorób uniknąć.
NIE GARB SIĘ
Innym, rzadko wiązanym z pracą przy klawiaturze, schorzeniem są zmiany zwyrodnieniowe szyjnego odcinka kręgosłupa. "Większość osób zgłasza się z dolegliwościami oczu, ale to schorzenia kręgosłupa są głównym przeciwwskazaniem dla pracy przy komputerze, gdyż wykluczają wielogodzinne przebywanie w pozycji siedzącej" - wyjaśnia dr Wróblewska. Przestrzegając przepisów BHP, można uniknąć takich problemów. Wystarczy w czasie pracy co godzinę zrobić 10 minut przerwy lub co 2 godziny - 20 minut. Praca przy klawiaturze nie musi być jednak bezpośrednią przyczyną kłopotów z kręgosłupem. Mogą one mieć podłoże genetyczne lub zostać zapoczątkowane na wiele lat przed tym, nim człowiek pierwszy raz siądzie przed monitorem. Czynników wywołujących chorobę może być wiele - a komputer jedynie pogarsza stan zdrowia.
OŚWIETLENIE STANOWISKA PRACY
Codzienna, wielogodzinna praca przy komputerze może się przyczyniać do osłabienia, a nawet uszkodzenia wzroku. Zmuszanie mięśni oka do ciągłego wysiłku powoduje ich zmęczenie, a łzawienie, zaczerwienienie i pieczenie należy traktować jako sygnał ostrzegawczy. Winę za problemy ze wzrokiem w dużej mierze ponosi nieprawidłowe oświetlenie miejsca pracy.
Ekstremalnie nieprawidłowo ustawiony monitor: odbicia źródła światła (lampy i okna) powodują powstanie szkodliwego lśnienia. Wyraźnie widoczne odbicie użytkownika wymusza na oku ciągłą zmianę ostrości widzenia. Stojąca obok lampka wprawdzie oświetla biurko, ale także powoduje konieczność zwiększenia kontrastu, co negatywnie wpływa na komfort pracy. |
|
Przy tworzeniu nowego stanowiska pracy z komputerem powszechną praktyką jest ustawianie urządzenia na biurku w miejscu, w którym jest akurat wolny kawałek powierzchni. Jeśli nawet wcześniej oświetlenie było prawidłowe, w żaden sposób nie uwzględniamy zmienionej specyfiki pracy. Z czasem nowa organizacja miejsca powszednieje i użytkownik przestaje zauważać wady takiego ustawienia. Jednak wszelkie nieprawidłowości stopniowo pogarszają stan narządu wzroku.
Sytuacja nie jest jednak beznadziejna. Najczęściej wystarczy dokonać niewielkich zmian na naszym stanowisku pracy, by osiągnąć dużą poprawę komfortu widzenia. Przeważnie nie wymaga to żadnych nakładów finansowych, a efekty będą natychmiastowe i długotrwałe. Najwygodniej jest poprosić o ocenę aktualnego stanowiska pracy firmę specjalizującą się w określaniu prawidłowości oświetlenia, ale zaskakująco dużą poprawę można uzyskać samodzielnie.
ERGONOMIA-LOKALIZACJA I OŚWIETLENIE STANOWISKA PRACY
By spełnić wymagania dotyczące prawidłowego oświetlenia stanowiska pracy, niezbędne jest dobre rozplanowanie jego usytuowania w pomieszczeniu. Na wybór pokoju nie mamy zwykle wpływu, jeśli jednak moglibyśmy wybierać, należy na gabinet zarezerwować pomieszczenie nie wyższe niż 3 metry, najlepiej z oknami od strony północnej. Okna te nie powinny być zbyt duże; dobrze, jeśli są tylko w jednej płaszczyźnie. Nie ma oczywiście mowy o przeszklonych ścianach.
Stanowisko komputerowe ustawiamy tak, by ekran znajdował się na tle ściany bezokiennej, bokiem do okna, ale w odległości nie mniejszej niż 1 metr. Przy samym oknie możemy ulokować stanowisko pracy nie wyposażone w komputer. W żadnym wypadku okno - zwłaszcza od strony innej niż północna - nie powinno znajdować się za plecami użytkownika. Monitor należy tak ustawić, by żaden fragment okna nie odbijał się od ekranu pod kątem większym niż 45° od osi wzroku. Jeśli nie da się tego osiągnąć, warto zadbać o odpowiedniej wielkości przegrodę zasłaniającą okno. Przegroda taka nie musi być wysoka, powinna tylko zasłaniać dostęp bezpośredniego światła z okna do ekranu.
DZIAŁANIE PRĄDU NA ORGANIZM LUDZKI
Prąd elektryczny przepływający przez ciało człowieka wywołuje w nim zmiany chemiczne i biologiczne groźne dla zdrowia i życia. Działanie prądu może się objawiać w postaci zmian elektrolitycznych , oparzeń oraz zaburzeń czynności fizjologicznych. Niebezpieczeństwo porażenia prądem elektrycznym zależy od jego wartości , czasu rażenie (przepływu prądu przez organizm) oraz częstotliwości. Najniebezpieczniejsze są prądy o częstotliwości sieciowej 50-60Hz, gdyż jest ona zbliżona do częstotliwości bioprądów w organizmie. Niebezpieczeństwo porażenia prądem elektrycznym jest mniejsze dla prądu stałego oraz zmniejsza się wraz ze zwiększeniem częstotliwości ponad 50-60 Hz.
Prąd przepływający przez ciało człowieka jest proporcjonalny do napięcia dotykowego
( napięcie między dwoma elementami przewodzącymi, które znajdują się w zasięgu ręki) i odwrotnie proporcjonalny do rezystancji ciała. Rezystancja ciała człowieka zmienia się w szerokim zakresie i jest zależna od: warunków środowiskowych; stanu naskórka; indywidualnych cech człowieka.
Przy prądzie przemiennym płynącym przez ciało człowieka powinno się uwzględniać nie tylko rezystancję, lecz również reaktancję, ale dla uproszczenia przy obliczeniach jej wartości jest pomijana. Wypadkowa rezystancja ciała człowieka składa się z rezystancji skóry i rezystancji wewnętrznej organizmu. Rezystancja wewnętrzna jest niewielka i wynosi od 500 do 1000 SZ. Rezystancja skóry natomiast zmienia się w szerokich granicach. Przy suchym naskórku wynosi od 5000 S2 do 100 000 S~2 i może zmniejszać się pod wpływem wilgotności, przedłużającego się czasu rażenia i wzrostu napięcia rażeniowego.
Na tej podstawie przyjęto, że minimalna niebezpieczna dla człowieka wartość prądu płynącego przez ciało wynosi : 30mA prądu przemiennego i 10mA prądu stałego. Korzystając z prawa Ohma i podstawiając do wzoru niebezpieczne wartości prądu płynącego przez ciało człowieka oraz rezystancję ciała w danych warunkach środowiskowych (przyjmując najniższą wartość) otrzymuje się maksymalne wartości napięć dopuszczalnych dla człowieka - napięci dotykowe bezpieczne. W warunkach środowiskowych, w których rezystancja ciała człowieka w stosunku do ziemi wynosi co najmniej 1000 SZ (pomieszczenie o wilgotności względnej nie przekraczającej 75% i podłożu nieprzewodzącym), za napięcie bezpieczne uznaje się napięci 50 V dla prądu przemiennego i 100V dla prądu stałego. Gdy rezystancja ciała jest mniejsza niż 1000 S~, napięcie bezpieczne wynosi 25 V dla prądu przemiennego i 50 V dla prądu stałego.
ŚRODKI OCHRONY PRZECIWPORAŻENIOWEJ
Ochrona przeciwporażeniowa w instalacjach i urządzeniach elektrycznych ma na celu niedopuszczenie do przepływu przez ciało człowieka prądu rażeniowego lub ograniczenie czasu przepływu prądu przez szybkie wyłączenie zasilania, aby zapobiec powstaniu groźnych dla zdrowia i życia skutków.
Ochronę przeciwporażeniową można podzielić na trzy grupy:
1. Ochronę przez stosowanie napięć bezpiecznych,
2. Ochranę przed dotykiem bezpośrednim do części czynnych obwodu elektrycznego
(ochrona podstawowa),
3. Ochronę przed dotykiem pośrednim do części przewodzących dostępnych, na których w wyniku uszkodzenia izolacji pojawiło się napięcie dotykowe o wartości mogącej spowodować w danych warunkach środowiskowych przepływ prądu rażeniowego (ochrona dodatkowa).
Zgodnie z przepisami w sprawie ochrony przeciw porażeniowej należy stosować w zależności od zagrożenia następujące środki:
1. Ochronę podstawową,
2. Ochronę dodatkową,
Ochrona podstawowa ma zapobiegać:
• Zetknięciu się człowieka z przewodzącymi elementami obwodów elektrycznych, znajdujących się pod napięciem;
• Udzielaniu się napięcia przedmiotom lub elementom przewodzącym, które normalnie nie powinny znajdować się pod napięciem;
• Szkodliwemu działaniu na otoczenie łuku elektrycznego, który mógłby wystąpić przy pracy urządzeń.
Ochrona podstawowa polega więc przede wszystkim na umieszczeniu elementów znajdujących się pod napięciem poza. zasięgiem ręki człowieka, a wiec stosowanie przegród, siatek lub poręczy z materiału izolacyjnego.
Ochrona dodatkowa ma zapobiegać utrzymywaniu się niebezpiecznego napięcia dotykowego. Polega ona na zastosowaniu, poza ochroną podstawową jednego z następujących środków:
• Uziemienia ochronnego;
• Zerowania;
• Sieci ochronnej;
Uziemienia ochronne stanowią najbardziej rozpowszechniony rodzaj ochrony dodatkowej, stosowane do maszyn i urządzeń elektrycznych. Celem stosowania uziemienia ochronnego jest zrównanie potencjału uziemionych przedmiotów z potencjałem ziemi.
Zerowanie może być stosowana w przystosowanych do tego sieciach trójfazowych o napięciu poniżej 300 V. Polega ono na połączeni dostępnych części metalowych urządzeń z uziemionym przewodem zerowym.
Sieć przewodów ochronnych wolno stosować w urządzeniach przemiennoprądowych i stałoprądowych niezależnie od napięcia. Wszystkie dostępne części metalowe nie znajdujące się pod napięciem, oraz dostępne metalowe konstrukcje wsporcze i osłony powinny być połączone z przewodem ochronnym .
|
Przykładowe rozmieszczenie stanowisk pracy: biurka z komputerami znajdują się w drugim i trzecim rzędzie daleko od okien, bokiem do nich. Oprawy oświetlenia ogólnego umieszczone są nad przejściami, a nie bezpośrednio nad stanowiskami. Dla niektórych miejsc pracy może być konieczne ustawienie niskich ścianek działowych, ograniczających odbicia. Oprawy oświetleniowe muszą być kierunkowe, by nie oślepiać osób pracujących w końcach sali. |
Oświetlenie ogólne (oprawy i lampy sufitowe) nie powinno znajdować się bezpośrednio nad stanowiskiem pracy, lecz z boku. Jeśli pokój z kimś dzielimy, najlepiej je umieścić nad przejściem między biurkami. Nie jest specjalnie istotne, czy do oświetlenia wybierzemy świetlówki czy lampy żarowe (ciepłe), jeśli tylko nie występuje efekt migotania. Warto zauważyć, że światło świetlówek wymaga nieco większego natężenia oświetlenia niż światło żarowe. Na płaszczyźnie roboczej biurka natężenie oświetlenia powinno wynosić ok. 500 luksów.
Oprawy oświetlenia ogólnego powinny być tak dobrane, by nie świeciły bezpośrednio na ekran, lecz kierunkowo w stronę podłogi lub blatu biurka. W pomieszczeniu najjaśniejszy powinien być sufit, ściany nieco ciemniejsze, a podłoga wyraźnie ciemniejsza. W razie potrzeby należy tak doświetlić ścianę za ekranem, by uzyskać odpowiedni stosunek luminacji tła do luminacji ekranu. Należy jednak unikać stosowania nisko umieszczonych kinkietów ze względu na możliwość wystąpienia trudnego do wyeliminowania źródła olśnienia.
Choć lepiej jest lokalnie doświetlać zbyt ciemne obszary pracy, niż zwiększać poziom oświetlenia ogólnego, to powinniśmy zdawać sobie sprawę, że nasze dodatkowe lampki mogą spowodować przykre odbicia w monitorach współpracowników.
Na koniec warto chwilę uwagi poświęcić oknom: nie przesłonięte niczym są bardzo jaskrawe w dzień, a w nocy stanowią czarną płaszczyznę. Obie sytuacje są niekorzystne, dlatego w domu należy powiesić firanki, a w biurze, gdzie firanki z różnych względów nie są używane, powinny się znaleźć pionowe żaluzje, najlepiej wykonane z tkaniny. Żaluzje materiałowe przy ustawieniu prostopadłym do płaszczyzny okna nie przeszkadzają w swobodnym wyglądaniu na zewnątrz, a jednocześnie redukują szkodliwe odbicia.
Bibliografia:
Word Makrodefinicje, Steven Roman.
Visual Basic dla Aplikacji 5 w zastosowaniach, Paul Sanna i inni.
CHIP i inne czasopisma poświęcone tematyce kopmuterowej.
62