08 - Komunikacja z użytkownikiem
W tej lekcji poznamy podstawowe sposoby komunikacji z użytkownikiem. Dowiemy się jak wyświetlać komunikaty do osób
korzystających z Twoich makr, jak wyświetlać okienka z zapytaniam (np. potwierdzenie usunięcia jakichś danych) oraz
jak sprawić, aby w trakcie działania makra użytkownicy mogli podać jakieś informacje, które będą potem w tym makrze
wykorzystane.
Zanim jednak zostaną omówione sposoby komunikacji z użytkownikiem, poznamy jeszcze kilka interesujących informacji
na temat wywoływania funkcji i procedur, które będą przydatne także podczas omawiania tematu przewodniego tej lekcji.
Kolejność argumentów w wywoływaniu procedur i funkcji
Wiesz już doskonale, że wywołując jakąś procedurę czy funkcję, można do niej przekazać jakieś argumenty.
W lekcji poświęconej funkcjom dowiedziałeś się również, że część z tych argumentów (a nawet wszystkie) może
być opcjonalna. Wspomniałem również, że funkcja lub procedura maksymalnie mogą liczyć 60 argumentów.
Spójrz teraz na poniższy fragment kodu:
1
2
3
4
5
6
7
8
9
10
Function pensjaPoOpodatkowaniu(podstawa As Long, _
Optional stawka As Single = 0.18, _
Optional ulgaProrodzinna As Single, _
Optional ulgaNaInternet As Single, _
Optional ulgaMieszkaniowa As Single, _
Optional ulgaBudowlana As Single) As Long
pensjaPoOpodatkowaniu = podstawa - (podstawa - ulgaProrodzinna - _
ulgaNaInternet - ulgaMieszkaniowa - ulgaBudowlana) * stawka
End Function
Jest to omawiana już kilkakrotnie funkcja do obliczania pensji netto. Jednak na potrzeby dyskutowanego teraz zagadnienia
jej konstrukcja została trochę skomplikowana, ponieważ oprócz wymaganego już wcześniej argumentu podstawa
,
pojawiło się też 5 nowych argumentów opcjonalnych. Wszystko po to, aby zaprezentować Tobie przykład rozbudowanej funkcji,
posiadającej wiele argumentów, zwłaszcza opcjonalnych (zanim wkleisz ją do swojego edytora, upewnij się, że usunąłeś
poprzednią wersję tej funkcji - w jednym module nie mogą znajdować się dwie funkcje o takiej samej nazwie!).
Jak wiesz, argumenty opcjonalne mają to do siebie, że mogą, ale nie muszą być podane przy wywoływaniu funkcji.
Wyobraź sobie sytuację, w której chcesz skorzystać z powyższej wersji funkcji pensjaPoOpodatkowaniu
,
a jedynym argumentem opcjonalnym, który chcesz podać jest ostatni z nich - ulgaBudowlana
(oczywiście
będziesz musiał też podać argument podstawa
, który jest w tej funkcji wymagany).
Poniżej opisano dwa sposoby na ominięcie pozostałych opcjonalnych argumentów i podanie tylko ostatniego z nich
(testując je operuj na oknie Immediate).
Poniższy wiersz z okna Immediate przedstawia pierwszy z tych sposobów:
?pensjaPoOpodatkowaniu(5000, , , , , 1000)
W tym przykładzie funkcja pensjaPoOpodatkowaniu
została wywołana z argumentem podstawa
równym 5000 oraz argumentem ulgaBudowlana
równym 1000.
Jak widzisz, w miejscu argumentów opcjonalnych, których nie chcesz podawać przy wywołaniu funkcji lub procedury,
trzeba po prostu wstawić spację i przecinkiem przejść do kolejnego argumentu (przecinek to znak informujący
kompilator o przejściu do określania kolejnego argumentu z listy argumentów danej funkcji lub procedury).
Taki sposób ma oczywiście swoje zalety i wady.
Zaletą jest na pewno szybkość, ponieważ w miejsce omijanych argumentów opcjonalnych wstawia się jedynie spację
i przechodzi do kolejnego argumentu.
Główną wadą takiego rozwiązania jest natomiast jego nieczytelność. Patrząc na powyższą linijkę kodu, na pierwszy
rzut oka nie masz pojęcia którego argumentu dotyczy liczba 1000. W przytaczanym przykładzie można się jeszcze w miarę
łatwo domyślić, do którego argumentu przypisana jest wartość 1000, ponieważ jest to ostatni argument z listy. Zdarzają
się jednak sytuacje, że funkcja posiada przykładowo 20 argumentów opcjonalnych, a podany ma być tylko dwunasty z nich.
W przypadku funkcji z bardzo dużą liczbą argumentów opcjonalnych, z których większość ma być pominięta, ujawnia się też
druga wada tej metody - konieczność niepotrzebnego wpisywania wielu spacji z przecinkiem. Oprócz tego, że jest to zajęcie
czasochłonne i bardzo nieczytelnie wygląda w kodzie, mogłoby też prowadzić do wielu pomyłek, gdyż wpisując te spacje
łatwo się pomylić i zapomnieć przy którym argumencie aktualnie się znajduje. Ale w tej kwestii z pomocą przychodzi
edytor VBA i jego narzędzie Auto Quick Info, które przy podawaniu argumentów procedury i funkcji podświetla
argument, który jest w danym momencie wpisywany (tak jak pokazano na poniższym obrazku).
Drugi sposób omijania niepotrzebnych argumentów opcjonalnych w przypadku funkcji o małej liczbie argumentów wymaga nieco
więcej pisania niż poprzedni, jest za to o wiele bardziej czytelny. Natomiast dla funkcji z bardzo dużą liczbą argumentów
opcjonalnych, spośród których tylko nieliczne mają zostać określone, nawet ta wada przestaje mieć znaczenie i sposób ten
staje się jedynym słusznym wyborem.
Sposób ten został przedstawiony w poniższym wierszu kodu:
?pensjaPoOpodatkowaniu(podstawa:=5000, ulgaBudowlana:=1000)
Za pomocą tej metody należy określić nazwę każdego z podawanych argumentów, wstawić dwukropek ze znakiem równości
(:=
) i przypisać do niej wartość.
Stosując to rozwiązanie po prostu ignorujesz wszystkie niepotrzebne w danym wywołaniu argumenty wywoływanej funkcji.
Drugi z opisanych sposobów jest zarazem jedyną metoda na podanie argumentów w innej kolejności niż zostało to
określone przy tworzeniu funkcji.
Powyższa funkcja równie dobrze zadziałałaby, gdyby została wywołana w taki sposób:
?pensjaPoOpodatkowaniu(ulgaBudowlana:=1000, podstawa:=5000)
Zagnieżdżanie funkcji
Podobnie jak w tradycyjnym arkuszu Excelowym, programując w VBA możesz stosować zagnieżdżanie funkcji.
Oznacza to, że jako argument funkcji lub procedury możesz podać inną funkcję.
Bez żadnych problemów zadziała na przykład poniższy wpis, w którym jako argument funkcji
pensjaPoOpodatkowaniu
podana została funkcja Abs(-5000)
.
?pensjaPoOpodatkowaniu(Abs(-5000))
Obliczając takie wyrażenie, kompilator rozpoczyna od obliczenia funkcji znajdującej się na najniższym poziomie
hierarchii, czyli w tym przypadku od funkcji Abs(-5000)
.
Gdyby jako argument funkcji Abs
również podana była jakaś funkcja, to właśnie od niej rozpoczęłoby
się obliczanie całego wyrażenia.
Zagnieżdżając funkcje musisz zwracać uwagę na wymagane typy argumentów i typy zwracane przez zagnieżdżane funkcje.
Aby lepiej zrozumieć tę zasadę, wykonaj przedstawiony poniżej eksperyment.
Wklej do edytora poniższą funkcję:
1
2
3
Function zwrocTekst() As String
zwrocTekst = 5000
End Function
Funkcja ta nie wymaga podania żadnego argumentu i za każdym razem zwraca wartość 5000. Zwracana wartość jest tekstem
ponieważ w wierszu otwarcia określono za pomocą słów kluczowych As String
, że
funkcja zwraca wartości tekstowe.
Spróbuj teraz uruchomić w oknie Immediate następujący wiersz:
?pensjaPoOpodatkowaniu("5000")
Jak widzisz, funkcja zadziałała idealnie, mimo że podałeś jako argument wartość tekstową 5000, podczas gdy argument
podstawa
wymagał argumentu typu Long
. Kompilator bez kłopotu przetłumaczył sobie tekst 5000
(czyli identyczny tekst, jaki zwraca funkcja zwrocTekst
) na liczbę o takiej samej wartości.
Teraz spróbuj uruchomić w oknie Immediate tę samą funkcję, ale zamiast tekstu 5000 podaj w argumencie
funkcję zwrocTekst
. Jak pamiętasz, funkcja ta zawsze zwraca w swoim wyniku tekst 5000 (czyli ten
sam, który przed momentem idealnie zadziałał), więc teoretycznie również nie powinno być problemu z jej uruchomieniem.
?pensjaPoOpodatkowaniu(zwrocTekst)
Tak się jednak nie stało. Edytor VBA w ogóle nie uruchomił funkcji, a zamiast tego wyświetlił komunikat o
błędzie Run-time error '13': Type mismatch.
Wniosek z tego eksperymentu jest prosty: Funkcja zagnieżdżana w innej funkcji, musi zwracać typ danych identyczny z typem
reprezentowanym przez argument, w miejsce którego ta funkcja jest wstawiana.
Istnieje pewien sposób na ominięcie tego ograniczenia, który wymaga zastosowania omówionych w poprzedniej lekcji
funkcji konwersji.
Jeżeli zamiast argumentu typu Long
chcesz podać funkcję, która zwraca typ String
,
musisz dodatkowo przerobić tę funkcję funkcją konwertującą do odpowiedniego typu danych, w tym przypadku
funkcją CLng
.
W poniższej linijce kodu zmodyfikowano wcześniejsze zapytanie, tak aby zadziałało bez generowania błędów:
?pensjaPoOpodatkowaniu(CLng(zwrocTekst))
W tym kodzie zagnieżdżone są dwie funkcje: zwrocTekst
oraz CLng
. Jak już wcześniej wspomniałem,
kompilator kodu rozpoczyna wykonywanie obliczeń od najbardziej wewnętrznych funkcji, w tym przypadku od funkcji
zwrocTekst
, która zwraca wartość tekstową 5000. Następnie przechodzi do kolejnej funkcji
CLng
, która ma teraz za zadanie przekonwertować otrzymaną z funkcji zwrocTekst
wartość
tekstową 5000 do liczby o takiej samej wartości. Kiedy funkcja CLng
skończy swoje działanie
przekazuje 5000, już w postaci liczbowej, do głównej funkcji tego zapytania - pensjaPoOpodatkowaniu
.
W Excelu 2003 zagnieżdżanie funkcji jest ograniczone do maksymalnie siedmiu poziomów. Takiego ograniczenia nie ma
w języku VBA, ale w rzeczywistości nie powinno się stosować więcej niż 4-5 poziomów zagnieżdżania, ponieważ po
przekroczeniu tej liczby kod staje się bardzo nieczytelny i podatny na błędy.
Wyświetlanie komunikatów
Wyświetlanie komunikatów dla użytkownika to bardzo ważny element programowania. Za pomocą okienek z
odpowiednim komunikatem można przekazać użytkownikowi szereg istotnych informacji, takich jak np. brak
niezbędnych danych, błędy występujące podczas działania aplikacji czy też informację o pomyślnym zakończeniu
działania makra.
Poniżej znajduje się proste makro, którego jedynym zadaniem jest wyświetlenie powitania. Oczywiście nie ma ono zbyt
dużej wartości użytkowej, ale w prosty sposób pokaże Ci jak wstawiać w kodzie VBA komunikaty.
Najpierw wklej do swojego edytora VBA poniższy kod i uruchom makro, aby zobaczyć jak działa, a następnie przejdź
do analizy kodu, znajdującej się pod ramką.
1
2
3
4
Sub wyswietlaniePowitania()
Call MsgBox("Witaj! To jest makro prezentujące " & _
"wyświetlanie komunikatów dla użytkownika.")
End Sub
Jedyną czynnością, jaką wykonuje powyższe makro jest wyświetlenie na ekranie ramki takiej, jak na
poniższym obrazku:
Pomijając wiersz otwarcia i zamknięcia, które powinieneś już doskonale znać, procedura składa się tylko z jednego polecenia:
MsgBox
.
MsgBox
to wbudowana funkcja VBA, która odpowiada za wyświetlanie komunikatów do użytkownika i odczytywanie jego
reakcji na te komunikaty.
Jeżeli podczas działania makra kompilator natrafi na funkcję MsgBox
i wyświetli na ekranie okno
komunikatu, to wykonywanie kolejnych instrukcji znajdujących się po tej funkcji jest wstrzymane do momentu,
kiedy okno komunikatu zostanie zamknięte.
Składnia funkcji MsgBox
przedstawia się następująco:
1
2
3
Function MsgBox(Prompt As String, _
Optional Buttons As VbMsgBoxStyle = vbOKOnly, Optional Title As _
String, Optional HelpFile, Optional Context) As VbMsgBoxResult
Poniżej zostały opisane trzy podstawowe argumenty funkcji MsgBox
-
Prompt
,
Buttons
oraz
Title
.
Prompt
Argument Prompt
to jedyny wymagany argument funkcji MsgBox
.
Jest to argument typu tekstowego i odpowiada za tekst, który pojawi się w okienku wyświetlonym na ekranie użytkownika.
W przytoczonym przykładzie argument Prompt
miał wartość Witaj! To jest makro prezentujące wyświetlanie
komunikatów dla użytkownika i taka też wartość pojawiła się jako komunikat.
Wyświetlając komunikaty za pomocą funkcji MsgBox
, nie musisz ograniczać się do wypisywania ich jednym ciągiem.
Język VBA posiada specjalne polecenia, które umożliwiają przeniesienie części komunikatu do nowej linijki lub
zastosowanie wewnątrz komunikatu tabulatorów.
Poniżej znajduje się zmodyfikowana procedura wyswietlaniePowitania
, w której dodano aktualną datę i czas
(zastosowane tutaj funkcje zwracające aktualną datę i czas zostały omówione
w poprzedniej lekcji)
i przeniesiono je do nowej linijki (nowe fragmenty kodu zostały oznaczone na czerwono).
1
2
3
4
5
6
7
Sub wyswietlaniePowitania()
Call MsgBox("Witaj!" & vbCrlf & "Oto makro prezentujące " & _
"wyświetlanie komunikatów dla użytkownika." & _
vbCrLf & vbCrLf & vbCrLf & _
"Aktualna data: " & Date & vbCrLf & _
"Aktualny czas: " & Time)
End Sub
Jak widać w kodzie umieszczonym powyżej, aby przenieść część komunikatu do następnej linijki, należy zamknąć
cudzysłowem dotychczasowy tekst komunikatu, dopisać znak łączenia znaków otoczony spacjami ( &
), potem
wpisać słowo kluczowe vbCrLf
, ponownie wstawić znak łączenia znaków ze spacjami z lewej i prawej strony
( &
) i kontynuować pisanie komunikatu dla użytkownika. Część znajdująca się po słowie kluczowym
vbCrLf
znajdzie się w komunikacie już w nowym wierszu.
Pomiędzy częścią Oto makro prezentujące wyświetlanie komunikatów dla użytkownika., a wyświetlaniem aktualnej daty,
słowo kluczowe vbCrLf
zostało wstawione trzykrotnie, dzięki czemu w komunikacie pojawią się dodatkowo dwie
puste linijki, które wyraźnie oddzielą obie części komunikatu.
Wyświetlony komunikat powinien wyglądać tak jak na poniższym rysunku:
Oprócz przenoszenia części komunikatu do nowego wiersza, VBA umożliwia również wstawianie w komunikatach tabulatorów,
które przesuwają tekst o kilka znaków w prawo w ramach tej samej linijki.
Poniższy kod jest modyfikacją poprzedniego, w którym, oprócz przeniesienia niektórych fragmentów komunikatu do nowych
linijek, nagłówki Aktualna data: i Aktualny czas: oddzielono kilkoma tabulatorami od ich wartości
(tradycyjnie nowe fragmenty kodu zostały podświetlone na czerwono).
1
2
3
4
5
6
7
Sub wyswietlaniePowitania()
Call MsgBox("Witaj!" & vbCrLf & "Oto makro prezentujące " & _
"wyświetlanie komunikatów dla użytkownika." & _
vbCrLf & vbCrLf & vbCrLf & _
"Aktualna data: " & vbTab & vbTab & Date & vbCrLf & _
"Aktualny czas: " & vbTab & vbTab & Time)
End Sub
Zmodyfikowana funkcja wyświetli komunikat taki jak na poniższym rysunku:
Aby w komunikacie oddzielić od siebie dwie części tekstu tabulatorem, należy zamknąć pierwszą część tekstu
cudzysłowem, wstawić polecenie & vbTab &
, a potem wpisać drugą część komunikatu, która pojawi się
już przesunięta względem pierwszej części tekstu o określoną liczbę tabulatorów.
Polecenia vbCrLf
i vbTab
mają zastosowanie nie tylko przy wyświetlaniu komunikatów za
pomocą funkcji MsgBox
, ale wszędzie tam, gdzie masz do czynienia z tekstami - mogą być one elementem
każdej zmiennej tekstowej.
Jeżeli w makrze pojawiłaby się przykładowo taka linijka kodu:
Cells(1,1) = "pierwszy wiersz" & vbCrLf & "drugi wiersz"
to w komórce A1, tekst ten zostałby zapisany tak jak na poniższym rysunku, o czym zresztą łatwo możesz się
przekonać na własne oczy, wklejając i wywołując tę linijkę w oknie Immediate.
Argument Buttons
, jak sama nazwa wskazuje, jest odpowiedzialny za wygląd przycisków i ikon,
jakie pojawią się w oknie z komunikatem dla użytkownika.
Poniższa lista przedstawia podstawowe parametry, jakie można określić za pomocą argumentu Buttons
:
- liczba przycisków w oknie z komunikatem,
- domyślnie wybrany przycisk,
- ikona, która towarzyszy komunikatowi,
- wyrównanie tekstu w oknie komunikatu.
Przy określaniu każdego z powyższych parametrów masz do wyboru pewną liczbę wariantów, które zostaną opisane poniżej.
Nie ma konieczności określania każdego parametru - możesz opisać tylko niektóre z nich, dla pozostałych zostaną
wówczas przypisane wartości domyślne.
Jeżeli argument Buttons
jest całkowicie pominięty, dla wszystkich parametrów zostaną przypisane wartości
domyślne - a więc w oknie komunikatu pojawi się tylko przycisk OK, który jako jedyny przycisk będzie oczywiście
domyślnie zaznaczony, a tekst komunikatu będzie wyrównany do lewej i nie będzie mu towarzyszyła żadna ikona.
Określanie kolejnych parametrów wygląda w kodzie tak, jakby były one do siebie dodawane - oznacza to, że należy wybrać z
listy wartość dla pierwszego parametru, następnie wstawić znak plusa, wybrać wartość dla kolejnego parametru itd. Po
szczegółowym opisie wszystkich parametrów znajdziesz kilka przykładów
prezentujących sposób określania parametrów przykładach.
Pierwszym parametrem opisywanym przez argument Buttons
jest liczba oraz nazwy przycisków, jakie
pojawią się w oknie komunikatu.
Jeżeli parametr ten zostanie pominięty, domyślnie wyświetlony zostanie tylko jeden przycisk z napisem OK.
Dostępne zestawy parametrów zostały zaprezentowane w poniższej tabelce (zapamiętaj, że wartości przedstawione w lewej
kolumnie tabeli muszą być wpisywane w kodzie bez cudzysłowów, ponieważ nie są one zmiennymi tekstowymi lecz tzw.
wartościami wyliczeniowymi, które będą omówione w późniejszej części kursu):
Liczba i nazwy przycisków w oknie komunikatu
WARTOŚĆ | WYŚWIETLANE PRZYCISKI |
vbOKOnly | wyświetla tylko przycisk OK |
vbOKCancel | wyświetla przyciski OK oraz Cancel |
vbAbortRetryIgnore | wyświetla przyciski Abort, Retry oraz Ignore |
vbYesNoCancel | wyświetla przyciski Yes, No oraz Cancel |
vbYesNo | wyświetla przyciski Yes oraz No |
vbRetryCancel | wyświetla przyciski Retry oraz Cancel |
Nazwy pojawiające się na przyciskach są uzależnione od zainstalowanego systemu operacyjnego. Niestety nie da się
zmodyfikować funkcji MsgBox
tak, aby dostosować nazwy przycisków do własnych potrzeb. W późniejszej
części kursu nauczysz się jednak tworzyć własne, bardziej zaawansowane narzędzia do interakcji z użytkownikiem,
gdzie w razie potrzeby, będziesz mógł wstawiać własne nazwy przycisków.
Stosowanie różnych zestawów przycisków służy oczywiście temu, aby makro wywoływało odpowiednie czynności w
zależności od tego, który z tych przycisków został wciśnięty.
Przykłady wywoływania czynności na podstawie wciśniętego przycisku zostaną jednak omówione dopiero w następnej lekcji,
kiedy poznasz konstrukcję warunkową If ... Then
, niezbędną do konstruowania tego typu poleceń.
Na razie zapamiętaj tylko, że w oknie komunikatu mogą pojawiać się różne zestawy przycisków. Nie ma sensu uczyć się ich
na pamięć, ponieważ po pierwsze zawsze możesz zajrzeć do przedstawionej powyżej tabelki, a po drugie przy pisaniu kodu
edytor VBA pokazuje listę dostępnych wartości (tak jak to przedstawiono na poniższym obrazku), dzięki czemu, nie dość
że nie będziesz musiał pamiętać ich dokładnych nazw, to jeszcze zaoszczędzisz sporo czasu, gdyż zamiast wpisywać je
ręcznie, będziesz mógł wybrać je z listy.
W tej konkretnej sytuacji autouzupełnianie ma jednak pewną wadę - wartości dla wszystkich parametrów znajdują się na
jednej liście i są ze sobą wymieszane, w związku z czym początkowo możesz mieć niewielkie trudności przy ich wyborze.
Na szczęście jednak wartości są dosyć dobrze nazwane i nawet nie mając ich biegle opanowanych, bez trudu domyślisz się,
czego dotyczą poszczególne z nich (w ostateczności zawsze możesz zajrzeć do spisu wartości przy każdym parametrze
omówionym w tej lekcji).
Jeżeli w oknie komunikatu umieściłeś zestaw przycisków zawierający przycisk Cancel to wciśnięcie krzyżyka
służącego do zamykania okna umieszczonego w jego prawym górnym rogu lub klawisza Esc będzie równoznaczne z
wciśnięciem przycisku Cancel.
Jeżeli Twoje okno nie zawiera przycisku Cancel to rolę tę przejmuje przycisk OK.
Jeżeli okno nie zawiera żadnego z tych dwóch przycisków, wciśnięcie klawisza Esc przy wyświetlonym oknie komunikatu
nie odniesie żadnych skutków. Niemożliwe jest też w takiej sytuacji zamknięcie okna komunikatu poprzez wciśnięcie krzyżyka
w prawym górnym rogu. Jedynym sposobem zamknięcia okna jest wówczas kliknięcie któregoś z dostępnych przycisków.
Drugim z parametrów określanych poprzez argument Buttons
jest przycisk, który ma być domyślnie
zaznaczony przy wyświetlaniu okna z komunikatem.
Wartości określające domyślny przycisk są tak proste, że w zasadzie nie ma sensu ich wyjaśniania, ale dla spójności
całej lekcji zostały przedstawione w poniższej tabelce.
Wartości określające domyślnie wybrany przycisk
WARTOŚĆ | DOMYŚLNY PRZYCISK |
vbDefaultButton1 | domyślnie wybrany pierwszy przycisk |
vbDefaultButton2 | domyślnie wybrany drugi przycisk |
vbDefaultButton3 | domyślnie wybrany trzeci przycisk |
vbDefaultButton4 | domyślnie wybrany czwarty przycisk |
Podobnie jak w przypadku wartości określających liczbę przycisków i pozostałe parametry, poniższe wartości muszą być
wpisywane w edytorze bez cudzysłowów, ponieważ nie są tekstami, lecz wartościami wyliczeniowymi.
Jeżeli liczba przycisków będzie mniejsza niż numer domyślnego przycisku (np. okno będzie posiadało tylko przyciski
OK i Cancel, a równocześnie zostanie określone, że domyślnym przyciskiem jest przycisk trzeci)
automatycznie domyślnym przyciskiem zostanie uczyniony pierwszy przycisk.
Wreszcie ostatnim parametrem definiowanym przez argument Buttons
jest wyrównanie tekstu komunikatu.
Tutaj do wyboru jest tylko jedna wartość - vbMsgBoxRight
, oznaczająca, że tekst będzie wyrównywany
do prawej strony.
Aby wyrównać tekst do lewej strony wystarczy pominąć ten parametr, ponieważ wyrównanie do lewej jest jego domyślnym
ustawieniem.
Pamiętaj, aby do każdego parametru wybrać tylko jedną wartość. Równoczesne określenie kilku wartości dla tego samego
parametru może prowadzić do nieprzewidzianych rezultatów!
Title
Argument opcjonalny Title
pozwala zmienić napis wyświetlany na niebieskim pasku u góry okna komunikatu.
Domyślnie na pasku tym pojawia się napis Microsoft Excel. Taki też napis pojawił się we wszystkich wcześniejszych
wywołaniach okna komunikatu, przedstawionych w niniejszej lekcji, ponieważ za każdym razem argument Title
był pomijany.
Warto poświęcić trochę czasu i zadbać o to, aby okna z komunikatami były dobrze zatytułowane, co zawsze dodaje aplikacji
profesjonalizmu.
Poniżej przedstawiono kod makra wyświetlającego komunikat powitalny (z początku tego podrozdziału), wzbogacony o tytuł
okna komunikatu.
1
2
3
4
5
Sub wyswietlaniePowitania()
Call MsgBox(Prompt:="Witaj! To jest makro prezentujące " & _
"wyświetlanie komunikatów dla użytkownika.", _
Title:="Powitanie")
End Sub
Okno wyświetlane przez ten zmodyfikowany kod wygląda tak jak na poniższym obrazku. Zwróć uwagę na tytuł na niebieskim
pasku u góry okna.
Przykłady wywołań okna komunikatu
Poniżej przedstawiono kilka przykładów wywołań okna komunikatu. Każdy z przykładów składa się z odpowiedniego
fragmentu kodu oraz obrazka pokazującego wyświetlone okno.
Okno komunikatu z dwoma przyciskami: OK i Cancel (gdzie przycisk Cancel jest domyślny)
oraz ikoną stanu krytycznego.
1
2
3
4
Sub wyswietlaniePowitania()
Call MsgBox("Tekst komunikatu", _
vbOKCancel + vbCritical + vbDefaultButton2, "Tytuł okna")
End Sub
Okno komunikatu z trzema przyciskami: Yes, No oraz Cancel (gdzie przycisk Cancel
jest domyślny) oraz ikoną zapytania.
1
2
3
4
5
Sub wyswietlaniePowitania()
Call MsgBox("Czy na pewno chcesz usunąć plik?", _
vbYesNoCancel + vbQuestion + vbDefaultButton3, _
"Potwierdzenie usunięcia")
End Sub
Okno komunikatu z dwoma przyciskami: OK i Cancel oraz ikoną ostrzeżenia, w którym treść
komunikatu wyrównana jest do prawej.
1
2
3
4
Sub wyswietlaniePowitania()
Call MsgBox("Wyrównanie do prawej", _
vbOKCancel + vbExclamation + vbMsgBoxRight, "Ostrzeżenie")
End Sub
Obok omówionej funkcji MsgBox
, wyświetlającej komunikaty i umożliwiającej użytkownikom
podejmowanie prostych decyzji (Tak/Nie, Zatwierdź/Anuluj), język VBA udostępnia jeszcze
drugą funkcję służącą do komunikacji z użytkownikami - InputBox
.
Zadaniem funkcji InputBox
jest pobieranie od użytkowników bardziej złożonych informacji,
takich jak np. haseł, nazw, dat lub wartości liczbowych.
Skopiuj poniższy kod i wklej go do edytora:
1
2
3
4
5
6
Sub pobieranieWartosci()
Dim tekst As String
tekst = InputBox("Wartość, która pojawi się w komórce A1")
Cells(1,1) = tekst
End Sub
Działanie całego makra polega na wyświetleniu okienka identycznego, jak na poniższym obrazku
a następnie pobranie wartości, którą użytkownik wpisał w tym oknie, i wpisanie jej do komórki A1 aktywnego arkusza.
W drugiej linijce kodu zostaje zadeklarowana zmienna typu tekstowego tekst
.
W czwartym wierszu do zmiennej tekst
zostaje przypisany wynik działania funkcji InputBox
,
czyli wartość wpisana w przedstawionym przed momentem oknie (sposób działania funkcji InputBox
za chwilę
zostanie szczegółowo omówiony).
Wreszcie w ostatnim wierszu procedury przed jej zamknięciem (5), znajduje się znane Ci już
polecenie Cells(1,1) = tekst
, które w komórce A1 aktywnego arkusza wyświetla wartość zmiennej
tekst
.
W powyższej procedurze zmienna tekst
mogłaby zostać pominięta, a wynik funkcji od razu zapisany w
arkuszu za pomocą poniższego wiersza:
Cells(1,1) = InputBox("Wartość, która pojawi się w komórce A1")
Korzystanie ze zmiennych pośredniczących w takich przykładach, jak powyżej, wydłuża wprawdzie cały kod, ale ma na
celu przyzwyczaić Cię do deklarowania zmiennych, co przy większych i bardziej skomplikowanych makrach, którymi
będziesz się zajmował w przyszłości, okaże się bardzo przydatne.
Szczegółowego omówienia wymaga wiersz 4 tej procedury, w którym pojawił się jedyny
nowy element - bohaterka niniejszego podrozdziału, funkcja InputBox
.
Postać ogólna funkcji InputBox
przedstawia się następująco:
Function InputBox(Prompt As String, _
Optional Title As String, Optional Default, _
Optional XPos As Single, Optional YPos As Single, _
Optional HelpFile, Optional Context) As String
Argumenty Prompt
oraz Title
zostały już szczegółowo omówione przy okazji
podrozdziału poświęconego funkcji MsgBox
.
W funkcji InputBox
ich działanie jest identyczne: argument Prompt
odpowiada
więc za treść komunikatu dla użytkownika (w tym przypadku będzie to instrukcja dotycząca pobieranej
wartości, np.: Wpisz datę urodzenia lub Wpisz hasło), natomiast wartość argumentu
Title
pojawi się na górnym pasku okna wyświetlanego na ekranie.
Oba elementy zostały zaznaczone na poniższym rysunku (czerwoną ramką oznaczono miejsce, gdzie w oknie
InputBox
pojawia się wartość argumentu Prompt
, natomiast zieloną - miejsce, w
którym wyświetlony jest tekst podany jako argument Title
).
Argument Default
pozwala zdefiniować wartość domyślną, jaka ma się pojawić w polu
tekstowym wyświetlanego okna. Argument ten może przyjmować wartości wszystkich typów podstawowych.
Jeżeli argument Default
zostanie pominięty, okno InputBox
będzie wyświetlone
z pustym polem tekstowym.
Argumenty XPos
i YPos
odpowiadają za początkową pozycję okna InputBox
na ekranie (po jego wyświetleniu możesz je przesunąć w dowolne miejsce ekranu).
Argument XPos
określa odległość okna InputBox
od lewej krawędzi ekranu, natomiast
argument YPos
jego odległość od górnej krawędzi.
Obie te wartości wyrażane są w jednostkach zwanych twipsami (1440 twipsów = 1 cal).
W sytuacji, gdy wartości XPos
i YPos
zostaną pominięte przy wywoływaniu tej funkcji,
okno InputBox
zostanie wyświetlone na środku ekranu w poziomie i mniej więcej w jednej trzeciej
wysokości ekranu.
Argumenty XPos
i YPos
muszą być podane łącznie. Jeżeli określisz tylko jeden z tych
argumentów, pomijając drugi, okno InputBox
zostanie wyświetlone tak, jakbyś nie podał żadnego z
nich.
W funkcji InputBox
w przeciwieństwie do MsgBox
nie ma możliwości dostosowania liczby i
nazw wyświetlanych przycisków. W kwestii przycisków jedyną dostępną opcją jest domyślny zestaw dwóch przycisków -
OK oraz Cancel.
Poniżej znajdują się dwa przykłady funkcji InputBox
, składające się z fragmentu kodu
oraz obrazka pokazującego jak zostało w danej sytuacji wyświetlone okno z zapytaniem. (Przykłady są
przeznaczone do wywołania w oknie Immediate, o czym świadczy znak zapytania na poczatku wiersza,
więc jeżeli chcesz je przetestować własnoręcznie, zrób to właśnie w oknie Immediate).
Okno z zapytaniem o datę urodzenia i wartością domyślną 3 stycznia 1983, położone w odległości
1 cala od góry i 1 cala od lewej krawędzi ekranu.
?InputBox("Podaj datę urodzenia", "Data urodzenia", #1983-01-03#, 1440, 1440)
Okno z zapytaniem o wysokośc pensji brutto i wartością domyślną 4000, wyświetlony w domyślnym miejscu na ekranie.
?InputBox("Podaj pensję brutto", "Pensja brutto", 4000)
Przykłady prostych aplikacji komunikujących się z użytkownikiem
Aby utrwalić wiedzę zdobytą w dotychczasowych lekcjach, przeanalizuj umieszczone poniżej przykłady dwóch
niewielkich aplikacji korzystających z omówionych w niniejszej lekcji sposobów komunikacji z użytkownikiem
oraz z kilku innych funkcjonalności przedstawionych w poprzednich lekcjach.
Obliczanie pensji netto
Pierwszy przykład będzie się opierał na omawianej już i kilkakrotnie modyfikowanej funkcji do obliczania pensji netto.
Dodatkowym elementem będzie jednak pobieranie informacji o pensji brutto bezpośrednio od użytkownika, do czego
wykorzystana zostanie funkcja InputBox
, oraz wyświetlenie obliczonej pensji netto w oddzielnym oknie
zapomocą funkcji MsgBox
.
1
2
3
4
5
6
7
8
9
10
Sub zarobki()
Dim pensjaBrutto As Long
Dim pensjaNetto As Long
pensjaBrutto = InputBox("Podaj wysokość pensji brutto", "Pensja brutto")
pensjaNetto = pensjaPoOpodatkowaniu(pensjaBrutto)
Call MsgBox("Twoja pensja netto wynosi: " & pensjaNetto, _
vbOKOnly, "Pensja netto")
End Sub
1
2
3
Function pensjaPoOpodatkowaniu(podstawa As Long) As Long
pensjaPoOpodatkowaniu = podstawa - (podstawa * 0.18)
End Function
Większość przedstawionego powyżej kodu powinna być Ci już znana z poprzednich lekcji.
W wierszach 2-3 zadeklarowane są dwie zmienne typu Long
: pensjaBrutto
i pensjaNetto
.
W wierszach 5-6 do zmiennej pensjaBrutto
zostaje przypisany wynik działania funkcji
InputBox
, a więc to, co użytkownik wpisze w wyświetlonym oknie.
Przy wywołaniu funkcji InputBox
, oprócz obowiązkowego argumentu Prompt
, który przyjmuje wartość
Podaj wysokość pensji brutto, podany został również argument opcjonalny Title
, do którego przypisano
tekst Pensja brutto (oznacza to, że taki tekst pojawi się na niebieskim pasku u góry okna z zapytaniem).
Zwróć uwagę, że funkcja InputBox
zwraca wartości tekstowe, więc nawet jeśli wpiszesz w jej oknie liczbę lub
datę, to wynikiem funkcji będzie tekstowa reprezentacja tej liczby lub daty. Na szczęście, jak wspomniano
w lekcji omawiającej typy danych, przy przypisywaniu tekstowych reprezentacji
liczb do zmiennych liczbowych, język VBA automatycznie konwertuje je do wartości liczbowych.
W wierszu 7 do zmiennej pensjaNetto
zostaje przypisany wynik funkcji
pensjaPoOpodatkowaniu
, w której argumentem podstawa
jest wartość zmiennej pensjaBrutto
,
czyli wartość, którą użytkownik podał w oknie InputBox
.
W wierszu 9 zostaje wywołana funkcja MsgBox
, która wyświetla na ekranie informację
o wysokości pensji netto dla podanej wcześniej pensji brutto.
Jak widzisz na podstawie argumentów podanych przy wywoływaniu funkcji MsgBox
, okno komunikatu będzie posiadało
tylko przycisk OK, a na pasku tytułu pojawi się napis Pensja netto.
Powyższa aplikacja pozostawia jeszcze trochę do życzenia, głównie w kwestii sprawdzania poprawności danych.
Wyobraź sobie bowiem, że użytkownik w oknie z pytaniem o wysokość pensji brutto zamiast wartości liczbowej
wpisze tekst. W dopiętej na ostatni guzik aplikacji w takiej sytuacji powinien pojawiać się komunikat o
nieprawidłowym formacie danych wraz z informacją, że w tym polu wymagana jest liczba.
Omówiona przed chwilą aplikacja nie jest uodporniona na tego typu zachowania użytkowników i w przypadku podania wartości
tekstowej zostanie wygenerowany błąd, a całe makro przerwie swoje działanie wyświetlając na ekranie zupełnie
niezrozumiały dla końcowego użytkownika komunikat VBA zawierający numer błędu. W profesjonalnych aplikacjach
nie ma miejsca na takie sytuacje - użytkownik nigdy nie powinien oglądać komunikatów o błędach powstałych
podczas wykonywania kodu.
W kolejnej lekcji poznasz jednak instrukcję warunkową If ... Then
, która doskonale nadaje się do tego,
żeby wyeliminować tę niedoskonałość aplikacji.
Obliczanie liczby przeżytych miesięcy, tygodni, dni itd.
Drugi przykład prezentuje aplikację, która na podstawie podanej przez użytkownika daty urodzenia oblicza
liczbę przeżytych przez niego miesięcy, tygodni oraz dni i wyświetla te informacje w oknie z komunikatem.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Sub obliczanieCzasu()
Dim dataUrodzenia As Date
Dim miesiace As Long
Dim tygodnie As Long
Dim dni As Long
dataUrodzenia = InputBox("Podaj datę urodzenia", "Data urodzenia")
miesiace = DateDiff("m", dataUrodzenia, Date)
tygodnie = DateDiff("ww", dataUrodzenia, Date)
dni = DateDiff("d", dataUrodzenia, Date)
Call MsgBox("Dotychczas przeżyłeś: " & vbCrLf & _
miesiace & " miesięcy" & vbCrLf & _
tygodnie & " tygodni" & vbCrLf & _
dni & " dni", vbOKOnly, "Ile już przeżyłeś")
End Sub
W wierszach 2-5 znajdują się deklaracje zmiennych wykorzystanych w tej aplikacji.
Pierwszą z nich jest zmienna typu datowego dataUrodzenia
, do której, jak wskazuje jej nazwa,
przypisana zostanie później wprowadzona przez użytkownika data urodzenia. Oprócz niej w aplikacji wykorzystane
są trzy zmienne typu Long
- miesiace
, tygodnie
oraz dni
,
do których przypisana będzie odpowiednia liczba miesięcy, tygodni i dni.
W wierszu 7 do zmiennej dataUrodzenia
zostaje przypisany wynik działania
funkcji InputBox
, czyli data, jaką użytkownik wpisze w wyświetlonym oknie.
W kolejnych trzech wierszach do zmiennych miesiace
, tygodnie
i dni
przypisana
zostaje liczba miesięcy, tygodni i dni jakie upłynęły od daty urodzenia wprowadzonej przez użytkownika do daty
dzisiejszej.
Do obliczenia różnicy pomiędzy dwiema datami - dzisiejszą i podaną przez użytkownika - zastosowano wbudowaną funkcję
DateDiff
, której działanie omówiono szczegółowo w
poprzednim rozdziale.
Aby pobrać aktualną datę wykorzystano natomiast inną wbudowaną funkcję - Date
.
Po obliczeniu wszystkich różnic w datach i przypisaniu ich do zmiennych, w wierszach 12-15 zostaje
wywołane okno komunikatu, w którym wyświetlono wartości tych zmiennych.
Określając tekst komunikatu kilkukrotnie zastosowano słowo kluczowe vbCrLf
, co pozwoliło na wyświetlenie
każdej wyliczonej wartości w oddzielnej linijce.