FM20 – Listbox
ListBox to kontrolka ActiveX z zestawu biblioteki FM20 (standardowy przybornik) dla kompilacji Office 32/64 bit.
Podstawowa kontrolka przedstawiona w formie listy wyboru. Przez większość używana jako Lista pojedyncza, Dwie listy z możliwością przekazywania wybranych danych, pod-lista innej listy. Spróbujemy sobie omówić większość zagadnień związanych z tą kontrolką poniżej.
Lista pojedyncza: Kontrolka posiada parametr .ListStyle definiujący czy elementy listy mają być zaznaczone przez wskazanie czy też w formie zaznaczania przez ikonkę. Pokrewnym parametrem jest .MultiSelect, który w pierwszym przypadku pozwala na zaznaczenie wielu elementów z [Ctrl] lub [Shiftem] dla zakresu, a w drugim zamienia ikonkę radio (kropka w kołeczku) na Checka (kwadracik).
Ładowanie danych do kontrolki. Przygotowałem arkusz z dowolnymi danymi i dodaje te dane do ListBox pokazując 5 możliwych opcje prezentacji z zaznaczeniem. W formie umieszczam Kontrolkę listbox i dwa comboboxy, do których importuje nazwy kodowe ustawienia listboxa, a po ich wybraniu przypisuje indeks odpowiadający konkretnej opcji:
Private Sub UserForm_Initialize()
ComboBox1.AddItem "fmListStylePlain" 'Wybór przez zaznaczenie pozycji
ComboBox1.AddItem "fmListStyleOption" 'Wybór przez zaznaczenie ikony radio lub checka
ComboBox1.ListIndex = 0
ComboBox2.AddItem "fmMultiSelectSingle" 'Wybieranie tylko jednej pozycji
ComboBox2.AddItem "fmMultiSelectMulti" 'Możliwość wyboru wielu z Ctrl
ComboBox2.AddItem "fmMultiSelectExtended" 'Możliwość zaznaczenia z Shiftem i Ctrl
ComboBox2.ListIndex = 0
Dim x As Integer 'deklaracja zmiennych (wystarczy w tym przypadku integer)
For x = 1 To 10
ListBox1.AddItem Cells(x, "a") 'dodanie pozycji arkusza do kontrolki
Next
ListBox1.ListIndex = 0 'ustawianie kontrolki na pierwszą pozycję.
End Sub
Private Sub ComboBox1_Change() 'Przekazanie nazw kodowych stylu
ListBox1.ListStyle = ComboBox1.ListIndex 'ładowane dane do Combo mają swoją kolejność czyli indeks
End Sub
Private Sub ComboBox2_Change() 'Przekazanie nazw kodowych multi wybierania
ListBox1.MultiSelect = ComboBox2.ListIndex
End Sub
Zmodyfikujmy formę, tak aby można było dopisać jakąś wartość na listę i również z niej skasować wybraną pozycję lub wiele pozycji (wybierając styl kontrolki). W szkoleniu o ComboBoxie pokazałem jak dodać z Inputboxa, czyli okna generowanego kodem, tym razem posłużę się polem tekstowym Textbox. Skutek będzie ten sam. Kwestię sortowania i sprawdzenia czy jest już na liście sobie tym razem odpuszczamy.
Private Sub CommandButton1_Click() 'dodaje pozycje jeśli coś wpisano i czyszczę kontrolkę textbox
If Len(TextBox1.Text) > 0 Then ListBox1.AddItem TextBox1.Text: TextBox1.Text = ""
End Sub
Private Sub CommandButton2_Click()
If ListBox1.ListCount > 0 Then 'pozwalam usunąć pozycję jeśli jakieś są na liście
Dim czy, x%
If ListBox1.MultiSelect = fmMultiSelectSingle Then 'dla pojedynczo zaznaczonego
czy = MsgBox("Czy usunąć pozycję " & Chr(34) & ListBox1.Text & Chr(34), _
vbQuestion + vbYesNo + vbDefaultButton2, "Usuwanie pozycji z listy")
If czy = vbYes Then ListBox1.RemoveItem (ListBox1.ListIndex)
Else 'dla kilku zaznaczonych pozycji
czy = MsgBox("Czy usunąć wszystkie zaznaczone pozycje?", _
vbQuestion + vbYesNo + vbDefaultButton2, "Usuwanie pozycji z listy")
If czy = vbYes Then 'podobnie jak pow: jeśli wyrażono zgodę
For x = ListBox1.ListCount - 1 To 0 Step -1 'pętla wsteczna
If ListBox1.Selected(x) = True Then _
ListBox1.RemoveItem (x)
Next
End If
End If
End If
End Sub
Dwie listy z możliwością przekazywania wybranych danych. Na początek tworzę nową formę którą wyposażę w dwie listboxy oraz cztery przyciski CommandButton. Rolą ich będzie przekazywanie danych z listy na listę. Z pow kodu już wiemy jak wczytać dane, to też pierwszą listę będziemy uważać za napełnioną, druga zaś będzie pusta. Przyciski będą miały rolę kopii lub przeniesienia pojedynczego oraz całości danych.
Sterowanie przyciskiem [->] a [>>] jest takie same, z tą różnicą ze w pętli opuszczamy warunek po zaznaczonych rekordach co zaznaczę w kodzie. Odwrotny kierunek to zmiana nazw list i przypisania do procedur odpowiednich przycisków:
Private Sub UserForm_Initialize()
Dim x% 'deklaracja zmiennych (wystarczy w tym przypadku integer)
Dim max_r&: max_r = Cells(Rows.Count, "a").End(xlUp).Row
For x = 1 To max_r 'wszystkie pozycje od 1 do odst. z arkusza do kontrolki
ListBox1.AddItem Cells(x, "a") 'dodanie pozycji arkusza do kontrolki
Next
ListBox1.MultiSelect = fmMultiSelectExtended 'ustawiamy na wielo-zaznaczanie
ListBox1.ListIndex = 0 'ustawianie kontrolki na pierwszą pozycję.
End Sub
Private Sub CommandButton1_Click()
If ListBox1.ListCount > 0 Then
Dim x%
For x = ListBox1.ListCount - 1 To 0 Step -1 'pętla wsteczna
If ListBox1.Selected(x) = True Then 'warunek: realizuj dla zaznaczonych do opuszczenia w [>>]
ListBox2.AddItem ListBox1.List(x), 0 'dodaj zachowując porządek
If CheckBox1.Value = True Then ListBox1.RemoveItem (x)
End If 'koniec warunku j.w.
Next
End If
End Sub
Pod-lista innej listy czyli zależność wyboru jednej pozycji z pozycjami doń przypisanymi (jeden do wielu). Dla przykładu pobrałem 2 kolumnową listę firm i potem marek samochodowych produkujących przez te firmy aby zaprezentować mechanizm podlisty. Kolumn może być wiele ale aby opisać mechanizm wystarczą dwie. Załóżmy że baza ta jest posortowana i bez dubli. Budujemy formę z dwoma ListBoxami osadzonymi blisko siebie:
W procedurze uruchomieniowej wpisujemy kod, tak aby dodawał do pierwszej kontrolki listę bez dubli, powołując się na już dodany rekord. Jeśli takiej treści nie było to powiększamy listę w pętli. Listę główną podłączamy pod procedurę kliknięcia myszą, ponieważ nią inicjujemy zmianę zaznaczenia. Kliknięcie na rekord powoduje każdorazowe wymazanie danych z listy nr 2 i napełnienie jej pozycjami kol B zgodnie z nazwą pierwszej kolumny A równej zaznaczonej pozycji kontrolki:
Private Sub UserForm_Initialize()
Dim x%, max_r&: max_r = Cells(Rows.Count, "a").End(xlUp).Row
For x = 1 To max_r
If ListBox1.ListCount = 0 Then
ListBox1.AddItem Cells(x, "a") 'dodanie pierwszej pozycji arkusza do kontrolki
Else
If ListBox1.List(ListBox1.ListCount - 1) <> Cells(x, "a") Then ListBox1.AddItem Cells(x, "a")
End If
Next
ListBox1.MultiSelect = fmMultiSelectSingle 'jedno zaznaczenie
ListBox1.ListIndex = 0 'ustawianie kontrolki na pierwszą pozycję.
Call ListBox1_Click
End Sub
Private Sub ListBox1_Click()
Dim x%, max_r&: max_r = Cells(Rows.Count, "a").End(xlUp).Row
ListBox2.Clear 'czyszczenie kontrolki
For x = 1 To max_r
If ListBox1.Text = Cells(x, "a") Then
ListBox2.AddItem Cells(x, "b") 'dodanie pozycji jeśli w arkuszu kol A = zaznaczonej pozycji
'jeśli 1wszy znak komórki z arkusza jest większy niż zaznaczona pozycja to wyjdź z pętli
If Asc(Mid(ListBox1.Text, 1, 1)) > Asc(Mid(Cells(x, "a"), 1, 1)) Then Exit For
End If
Next
End Sub
Jeśli uważasz że pokazane materiały są godne polecenia – podziel się tą wiadomością z innymi pozostawiając odnośnik to tego materiału.
(c) Shon Oskar – http://VBATools.pl
Wszelkie prawa zastrzeżone. Żadna część ani całość tego artykułu nie może być powielana ani publikowana bez zgody autora.