Filtrowanie ListBox’a część 2

by Marcin

Pomyślałem sobie, że skoro funkcja filter, o której pisałem, działa szybko, można spróbować odfiltrować z grubsza przy jej pomocy to, co na pewno nie pasuje do podanych kryteriów, a następnie przefiltrować resztę raz jeszcze, dokładniej.

lista_nazwisk2 to przefiltrowana wstępnie funkcją FILTER tablica z nazwiskami

For i = UBound(lista_nazwisk2) To 0 Step -1 ' dla każdego nazwiska w tablicy, zaczynając od ostatniej pozycji

' jeżeli nazwisko nie pasuje do wzorca

  If Not UCase(lista_nazwisk2(i)) Like UCase(Me.TextBox2.Value) & "*" Then

     ' przesuwam wszystkie elementy lezace nizej o jedna pozycje do góry (zastępując niepasujący element)

     For licznik = i To UBound(lista_nazwisk2) - 1

        lista_nazwisk2(licznik) = lista_nazwisk2(licznik + 1)

     Next licznik

     ' i usuwam ostatni element (zmieniam wymiar tablicy)

     ReDim Preserve lista_nazwisk2(UBound(lista_nazwisk2) - 1)

End If

Next i

Na koniec sprawdziłem jeszcze tylko czy takie wstępne filtrowanie ma w ogóle sens. Przecież można po prostu przy pomocy pętli od razu przefiltrować wszystkie nazwiska.

Zmierzyłem czas wykonywania procedury z wstępnym filtrowaniem i bez niego. W przypadku listy 5600 nazwisk czas wylistowania z filtrowaniem wstępnym, po wpisaniu przypadkowej litery, wyniósł 0,05 sekundy. Bez wstępnego przefiltrowania – 0,22. Nieco bardziej konkretnie – dla litery „s” (511 nazwisk zaczynających się tą literą na mojej liście) czas wykonania wyniósł odpowiednio 0,38 i 1,23 sekundy. Prawie sekunda róznicy. Niby niewiele, ale w przypadku odświeżania ListBox’a jest to opóźnienie bardziej niż zauważalne. W przypadku róznych liter są to oczywiście różne wyniki (w zależności od tego jak wielka jest wstępnie odfiltrowana tablica) zawsze jednak jest to różnica na korzyść wstępnego przefiltrowania. Różnica ta oczywiście maleje w miarę wpisywania kolejnych liter i zawężania listy.

Na koniec, tytułem eksperymentu, zmierzyłem jeszcze czas wykonania innej procedury, która po prostu wstawia listę bezpośrednio do ListBox’a, a następnie usuwa z niego wszystkie elementy, które nie pasują do wzorca.


Private Sub TextBox1_Change()

Dim lista_nazwisk As Variant

Dim licznik As IntegerWith Worksheets("Nazwiska") ' nazwiska znajdują się w skoroszycie "Nazwiska"

   ' pobieram do tablicy listę nazwisk z arkusza.

   lista_nazwisk = Range(Range("C4"), Range("C4").End(xlDown)).Value

End With

Me.ListBox1.List = lista_nazwisk ' wypelniam ListBox’a wartościami

For licznik = Me.ListBox1.ListCount - 1 To 0 Step -1

   If Not UCase(Me.ListBox1.List(licznik)) Like UCase(Me.TextBox3.Value) & "*" Then

      Me.ListBox1.RemoveItem licznik

   End If

Next licznik

End Sub

W tym przypadku, dla wspomnianej już litery „s” czas odfiltrowania listy wyniósł 0,62 sekundy.

Przygotowując jednak projekt dla jednego z klientów chciałem przefiltrować listbox’a z kilkoma kolumnami. Wkrótce postaram się napisać o tym jaką metodę filtrowania wybrałem do projektu, dlaczego oraz jaki jest efekt.

Marcin

{ 5 comments… read them below or add one }

Karolina

Jest już gdzieś to filtrowanie listboxa z kilkoma kolumnami?? Bardzo mnie interesuje jak to zrobiłeś 🙂

Maciej

Rownież czekam niecierpliwie na wspomniane rozwiązanie 🙂

Maciek

Tez sie nie moge doczekac tego rozwiazania. Mam nadzieje, ze wkrotce sie pojawi!

Krzysztof

W ostatniej procedurze zauważyłem usterkę – brak instrukcji With rozpoczynającej pętlę, jest natomiast jej koniec End With

Keso

Zapewne do tego i wcześniejszego artykułu już nie wrócisz? Wielka szkoda!
Zapewniałeś w ostatnim zdaniu powyższego tekstu, że się postarasz …
Gdybyś jednak miał (moralny) przymus powrotu do przeszłości, chętnie przeczytałbym wyjaśnienia dlaczego w kolejnych kodach pojawiają się obiekty TextBox2, TextBox3 – czy tworzysz kolejne TextBoxy z obsługą własnych zdarzeń w tym samym UserForm1? Nie jestem aż tak leniwy, bym nie miał woli dopisać do wcześniejszego formularza dwóch kolejnych TextBoxów, ale artykuł byłby pełniejszy gdybyś dorzucił jakąś sugestię, inaczej dla mniej wyrobionego czytelnika przykłady pozostaną mało czytelne.
Pozdrawiam
Keso

Leave a Comment

Previous post:

Next post: