Listbox in Access per Mausklick sortieren

01. Juni 2008 von Werner Mager · Gelesen: 2217 · heute: 1

Das man Listboxen und GridViews mit einem Mausklick auf die Kopfzeilen sortieren kann, ist mittlerweile in fast allen Programmen Standard - leider nur in fast allen. Microsoft Access bildet hierbei eine Ausnahme. Das wahrscheinlich beliebteste Programm um “mal eben” schnell eine Datenbank zu erstellen, eine hübsche Oberfläche oder einen Report zu gestalten, bietet diese Funktion von Haus aus nicht. Aber mit ein paar kleinen Tricks kann man diese - eins, zwei, drei - nachrüsten.

Trick eins - Den Klick auf die Kopfzeile erkennen

Um einen Klick auf die Listbox abzufangen, muss das Ereignis “MouseDown” implementiert werden. Hier rufen wir die Funktion “Sortlistbox” auf, die im Folgenden erarbeitet wird:

Private Sub Listbox1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  SortListbox Listbox1, X, Y
End Sub

Dabei werden die Koordinaten des Klicks übergeben. Ist Y <=210, so wurde auf die Kopfzeile geklickt (Die Höhe 210 gilt aber nur für die Standard-Schriftart Tahoma mit 8pt, bei anderen Schriftarten ist die Höhe entsprechend zu wählen):

Function SortListbox(lf As ListBox, X As Single, Y As Single)
  If Y <= 210 Then
    ' sortieren...
  End If
End Function

Trick zwei - Die geklickte Spalte ermitteln

Nun müssen wir herausfinden, welche Spalte geklickt wurde. Der X-Wert des Klicks ist nun von Bedeutung. Wir verwenden die Eigenschaft “ColumnWidth” der Listbox, die alle Spaltenbreiten als Komma-getrennte Liste enthält. Diese zerlegen wir mit “split” und summieren die Breiten, bis wir den X-Wert erreicht haben:

Function getColumn(X, lf As Object) As Integer
  Dim columns
  columns = Split(lf.ColumnWidths, ";")
  sum = 0
  While sum < X And getColumn <= UBound(columns)
    ' summiere Breite
    sum = sum + CInt(columns(getColumn ))
    getColumn = getColumn + 1
  Wend
End Function

Nun kennen wir die Spalte, die geklickt wurde. Über die Eigenschaft “Header” erhalten wir den Namen der Spalte, was uns ermöglicht, nach dieser zu sortieren. Die Funktion SortListbox sieht nun so aus:

Function SortListbox(lf As ListBox, X As Single, Y As Single)
  If Y <= 210 Then
    Column = getColumn(X, lf)
    header = lf.Column(Column - 1, 0)
    If Not IsNull(header) Then
      ' sortiere nach der ermittelten Spalte …
    End If
  End If
End Function

Trick drei - Die Datenquelle modifizieren

Das eigentliche Sortieren geschieht nun durch Änderung der Rowsource der Listbox. Dies übernimmt die Funktion “reOrder”, die das SQL-Statement der Listbox um die nötigen OrderBy-Anweisungen ergänzt:

Function SortListbox(lf As ListBox, X As Single, Y As Single)
  If Y <= 210 Then
    Column = getColumn(X, lf)
    header = lf.Column(Column - 1, 0)
    If Not IsNull(header) Then
      reordered = reOrder(lf.rowsource, header$)
      lf.rowsource = reordered
    End If
  End If
End Function
 
Function reOrder(rowsource As String, byWhat As String)
  ' Leerzeichen entfernen
  rowsource = Trim(rowsource)
  ' Falls byWhat einen Alias hat, diesen ermitteln
  byWhat = getAlias(rowsource, byWhat)‘ Direkte Quelle?
  If Not (Mid(rowsource, 1, 6) = "select") Then
    reOrder = "SELECT * from " & rowsource & " ORDER by " & byWhat & ";"
  Else
    ' SQl-String?
    reOrder = removeOrderBy(rowsource) & " ORDER BY " & byWhat & ";"
    ‘ Beim zweiten Klick absteigend sortieren
    If (rowsource = reOrder) And InStr(reOrder, "DESC") = 0 Then
      reOrder = Mid(reOrder, 1, Len(reOrder) - 1) + " DESC;"
    End If
  End If
End Function

Reorder greift dabei noch auf folgende Funktionen zurück:

Function removeOrderBy(src As String)
  i = InStr(src, "ORDER BY")
  If Not (i = 0) Then
    removeOrderBy = Trim(Mid(src, 1, i - 1))
    Exit Function
  End If
  If Mid(src, Len(src)) = ";" Then
    removeOrderBy = Trim(Mid(src, 1, Len(src) - 1))
    Exit Function
  End If
  removeOrderBy = Trim(src)
End Function
 
Function getAlias(sqlstr As String, obj As String) As String
  ' Suche in String
  i = InStr(sqlstr, " " + obj)
  If i = 0 Then
    i = InStr(sqlstr, "[" + obj)
  End If
  If Not (i = 0) Then
    ' Wenn direkt davor "as [" oder "as " steht…
    If Trim(Mid(sqlstr, i - 3, 3)) = "as" Then
      getAlias = lastWord(Mid(sqlstr, 1, i - 4))
      Exit Function
    End If
  End If
  ' sonst existiert kein Alias
  getAlias = "[" & obj & "]"
End Function
 
Function lastWord(str As String) As String
  Dim words
  words = Split(str, " ")
  lastWord = words(UBound(words))
End Function

Mit der Funktion SortListbox lässt sich nun jede ListBox in Access mit einer Zeile Code sortierbar machen. Die hier vorgestellten Methoden fügt man am besten als Modul zu dem Access Projekt hinzu.

Download Beispielprojekt und VBA-Modul

Wie immer habe ich das ganze in einem kleinen Beispielprojekt zusammengefasst:

Access Beispielprojekt

Und für alle, die es kurz und knapp mögen, hier das Modul mit der Funktion sortListbox:

Modul “sortlistbox”

Eine Antwort zu “Listbox in Access per Mausklick sortieren”

  1. VB Listbox Spalten sagt:

    […] End Sub  Das Modul dazu habe ich in meinem Blog beschrieben: Listbox in Access per Mausklick sortieren Viel Spa

Hinterlasse eine Antwort