Kolekcja jest zbiorem obiektów tego samego typu. W Excelu mamy m.in. kolekcję skoroszytów, arkuszy, komórek, wykresów, tabel przestawnych czy kształtów. Z poziomu VBA możemy alternatywnie skorzystać z obiektu słownika. W tym tekście opiszę na czym polega przewaga słownika nad kolekcją.
Krótko o słowniku
Słownik jest lekkim i bardzo wydajnym obiektem wchodzącym w skład biblioteki Microsoft Scripting Runtime. Oznacza to, że jeżeli chcemy mieć dostęp do właściwości i metod tego obiektu – musimy dodać odpowiednią referencję w edytorze VBA.

Jak zrozumieć obiekt słownika? Można go przyrównać do słownika języka obcego. Mamy pewien zwrot w języku ojczystym i przypisany mu odpowiednik w języku obcym. Analogicznie jest w obiekcie Scripting.Dictionary – przechowujemy w nim pary słów. Pierwsze z nich jest unikatowym kluczem, zaś drugie – przechowywaną informacją.
1 2 3 4 5 6 7 8 9 10 11 12 |
Sub TworzenieSlownika() Dim objDict As Object Set objDict = CreateObject("Scripting.Dictionary") objDict.Add "JK1", "Jan Kowalski" objDict.Add "AN1", "Anna Nowak" 'Wyświetlenie wartości MsgBox objDict("JK1") End Sub |
Słownik vs. kolekcja
Tytuł tego wpisu jest bardzo tendencyjny, ale jest to zabieg zamierzony. Osobiście preferuję korzystanie ze słownika nad korzystaniem z kolekcji, co znalazło swoje potwierdzenie w funkcji służącej do wydobycia unikatów z zakresu komórek.
Prześledźmy zatem, gdzie tkwi przewaga słownika nad kolekcją.
Metoda Exists
Metoda Exists pozwala szybko i łatwo sprawdzić czy dany wpis znajduje się w słowniku.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Sub MetodaExists() Dim objDict As Object Set objDict = CreateObject("Scripting.Dictionary") objDict.Add "A", "Produkt A" If objDict.Exists("A") Then MsgBox "Produkt jest w słowniku." Else MsgBox "Produkt nie istnieje." End If End Sub |
W przypadku kolekcji musimy kombinować. Jak to zrobić?
Pierwszą opcją jest przejście w pętli po wszystkich elementach kolekcji i porównanie każdego z nich z szukanym wzorcem. Możemy się łatwo domyślić, że ten sposób nie należy do najbardziej efektywnych.
Drugim sposobem, stosowanym przez osoby z większą wiedzą, jest próba odwołania się do konkretnego elementu kolekcji za pomocą zmiennej. Linię tą poprzedza instrukcja 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 szukanego wpisu nie ma w kolekcji.
Reasumując. W przypadku kolekcji musimy działać w okrężny sposób.
Lista kluczy
Dodając element do kolekcji lub słownika zawsze określamy dwa parametry. Pierwszym 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ść, którą chcemy dodać.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Sub ListaKluczy() Dim objSlownik As Object Dim avKlucze As Variant Dim i As Integer Set objSlownik = CreateObject("Scripting.Dictionary") objSlownik.Add "JK1", "Jan Kowalski" objSlownik.Add "AN1", "Anna Nowak" avKlucze = objSlownik.Keys For i = LBound(avKlucze) To UBound(avKlucze) Debug.Print avKlucze(i) Next i End Sub |
W przypadku kolekcji możemy otrzymać tylko listę elementów. Nie uzyskamy listy unikatowych kluczy – nawet przechodząc w pętli po wszystkich elementach. W przypadku słownika otrzymujemy dostęp zarówno do wartości jak i kluczy.
Tablice Keys i Items
Wiemy już, że stosując kolekcję, nie mamy dostępu do kluczy.
A jak się sprawa ma z dostępem do wartości? Chcąc sczytać do arkusza wszystkie elementy kolekcji – musimy to zrobić w pętli.
W przypadku słownika zarówno klucze jak i wartości są przechowywane w osobnych tablicach Keys i Items. Jest to dużym ułatwieniem, ponieważ taką tablicę możemy wkleić do arkusza za pomocą jednej linijki kodu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Sub TabliceKeysItems() Dim objSlownik As Object Dim avKlucze As Variant Dim avWartosci As Variant Dim i As Integer Set objSlownik = CreateObject("Scripting.Dictionary") objSlownik.Add "K001", "Krzesło" objSlownik.Add "T002", "Stół" avKlucze = objSlownik.Keys avWartosci = objSlownik.Items For i = LBound(avKlucze) To UBound(avKlucze) Debug.Print avKlucze(i) & " - " & avWartosci (i) Next i End Sub |
Zmiana wartości klucza
W przypadku słownika możemy w prosty sposób zmienić wartość klucza. W przypadku kolekcji należałoby usunąć element i dodać go ponownie z nowym kluczem.
1 2 3 4 5 6 7 8 9 10 11 |
Sub ZmianaWartosci() Dim objSlownik As Object Set objSlownik = CreateObject("Scripting.Dictionary") objSlownik.Add "Kowalski", "Pracownik" objSlownik("Kowalski") = "Manager" MsgBox objSlownik("Kowalski") End Sub |
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.
1 2 3 4 5 6 7 8 9 10 11 |
Sub DowolnyTypKlucza() Dim objSlownik As Object Set objSlownik = CreateObject("Scripting.Dictionary") objSlownik.Add 101, "Produkt X" objSlownik.Add #01/01/2025#, "Wydarzenie" MsgBox objSlownik(101) End Sub |
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ą znaków. Przykładowo możemy dodać do słownika trzy wartości z takimi kluczami: „Jan Kowalski”, „JAN KOWALSKI”, „jan kowalski”.
W przypadku kolekcji wielkość liter nie jest rozróżniana, więc moglibyśmy dodać do zbioru tylko jedną wartość.
Co więcej, w przypadku słownika możemy ustawić, aby wielkość liter nie była rozróżniana. Odbywa się to poprzez zmianę z trybu binarnego na tekstowy dla właściwości CompareMode. Mamy więc tutaj pełną elastyczność.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Sub WielkoscLiter() Dim objSlownik As Object Set objSlownik = CreateObject("Scripting.Dictionary") objSlownik .CompareMode = vbTextCompare objSlownik .Add "JAN", "Osoba A" If objSlownik.Exists("jan") Then MsgBox "Znaleziono." Else MsgBox "Nie znaleziono." End If End Sub |
Metoda RemoveAll
Słownik posiada metodę RemoveAll, która pozwala jednym poleceniem wyczyścić całą zawartość słownika.
1 2 3 4 5 6 7 8 9 10 11 |
Sub CzyszczenieSlownika() Dim objSlownik As Object Set objSlownik = CreateObject("Scripting.Dictionary") objSlownik.Add "Element1", "A" objSlownik.Add "Element2", "B" objSlownik.RemoveAll MsgBox "Słownik wyczyszczony." End Sub |
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ą.
1 2 3 4 5 6 7 8 9 |
Sub DodawanieElementu() Dim objSlownik As Object Set objSlownik = CreateObject("Scripting.Dictionary") objSlownik("K001") = "Krzesło" objSlownik.Add "T002", "Stół" End Sub |
Ten sposób jest jednak mniej intuicyjny od metody Add i lepiej potraktować go jako ciekawostkę.
Podsumowanie
Słownik Dictionary w VBA oferuje znacznie większą elastyczność i funkcjonalność w porównaniu do kolekcji Collection. Słownik to wszechstronne narzędzie, które czyni kod bardziej czytelnym, elastycznym i efektywnym. Jeśli w VBA często operujesz na danych i zależy Ci na szybkości oraz prostocie, warto rozważyć użycie słownika zamiast klasycznej kolekcji.