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 Sub

Fö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

Upp 


Flera kolumner

Hä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

Upp 


Välja flera listvärden

Fö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

Upp 


Kopplad Listbox

Hä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 Variant

vaLista1 = VBA.Array("Januari", "Februari", "Mars", "April")

With ListBox1
    .Clear
    .List = vaLista1
End With

End Sub

Hä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 Sub

Det 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 Sub

Nedan visas den dialogruta som ligger till grund för att koppla LIstBox:

Upp 


Multipel datafångst

Hä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

Upp 


Listvärden från rad

Att 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

Upp 


Listvärden från flera kolumner

Hä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

Upp


Ta bort & lägga till enstaka listvärden

Hä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 1

Fö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", 0

Vill 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!

Upp


Sortera listvärden

I 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 Sub

Så här ser listan ut efter sorteringen:

Upp

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 Sub

Detta exempel finns ej att tillgå för hämtning.

Upp