VBATools

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).

Obrazek

Ł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.

Obrazek
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.

Obrazek

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:

Obrazek

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.