vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Top-Preis! AP-Access-Tools-CD Volume 1  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Controls · ListView   |   VB-Versionen: VB606.08.01
Numerische Sortierung im ListView-Control

Dieses Beispiel zeigt, wie man in einem ListView-Control eine korrekte numerische Sortierung realisieren kann.

Autor:   Michael HartmannBewertung:     [ Jetzt bewerten ]Views:  28.567 
ohne HomepageSystem:  Win9x, WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt auf CD 

Ein großer Nachteil des ListView-Controls ist die fehlende Möglichkeit, eine Spalte des Controls numerisch zu sortieren. Hat man z.B. in einer Spalte die Werte 1, 2, 3 und 20, so sortiert VB diese Werte alphanumerisch in 1, 2, 20, 3. Das ist natürlich nicht besonders schön und macht keinen professionellen Eindruck beim Enduser.

Aber es gibt eine Möglichkeit das ListView-Control mit der Fähigkeit der numerischen Sortierung auszustatten. Dazu kann man die folgende Sortierroutine einsetzen:

Private Declare Function LockWindowUpdate Lib "user32.dll" ( _
  ByVal hWnd As Long) As Long
 
Public Sub SortListViewColumn(ByVal Index As Integer, _
  ByVal CurrentListView As ListView)
 
  Dim I As Integer
  Dim strFormat As String
  Dim strData() As String
  Dim lRet As Long
 
  On Error GoTo ErrorHandler
 
  ' Benutzerdefinierter Formatstring für die
  ' Format-Funktion
  strFormat = String(30, "0") & "." & String(30, "0")
 
  ' Automatische Aktualisierung des Fensters sperren
  lRet = LockWindowUpdate(CurrentListView.Parent.hWnd)
  If lRet = 0& Then
    Call MsgBox("Can't lock window " & _
      CurrentListView.Parent.hWnd, _
      vbOKOnly + vbCritical)
    Exit Sub
  End If
 
  With CurrentListView
    With .ListItems
      If (Index > 0) Then ' Sortierung nach Subitems
        For I = 1 To .Count
          With .Item(I).ListSubItems(Index)
            ' Sichern des aktuellen Wertes der
            ' Text-Eigenschaft in der Tag-Eigenschaft,
            ' ohne einen evtl. Inhalt der Tag-Eigenschaft
            ' zu überschreiben
            .Tag = .Text & vbNullChar & .Tag
            ' Falls die Text-Eigenschaft der SubItems
            ' eine Zahl ist, so formatiere mit dem oben
            ' definierten Formatstring.
            If IsNumeric(.Text) Then
              .Text = Format$(CDbl(.Text), strFormat)
            End If
          End With
        Next I
      Else ' Sortierung nach Mainitem
        For I = 1 To .Count
          With .Item(I)
            ' Sichern des aktuellen Wertes der
            ' Text-Eigenschaft in der Tag-Eigenschaft,
            ' ohne einen evtl. Inhalt der Tag-Eigenschaft
            ' zu überschreiben
            .Tag = .Text & vbNullChar & .Tag
            ' Falls die Text-Eigenschaft der SubItems
            ' eine Zahl ist, so formatiere mit dem oben
            ' definierten Formatstring.
            If IsNumeric(.Text) Then
              .Text = Format$(CDbl(.Text), strFormat)
            End If
          End With
        Next I
      End If
    End With
 
    ' Sortiere die umformatierten Spalten neu
    .SortKey = Index
    .Sorted = True
    .SortOrder = 1 - .SortOrder
 
    With .ListItems
      If (Index > 0) Then ' Sortierung nach SubItem
        For I = 1 To .Count
          With .Item(I).ListSubItems(Index)
            ' Extrahiere den ursprünglichen Inhalt des
            ' Subitems aus der Tag Eingeschaft und
            ' stelle ihn wieder in die Text-Eigenschaft
            ' ein.
            strData = Split(.Tag, vbNullChar)
            .Text = strData(0)
            .Tag = strData(1)
          End With
        Next I
      Else ' Sortierung nach MainItem
        For I = 1 To .Count
          With .Item(I)
            ' Extrahiere den ursprünglichen Inhalt des
            ' Subitems aus der Tag Eingeschaft und
            ' stelle ihn wieder in die Text-Eigenschaft
            ' ein.
            strData = Split(.Tag, vbNullChar)
            .Text = strData(0)
            .Tag = strData(1)
          End With
        Next I
      End If
    End With
  End With
 
  ' Aufheben der Aktualisierungssperre für das Fenster
  lRet = LockWindowUpdate(0&)
  Exit Sub
 
ErrorHandler:
  lRet = LockWindowUpdate(0&)
  Call MsgBox("Runtime error " & Err.Number & ": " & _
    vbCrLf & Err.Description, vbOKOnly + vbCritical)
End Sub

Die Funktion bekommt die Spalte, nach der sortiert werden soll, sowie einen Verweis auf das ListView-Control, das sortiert werden soll, übergeben, so dass die Funktion universell einsetzbar ist. Der eigentliche Trick ist, die Texte der einzelnen Items so umzuformatieren (führende Nullen einfügen), dass eine alphanumerische Sortierung zum gewünschten Ergebnis führt. Um die führenden Nullen nachher wieder leicht entfernen zu können, wird der ursprüngliche Inhalt der Text-Eigenschaft in der Tag-Eigenschaft zwischengespeichert und nach erfolgter Sortierung daraus wieder hergestellt. Damit der Benutzer vom Einfügen der führenden Nullen nichts mitbekommt, wird mit Hilfe der API-Funktion LockWindowUpdate die Aktualisierung des Fensters, in dem sich das zu sortierende ListView-Control befindet, gesperrt und erst nach erfolgter Sortierung wieder frei gegeben.

Die Funktion kann z.B. in der ColumnHeader_Click Event-Prozedur folgendermaßen aufgerufen werden:

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As _
 MSComctlLib.ColumnHeader)
'  ListView1.Sorted = True
'  ListView1.SortKey = ColumnHeader.Index - 1
'  ListView1.SortOrder = 1 - ListView1.SortOrder
  Call SortListViewColumn(ColumnHeader.Index - 1, _
    Me.ListView1)
End Sub

Um den Unterschied zur normalen Sortierung des ListView-Controls und der hier beschriebenen Funktion zu verdeutlichen, habe ich mal die Aufrufe zur normalen Sortierung auskommentiert dazu geschrieben. Auch eine Sortierung nach einem Datumswert ist durch leichte Anpassungen der Sortierroutine realisierbar. Man braucht nur das Datum in den entsprechenden Zahlenwert zu wandeln, die numerische Sortierung einsetzen und den Zahlenwert zum Schluß wieder in ein Datum umzuwandeln. Auch für frühere VB Versionen muss die Sortierfunktion etwas angepasst werden, da die Split-Funktion erst mit VB6 eingeführt wurde.
 

22.05.07 - Ergänzung von Dirk Siebert, Dieter Otter
Damit das Ganze auch mit Vorzeichen (negative Zahlen) korrekt funktioniert, sind die beiden Vorkommnisse:

            If IsNumeric(.Text) Then
              .Text = Format$(CDbl(.Text), strFormat)
            End If

durch nachfolgende Codezeilen zu ersetzen:

            If IsNumeric(.Text) Then
              .Text = Format$(CDbl("1" & String$(14, "0")) + CDbl(.Text), strFormat)
            End If

Dieser Tipp wurde bereits 28.567 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel