Przygotowując formularz do obsługi magazynu potrzebowałem wygenerować i umieścić w kontrolce ListBox listę niepowtarzających się elementów pobieranych z komórek jednego ze skoroszytów. Mam tam listę wszystkich producentów oraz waluty, w jakich rozliczane są zakupy. Poniżej fragment wspomnianego skoroszytu (przechowywane są w nim ustawienia aplikacji). Ponieważ jest to „żywy organizm” postanowiłem poukrywać informacje, które niekoniecznie są nam potrzebne.

To, co chciałem zrobić to wyświetlić w kontrolce ListBox listę (bez powtórzeń) używanych walut. Mniej więcej tak jak na rysunku poniżej.

Jak to w Excelu, problem można rozwiązać na kilka sposobów. Osobiście, z reguły, wykorzystuję kolekcje (zwane także zbiorami). Głównie dlatego, że rozwiązanie to wydaje mi się najprostsze.
Czym zatem jest kolekcja ?
Pomijam fachowe definicje – jeżeli takich szukasz bez problemów znajdziesz je w książkach o programowaniu. Z praktycznego punktu widzenia kolekcja, podobnie jak tablica, jest zmienną „w której” możesz przechowywać wiele informacji na raz.
W przeciwieństwie do tablic nie jesteś ograniczony tylko do jednego typu danych, nie musisz także deklarować rozmiaru kolekcji. Pamięć jest rezerwowana dynamicznie, za każdym razem kiedy dodajesz nowy element do kolekcji. Warto także dodać, że elementy w kolekcji numerowane są od „1”, w przeciwieństwie do tablic gdzie (o ile nie określisz inaczej) elementy numerowane są od „0”.
Kolekcje posiadają cztery metody – Add, Item, Remove oraz Count. Nazwy metod wyjaśniają w zasadzie ich działanie. W przypadku, o którym piszę interesuje nasz metoda Add.
Składnia metody Add jest następująca:
NazwaKolekcji.Add Item [, Key] [, Before,] [, After], gdzie Item to oczywiście element dodawany do kolekcji, Key(klucz) to coś na kształt identyfikatora, przypisanego do elementu, pozwalającego w bardziej przyjazny sposób odwoływać się do elementu. Before i After umożliwiają precyzyjne umieszczenie elementu wśród innych elementów znajdujących się już w kolekcji.
Kluczowe znaczenie w omawianym przypadku ma argument KEY (klucz). Kiedy korzystasz z tego argumentu, dla każdego dodawanego elementu musisz użyć INNEGO klucza. Jeżeli więc jako klucza użyjesz wartości dodawanego elementu (np. kiedy dodawany element to ciąg „marcin”, kluczem byłby także ciąg tekstowy„marcin”) to metoda zaakceptuje tylko niepowtarzające się elementy. W przypadku powtórzeń zwróci błąd, taki jak na rysunku poniżej.

Oczywiście nie chcemy, aby wykonywanie kodu przerwane zostało przez błędy. Dlatego przed rozpoczęciem wypełniania kolekcji dobrze jest chwilowo wyłączyć obsługę błędów i włączyć ja ponownie po zakończeniu.
Poniżej kod, jaki zastosowałem w swoim przykładzie.
Private Sub UserForm_Initialize()Dim WalutyBezPowtorzen As Collection ' deklaracja zmiennej użytej później jako kolekcja
Dim waluty As Range ' zakres komórek z nazwami walut
Dim waluta As Variant ' zmienna pomocnicza, użyta w pętli wypełniającej ListBox
Set WalutyBezPowtorzen = New Collection ' inicjowanie kolekcji
' wyłączam obsługę błędów, aby pomijać błędy wygenerowane w przypadku dodania powtarzającej się wartości
On Error Resume Next
' dla każdej komórki(symbolu) waluty w nazwanym zakresie
For Each waluty In Range("wksUstawienia_waluty")
' dodaję element do kolekcji.
WalutyBezPowtorzen.Add waluty.Value, waluty.Value
Next waluty
On Error GoTo 0 ' wyłączam obsługę błędów
' Wypelniam listox wartosciami przechowywanymi w kolekcji
For Each waluta In WalutyBezPowtorzen
Me.CboxWaluty.AddItem waluta
Next waluta
End sub
Chciałbym jeszcze zwrócić Twoją uwagę na fakt, że argument KEY (klucz) metody Add MUSI być ciągiem tekstowym. W moim przypadku waluty są przechowywane jako ciągi tekstowe, więc wszystko zadziałało poprawnie. Gdybyś jednak nie miał pewności, lub po prostu chciał całość zapisać poprawnie (na wszelki wypadek), tak jak ja to później zrobię, mógłbyś wykorzystać funkcję CStr, zamieniającą podany argument na ciąg tekstowy.
Zamiast
WalutyBezPowtorzen.Add waluty.Value, waluty.Value
możesz użyć więc
WalutyBezPowtorzen.Add waluty.Value, CStr(waluty.Value)
i zapomnieć o problemie.
Oczywiście w moim przypadku lista elementów do „odfiltrowania” była niewielka. Śmiało jednak możesz wyobrazić sobie sytuacje i wykorzystać kolekcje do tworzenia list niepowtarzających się elementów w bardziej złożonych przypadkach.

{ 3 comments… read them below or add one }
Witam,
W chwili obecnej buduję również skoroszyt który będzie magazynem.
Nie znam się na VBA i dlatego chciałbym zaproponować aby ExcelBlog stworzył budowę takiej aplikacji Krok po Kroku
Przy budowie czegoś co jest potrzebne szybciej można sie czegoś nauczyć
Pozdrawiam
A czy dałoby się pominąć niektóre wartości? Np żeby w zależności od producenta wyświetlało się Euro i dolarach, a w innym przypadku funtach i euro?
@m00ka
Wszystko (no prawie) da się zrobić. Kwestia motywacji
Marcin