Tytuł tego wpisu jest tendencyjny ponieważ zdradza moje preferencje jeżeli chodzi o korzystanie z pewnych funkcjonalności w VBA. Prześledźmy zatem, gdzie tkwią największe różnice pomiędzy wbudowanym obiektem kolekcji, a obiektem Dictionary wchodzącym w skład biblioteki MicrosoftScriptingRuntime.
Metoda Exists
Istnienie metody Exists w słowniku pozwala szybko i prosto sprawdzić czy dana wartość znajduje się w słowniku.
W przypadku kolekcji musimy kombinować. Pierwszym rozwiązaniem jest przejście w pętli po wszystkich elementach kolekcji i porównanie każdego z nich z szukanym wzorcem. Drugim rozwiązaniem (stosowanym przez osoby bardziej zaawansowane w temacie) jest próba odwołania się za pomocą zmiennej do konkretnego elementu kolekcji. Linijkę tą poprzedza instrukcja obsługi błędów On Error Resume Next na wypadek gdyby szukany element nie znajdował się w kolekcji. W wyniku sprawdzamy czy wystąpił błąd – jeżeli tak, wówczas mamy pewność, że szukany element nie znajduje się w kolekcji.
Reasumując. W przypadku kolekcji jest to trochę łopatologiczne działanie.
Lista Kluczy
Dodając element do kolekcji lub słownika zawsze określamy dwa parametry. Pierwszym z nich jest unikatowy klucz tzw. Key, po którym możemy się odwołać do tego elementu w kodzie makra. Drugim jest Item czyli obiekt lub konkretna wartość jaką chcemy dodać.
W przypadku kolekcji jesteśmy w stanie otrzymać tylko wartości elementów – nie możemy natomiast otrzymać listy unikatowych kluczy, nawet przechodząc w pętli po wszystkich elementach. W przypadku słownika uzyskujemy bezproblemowy dostęp zarówno do wartości jak i kluczy.
Tablice Keys + Items
Ten punkt jest nieco powiązany z poprzednim.
Wiemy już, że za pomocą kolekcji nie mamy dostępu do kluczy. Chcąc sczytać do komórek arkusza tablicę wszystkich wartości, musimy przejść w pętli po wszystkich elementach kolekcji i sczytać je jeden po drugim do arkusza (jest to rozwiązanie czasochłonne i odradzane).
Inna opcja polega na tym, aby przejść w pętli po wszystkich elementach i dodać każdą wartość do tablicy, a potem dopiero sczytać całą tablicę do zakresu komórek w arkuszu. Jest to, więc działanie, które wymaga podjęcia dużego wysiłku i sporej ilości kodu.
W przypadku słownika zarówno klucze jak i wartości są przechowywane w osobnych tablicach Keys i Items co jest rewelacyjnym rozwiązaniem bowiem tablicę taką można wkleić do arkusza za pomocą jednej linijki kodu.
Zmiana Wartości Klucza
W przypadku słownika można w bardzo prosty sposób zmienić wartość klucza np. objDict.Key(„Jan Kowalski”) = „J.Kowalski1”. W przypadku kolekcji należałoby usunąć element i dodać go ponownie z nowym kluczem.
Dowolny Typ Klucza
W przypadku słownika nie jesteśmy ograniczani do wprowadzania kluczy jako tekstu. Klucz jest obowiązkowy i musi być unikatem, ale typ danych jest bez znaczenia. Może to być tekst, liczba, wartość logiczna. W przypadku kolekcji obowiązkowo musi to być tekst.
Wielkość Liter
W nawiązaniu do poprzedniego punktu. Słownik posiada właściwość CompareMode, która pozwala na wprowadzenie rozróżnienia wielkości liter dla kluczy (jest to ustawienie domyślne).
Oznacza to, że możemy, jako kluczy używać takich samych zwrotów różniących się jedynie wielkością liter. Przykładowo możemy dodać do słownika trzy wartości z takimi kluczami jak: „Jan Kowalski”, „JAN KOWALSKI”, „jan kowalski”.
W przypadku kolekcji wielkość liter nie jest rozróżniana i tutaj moglibyśmy dodać do zbioru tylko jedną wartość.
Oczywiście w przypadku słownika także możemy ustalić, aby wielkość liter nie była rozróżniana zmieniając tryb binarny na tekstowy dla właściwości CompareMode. Pełna elastyczność.
Metoda RemoveAll
Słownik posiada metodę RemoveAll, która pozwala jednym poleceniem wyczyścić całą zawartość słownika. W przypadku kolekcji, aby wykonać podobną operację musielibyśmy usunąć każdy element w pętli.
Dodawanie Elementów
Słownik pozwala nam na dodawanie elementów nie tylko za pomocą standardowej metody Add, ale także w inny sposób np. objDict.Item(„J.Kowalski2”) = „Jan Kowalski” gdzie „J.Kowalski2” jest kluczem, a „Jan Kowalski” wartością.
Ten sposób jest jednak raczej mało intuicyjny i wspomniałem o nim, jako o ciekawostce. Sam korzystam z metody Add.
Witaj,
Czy mógłbyś dołączyć jakiś mały przykład z ilustracją sposobu korzystania z tego obiektu i wymienionych metod ? Włączyłem sobie tą referencję ale niestety wywala mi błędy:
Sub DictTest()
Dim objDict As New Dictionary
objDict.Key(“aa”) = “aaa”
aa = objDict(“aa”)
End Sub
pozdrawiam
golly
znalazłem, sorry, możesz wykasować mój wpis
Sub DictTest()
Dim objDict As Dictionary
Set objDict = New Dictionary
objDict(“aa”) = “aaa”
adda = objDict(“aa”)
End Sub
Ciekawy artykuł, dla mnie będzie bardzo pomocny
Tak, ale lepiej IMO użyć tutaj późnego wiązania i zadeklarować zmienną jako Object. Oczywiście we wczesnym wiązaniu wyświetlają się podpowiedzi (Inteliisense), ale musisz mieć zaznaczoną referencję do biiblioteki :-).
czemu programik poniżej wywala błąd w linii
Kod:
c = wkS_(1).Name
?
Kod:
Sub dicts()
Dim wkS_ As Object
Dim a, b, c
Set wkS_ = CreateObject(“Scripting.Dictionary”)
wkS_.CompareMode = vbTextCompare
wkS_.Add “Arkusz1”, ActiveSheet
a = wkS_.Count
b = wkS_(“Arkusz1”).Name
c = wkS_(1).Name
End Sub
jestem zaskoczony bo dla kolekcji działa mi bez zarzutu takie odwołanie
Kod:
Sub colls()
Dim wkS_ As New Collection
Dim a, b, c
wkS_.Add ActiveSheet, “Arkusz1”
a = wkS_.Count
b = wkS_(“Arkusz1”).Name
c = wkS_(1).Name
End Sub
Z tego co widzę działa taki sposób:
oDict.Items(0).Name
Czyli tak naprawdę odwołujemy się do tablicy, która przechowuje obiekty :-).
Niestety u mnie wywala błąd ;(
“Property let procedure not defined and propoerty get procedure did not return an object”
A zmieniłeś oDict na wkS_ ?
zmieniłem
uzyskałem odpowiedź na forum:
http://www.excelforum.pl/viewtopic.php?p=163523
szkoda że nie można tego zrobić bezpośrednio, dla mnie to spora niedogodność w jednym projekcie. Ale ogólnie bardzo przydatne narzędzie.
gratuluje ciekawego artykułu
pozdrawiam
Tak. Zauważ, że to rozwiązanie jest prawie takie samo jak moje. Autor przypisuje jednoelementową tablicę obiektów do zmiennej c, a następnie wyświetla nazwę pierwszego obiektu z tablicy. Ja od razu przypisuję do zmiennej c nazwę pierwszego obiektu ze słownika.
Prawie. Tyle że tamto działa a Twoje nie 🙂
Fakt. A przy wczesnym wiązaniu działa 🙂
Sub dicts()
Dim oDict As New Dictionary
Dim a As Integer, b As String, c As String
'Set oDict = CreateObject("Scripting.Dictionary")
oDict.CompareMode = vbTextCompare
oDict.Add Key:="Arkusz1", Item:=ActiveSheet
a = oDict.Count
b = oDict("Arkusz1").Name
c = oDict.Items(0).Name
'Stop
End Sub
dziękuję
Okazuję się że różnicę robi późne wiązanie. Jak się użyje deklaracji wcześnie wiązanej to można później odwoływać się do elementu podając jego numer (by master_mix)
http://www.excelforum.pl/viewtopic.php?p=163534
No to wszystko jasne :-).
Tomek, mógłbyś wrzucić jakieś swoje zdjęcie na awatara?
ok
dzikuję za pomoc