ListBox (Listruta)
För användning av ListBox direkt i arbetsblad se Kontroller.Många delar av det som presenteras här kan appliceras på ComboBox (Kombinationsruta).
Se Import av statisk data för exempel på hur en Combobox automatisk kan fyllas med data från en databas.
Introduktion
Här presenteras ett enkelt förfaringssätt för att skapa interaktivitet mellan ett kalkylblad och en ListBox i ett formulär.
Exemplet hämtar data från nedanstående uppställning och det önskade listvärdet från ListBox placeras i samma kalkylblad:
Vi antar att det redan finns ett formulär skapat och att i formuläret finns det en ListBox.
För att koppla ListBox till ovanstående kalkylblad och cellområde behöver vissa egenskaper ändras:
Egenskaper i ListBox RowSource: Här anges från vilket kalkylblad och cellområde ListBox ska hämta data ifrån - ListBox1!A2:A10. Här kan man med fördel använda sig av namn för att ange cellområde - t ex ListBox1!Avdelning.
ControlSource: Här anges vilken cell som ska visa det valda listvärdet - ListBox1!C2. ColumnsHeads: Om vi vill ha en kolumnrubrik i Listbox så anges det här - True - Det kan enbart vara raden ovanför cellområdet för RowSource.
När formuläret visas ser det ut på följande sätt:
Programkoden för Avbryt-knappen är:
Private Sub cmbAvbryt_Click() 'Stänger formuläret och tar bort det från arbetsminnet.
Unload Me'Tar bort eventuellt listvärde från cellen C2
Worksheets("ListBox1").Range("C2").Clear
End SubFör OK-knappen ser koden ut enligt följande:
Private Sub cmbOK_Click() 'Eftersom ControlSource tar hand om det valda listvärdet
'behövs ingen kod för det.
'Felhanteringsrutin - Om inget värde är valt i ListBox så är
'ListIndex = -1.
If ListBox1.ListIndex = -1 Then
MsgBox "Inget listvärde valt!", vbCritical
Exit Sub
End If
Unload Me
End Sub
Vill vi göra samma sak som ovan men med kod istället blir det på följande sätt - Koden placeras i initieringsproceduren för formuläret:
Private Sub UserForm_Initialize()
With ListBox1
.Clear
.RowSource = "ListBox1!A2:A10"
.ControlSource = "ListBox1!C2"
.ColumnHeads = True
End With
End Sub
Ett mer flexibelt sätt är att enbart använda sig kod. Nedan demonstreras en teknik för att lägga till en månadslista:
Private Sub UserForm_Initialize()
Dim vaManad As Variant
Dim i As Integer
'Skapar en matris med månadsnamn
vaManad = Array("Januari", "Februari", "Mars", "April", _
"Maj", "Juni", "Juli", "Augusti", "September", _
"Oktober", "November", "December")
'Alternativ 1 - Lägger till listvärden
For i = LBound(vaManad) To UBound(vaManad)
ListBox1.AddItem vaManad(i)
Next i'Tillser att inget listvärde är förvalt när formuläret öppnas
ListBox1.ListIndex = -1
'Alternativ 2 - Lägger till listvärden ännu enklare!
With ListBox1
.Clear
.List = vaManad
.ListIndex = -1
End With
End Sub
Det valda månadsvärdet tilldelas cellen A2 enligt följande:
Private Sub cmbOK_Click()
If ListBox1.ListIndex = -1 Then
MsgBox "Inget listvärde valt!", vbCritical
Exit Sub
End If
'Cellen A2 i det aktiva kalkylbladet tilldelas listvärdet - ej
'indexnumret!)
Cells(2, 1).Value = ListBox1.Value
Unload Me
End Sub
Flera kolumnerHär demonstreras hur vi kan använda oss av två eller fler kolumner i en ListBox.
Manuellt kan vi ange värden för vissa egenskaper hos ListBox:
RowSource: Cellområdet omfattar här två kolumner - ListBox2!A2:B6. ColumnCount: Anger hur många kolumner som ska visas - 2 BoundColumn: Här anges från vilken kolumn i ListBox som värdet ska hämtas ifrån - 2 (=Andra kolumnen från vänster räknat i RowSource) ControlSource: Här anges vilken cell som ska visa det valda listvärdet - ListBox2!C2. ColumnsHeads: Om vi vill ha en kolumnrubrik i Listbox så anges det här - True.
Vill vi göra samma sak som ovan men med kod istället blir det på följande sätt - Koden placeras i initieringsproceduren för formuläret:
Private Sub UserForm_Initialize()
With ListBox2
.Clear
.BoundColumn = 2
.ColumnCount = 2
.ColumnHeads = True
.ControlSource = "ListBox2!C2"
.RowSource = "ListBox2!A2:B6"
End With
End Sub
Vi kan också använda oss av kod för att lägga till listvärden:
Private Sub UserForm_Initialize()
Dim vaForsta, vaAndra As Variant
Dim stLista() As String
Dim i As Integer
'Tilldelar matriserna värden. Förekomsten av "VBA"
'säkerhetsställer att matriserna är 0-baserade, dvs
'matrisindex börjar alltid på 0.
vaForsta = VBA.Array("AA", "BB", "CC")
vaAndra = VBA.Array("10", "20", "30")
'Redimensionerar den två-dimensionella matrisen "stLista".
ReDim stLista(0 To UBound(vaForsta), 0 To 1)
'Här tilldelas StLista värdena ifrån vaForsta och vaAndra,
'varje post i SLista får två värden.
For i = 0 To UBound(vaForsta)
stLista(i, 0) = vaForsta(i)
stLista(i, 1) = vaAndra(i)
Next i
With ListBox2
.Clear
.BoundColumn = 2
.ColumnCount = 2
.List = stLista
.ListIndex = -1
End With
End Sub
Välja flera listvärdenFör att tillåta att flera värden kan väljas och hämtas från en ListBox så är det egenskapen "MultiSelect" som måste ändras.
Egenskapen kan anta tre alternativa värden:
- 0 - fmMultiSelectSingle: Endast ett listvärde kan väljas (Default).
- 1 - fmMultiSelectMulti: Flera listvärden kan markeras / avmarkeras mha muspekaren och i kombination med pil- och mellanslagtangenter.
- 2 - fmMultiSelectExtended: Flera listvärden kan väljas och markeringen kan också utökas / minskas mha Skift- och Ctrl-tangenten.
Ett problem uppstår när egenskapen "MultiSelect" är angivet till 1 eller 2. Vi kan inte använda oss av egenskaperna List, ListIndex och Value för att hämta de valda värdena. Lösningen består av att använda sig av "Selected".Exemplet fortsätter att bygga på exemplet i del 2 ovan.
Private Sub cmbOK_Click()
Dim i As Integer
Dim rnCell As Range
Set rnCell = Sheets("ListBox3").Range("A1")
If ListBox3.ListIndex = -1 Then
MsgBox "Inget listvärde valt!", vbCritical
Exit Sub
End If
'Här läses / skrivs de valda listalternativen. -1 finns
'med för att ListCount ger 3 vilket blir = 4 (0 - 3).
For i = 0 To ListBox3.ListCount - 1
If ListBox3.Selected(i) Then _
rnCell.Offset(i, 0).Value = ListBox3.List(i)
Next i
Unload Me
End Sub
Kopplad ListboxHär demonstreras hur vi genom att välja ett värde i en ListBox får tillgång till en annan ListBox värden.
Private Sub UserForm_Initialize()
Dim vaLista1 As VariantvaLista1 = VBA.Array("Januari", "Februari", "Mars", "April")
With ListBox1
.Clear
.List = vaLista1
End With
End SubHär visas den kod som aktiverar olika listor i ListBox 2 utifrån valt värde i ListBox1.
Private Sub ListBox1_Click()
Dim vaJan, vaFeb, VaMar, vaApril As Variant
'Matriserna tilldelas värden
vaJan = VBA.Array("1", "2", "3")
vaFeb = VBA.Array("10", "20", "30")
VaMar = VBA.Array("100", "200", "300")
vaApril = VBA.Array("1000", "2000", "3000")
'Denna Select-sats styr vilka serier som ska visas i ListBox2.
Select Case ListBox1.Value
Case "Januari"
ListBox2.List = vaJan
Case "Februari"
ListBox2.List = vaFeb
Case "Mars"
ListBox2.List = VaMar
Case "April"
ListBox2.List = vaApril
End Select
End SubDet valda värdet från ListBox2 förs över till en cell enligt följande:
Private Sub cmbOK_Click()
Dim i As Integer
Dim rnCell As Range
Set rnCell = Sheets("ListBox4").Range("A1")
If ListBox2.ListIndex = -1 Then
MsgBox "Inget listvärde valt!", vbCritical
Exit Sub
End If
rnCell.Value = ListBox2.Value
Unload Me
End SubNedan visas den dialogruta som ligger till grund för att koppla LIstBox:
![]()
Multipel datafångstHär demonstreras en teknik för att hämta flera valda listalternativ och samtidigt placera kolumnvärdena i enstaka celler.
Vid initiering av formuläret används samma kod som för Flera kolumner (se 2:a exemplet).
Formuläret ser ut på följande sätt vid körning:
![]()
Följande kod hämtar in de valda listalternativen och placerar respektive alternativs kolumnvärden i enstaka celler:
Private Sub cmbOK_Click()
Dim i, j As Integer
Dim rnCell As Range
Set rnCell = Sheets("ListBox5").Range("A1")
If ListBox5.ListIndex = -1 Then
MsgBox "Inget listvärde valt!", vbCritical
Exit Sub
End If
j = 0
For i = 0 To ListBox5.ListCount - 1
If ListBox5.Selected(i) Then
j = j + 1'Här tilldelas cellerna värden från de valda listalternativen
'ur den två-dimensionella matrisen
rnCell.Offset(j, 0).Value = ListBox5.List(i, 0)
rnCell.Offset(j, 1).Value = ListBox5.List(i, 1)
End If
Next i
Unload Me
End Sub
Listvärden från radAtt använda sig av en eller flera kalkylbladsrader som RowSource kräver en speciell lösning. Försöker vi koppla radcellområdet manuellt visas bara den första cellens värde i Listbox.
En lösning är att använda sig av "Add Item"-metoden enligt följande:
Private Sub UserForm_Initialize()
Dim rnCell, rnOmrade As Range
Set rnOmrade = Worksheets("Listbox6").Range("B2:G2")
For Each rnCell In rnOmrade
ListBox6.AddItem rnCell.Value
Next rnCell
End Sub
Listvärden från flera kolumnerHär demonstreras en teknik för att hämta listvärden från flera cellområden, dvs från flera separata kolumner i samma kalkylblad:
Private Sub UserForm_Initialize()
Dim rnLista, rnCell As Range
Dim wkData As Worksheet
Set wkData = ThisWorkbook.Sheets("ListBox7")
'Union sammanfogar de båda cellområdena.
Set rnLista = Union(wkData.Range("A2:A4"), _ wkData.Range("E2:E4"))
For Each rnCell In rnLista
ListBox7.AddItem rnCell.Value
Next rnCell
End Sub
Ta bort & lägga till enstaka listvärdenHär demonstreras skilda tekniker för att ta bort & lägga till enskilda listvärden.
Ta bort enskilda listvärden
Ta bort listvärdet som har indexnumret 1:
ListBox8.RemoveItem 1För att ta bort den av användaren markerade listvärdet kan följande kod användas:
ListBox8.RemoveItem (ListBox8.ListIndex)Dock måste man här kontrollera att ListIndex <> -1!
För att ta bort samtliga listvärden kan vi användas oss av:
ListBox8.Clear eller ListBox8.Rowsource = ""Lägga till enskilda värden:
ListBox8.AddItem "XX" eller för att lägga till ett värde i en förutbestämd position (index) i listan ListBox8.AddItem "XX", 0Vill vi lägga till enskilda värden från en annan ListBox kan det ske på följande sätt:
ListBox8.AddItem ListBox7.ValueÄven här måste kontroll ske att ListBox7.Value <> -1!
Sortera listvärdenI det nästsista exemplet visas hur vi kan sortera en lista i en ListBox.
Så här ser listan ut innan sorteringen:
Private Sub cmbOK_Click()
Dim iForsta, iSista As Integer
Dim i, j As Integer
Dim sTemp As String
iForsta = 0
iSista = ListBox8.ListCount - 1
For i = iForsta To iSista - 1
For j = i + 1 To iSista
If ListBox8.List(i) > ListBox8.List(j) Then
sTemp = ListBox8.List(j)
ListBox8.List(j) = ListBox8.List(i)
ListBox8.List(i) = sTemp
End If
Next j
Next i
End SubSå här ser listan ut efter sorteringen:
Tilldela Listbox en lista med unika värden
I det sista exemplet visas hur vi kan skapa en unik lista som vi tilldelar Listboxen:
Private Sub UserForm_Initialize()
© 2002 Alla rättigheter XL-Dennis
Dim Lista As New Collection
Dim rnOmrade As Range, rnCell As Range
Dim vaVarde As Variant
'Här hämtas data från det aktiva arbetsbladet
Set rnOmrade = ActiveSheet.Range(Range("C1"), Range("C65536").End(xlUp))
'Här skapas den nya kollektionen
On Error Resume Next
For Each rnCell In rnOmrade
Lista.Add rnCell.Value, CStr(rnCell.Value)
Next rnCell
On Error GoTo 0
'Slutligen tilldelas Listboxen den unika listan
For Each vaVarde In Lista
UserForm1.ListBox1.AddItem vaVarde
Next
End SubDetta exempel finns ej att tillgå för hämtning.