Jakiś nieszczęśnik trafił wczoraj na mojego bloga w poszukiwaniu typów wyliczanych w VBA. Przypuszczam, że w efekcie usnął i spóźnił się do pracy, skutkiem czego zapamiętał sobie, żeby nigdy więcej tutaj nie zaglądać. Niemniej jednak nadgryzę temat - a nuż ktoś kiedyś tu trafi szukając typów wyliczanych - i proszę bardzo, wszystko podane jak na tacy.
Na początku powiem, że typy wyliczane w VBA są nieudolną próbą naśladowania "prawdziwych", obiektowo zorientowanych języków programowania - nie należy się jednak spodziewać tutaj takiej elastyczności jaką daje na przykład enum w C#.
Wystarczy tej gry przedwstępnej, przejdźmy do rzeczy.
Typ wyliczany (po naszemu enumeration albo enumerated data type) to nic innego jak zbiór wartości liczbowych (całkowitych), z których każda ma etykietę tekstową, zebranych pod wspólną nazwą.
Przykład:
Enum Jablko
Antonowka
Malinowka
Reneta
Lobo
Kosztela
End Enum
W powyższym przykładzie definiujemy sobie typ wyliczany Jablko, a następnie przydzielamy mu pięć wartości typu Integer, od zera do czterech. Antonowka ma wartość 0, Malinowka 1 i tak dalej aż do Koszteli, która ma wartość 4.
Jeżeli z jakichś przyczyn chcemy przypisać wartości ręcznie, nie ma problemu:
Enum Pojazd
Samochod = 10
Autobus = 20
Samolot = 30
Balon = 40
Rower = 50
Deskorolka = 60
End Enum
Tutaj wymusiliśmy numerację elementów typu Pojazd - dopóki wartości będą unikalne, nie ma problemu.
Numerację można też wymusić w nieco inny sposób:
Enum Naczynie
Kubek = 1
Miska
Szklanka
Talerz
Wiadro
End Enum
W przykładzie powyżej numeracja elementów rozpocznie się od jedynki (zamiast od zera jak w przykładzie z jabłkiem), kolejne elementy będą dostawać numery 2, 3, 4 i 5.
Można jeszcze inaczej:
Enum Kolor
Bialy
Czarny
Brazowy
Niebieski = 10
Zielony
Czerwony
Zolty
End Enum
W tym przykładzie kolory Biały, Czarny i Brązowy są ponumerowane 0, 1 i 2, natomiast Niebieski i kolejne dostaną numery 10, 11, 12 i 13.
No dobrze. Wiemy jak utworzyć typ wyliczany, teraz spójrzmy jak go używać:
Enum Jablko
Antonowka
Malinowka
Reneta
Lobo
Kosztela
End Enum
Dim j as Jablko
j = Antonowka
Zauważmy, że po wpisaniu znaku równości podpowiadacz (zwany po naszemu IntelliSense) wyświetlił nam pełną listę elementów typu Jablko, dzięki czemu możemy wybrać interesujący nas element z listy.
A po co w ogóle stosuje się typy wyliczane, skoro można zamiast nich użyć stałych? Zamiast definiować typ wyliczany Jablko, wystarczyłoby przecież zdefiniować:
Const ANTONOWKA = 0, MALINOWKA = 1, RENETA = 2, LOBO = 3, KOSZTELA = 4
Jednak w takiej sytuacji zmuszeni bylibyśmy pamiętać nazwy stałych, podczas gdy mając zdefiniowany typ wyliczany wystarczy zapamiętać nazwę tego typu (Jablko), a IntelliSense podpowie nam, jakie wartości są dopuszczalne.
Jedna istotna rzecz, o której czasem się zapomina: zmienna typu wyliczanego jest tak naprawdę zmienną typu Integer, a więc można do niej podstawić dowolną wartość całkowitą, nawet taką, która nie ma swojego odpowiednika wśród elementów typu wyliczanego. Przykład:
Enum Jablko
Antonowka
Malinowka
Reneta
Lobo
Kosztela
End Enum
Dim j as Jablko
j = 7
Podstawiliśmy siódemkę a kompilator (ani interpreter) ani kwiknął - jest to całkiem legalna operacja. Jak więc tego uniknąć?
Zazwyczaj stosuje się prosty trick umożliwiający walidację wartości typu wyliczanego:
Enum Jablko
[_Pierwszy]
Antonowka
Malinowka
Reneta
Lobo
Kosztela
[_Ostatni]
End Enum
Function Walidacja(v As Jablko) As Boolean
If (v > Jablko.[_Pierwszy] And v < Jablko.[_Ostatni]) Then
Walidacja = True
Else
Walidacja = False
End If
End Function
Po pierwsze zaważmy, że elementy [_Pierwszy] i [_Ostatni] nie pojawiają się na liście IntelliSense, a to za sprawą podkreślnika na początku ich nazw. Po drugie, ważne żeby [_Pierwszy] był zawsze na początku listy a [_Ostatni] na jej końcu, dzięki czemu funkcja Walidacja zadziała poprawnie.
Na koniec jeszcze słówko o łączeniu atrybutów. Załóżmy, że tworzymy typ wyliczany definiujący elementy do odfiltrowania przy szukaniu samochodu. Jedni będą szukać po roczniku i kolorze, inni po marce i przebiegu, jeszcze inni po rodzaju paliwa, ilości drzwi i kształcie nadwozia.
Przyda się nam tutaj następujący typ wyliczany:
Enum FiltrAuta
IloscDrzwi = 1
Przebieg = 2
Marka = 4
Model = 8
RodzajPaliwa = 16
TypNadwozia = 32
RodzajSkrzyniBiegow = 64
Kolor = 128
Rocznik = 256
End Enum
Jak widać, poszczególne elementy tego typu wyliczanego mają wartości będące całkowitymi potęgami dwójki. Dzięki temu każdy z nich w reprezentacji binarnej ma "zapalony" tylko jeden bit, co pozwala na łączenie tych atrybutów:
Dim a As FiltrAuta
a = RodzajPaliwa Or Model
W powyższym przykładzie zmienna a przyjmie wartość 24 (operacja bitowa OR na tych dwóch wartościach "zapaliła" bity trzeci i czwarty, 2^3 + 2^4 = 24)
A jak sprawdzić czy zmienna zawiera daną opcję? Ano, trzeba zastosować operator And:
If a And FiltrAuta.RodzajSkrzyniBiegow Then
' tutaj blok kodu wykonujący się jeżeli do filtra wybrano rodzaj skrzyni biegów
End If
W ten sposób możemy utworzyć typ wyliczany z maksimum 32 elementami (ponieważ typ Integer kończy się na 2 ^ 31) - jeżeli potrzebujemy więcej elementów, trzeba kombinować dookoła.
To chyba wszystko w temacie typów wyliczanych - na koniec bardzo zachęcam do ich stosowania, ponieważ sprawiają, że kod jest bardziej przejrzysty, a także ułatwiają trzymanie atrybutów w ryzach.
Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]
Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.