Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1530

[VB6] ListViewCustomSort Helper Class

$
0
0
I did a search here but couldn't find an existing implementation. There are several out there in the wild, dating back to an old Randy Birch example base on an even older MS KB item on sorting by date columns. So clearly people have been doing this since the early VB5 days, 1997-1998 or so.

ListViewCustomSort .cls and its companion ListViewCustomSortStatic.bas attempt to do the same thing written from scratch based on the Windows SDK. Since I wanted to make something more readily reusable it made sense to start writing anew based on the Common Controls ListView documentation.

This should be quicker with a better user experience than other techniques, for example creating extra "hidden" (width = 0) columns to sort on. However that's a perfectly viable solution as well. It just eats more memory.


What it Does

ListViewCustomSort works with both ActiveX ListView controls, the one in COMCTL32.OCX and the one in MSCOMCTL.OCX.

While you can use the existing sorting properies exposed by both ListViews for simple text sorts in ascending or descending order, there isn't a "custom sort" option and Compare Event like that provided by other controls such as the MSHFlexGrid.

ListViewCustomSort works in parallel with a ListView to provide such an event for custom sorting. While this version only handles single-column sorts you could enhance it to provide more than one column's text to the Compare Event handler.

In your Compare Event handler you get the column text of two rows to compare and you return a comparison result. In order to do something like a date or numeric compare you must compare ItemText1 and ItemText2 returning a numeric result:

Code:

'Return values:
'
'  -1 = Less Than
'    0 = Equal
'    1 = Greater Than

This usually requires some data conversion and conditional logic.


Using ListViewCustomSort

You must add ListViewCustomSortStatic.bas and ListViewCustomSort.cls to your project that uses ListViews. ListViewCustomSortStatic.bas is needed in order to implement the required API callback function.

Then in Forms with ListView controls where you want to do custom sorting, you add a separate instance of the ListViewCustomSort Class WithEvents in order to get a custom-sort Compare Event for each ListView. If your ListViews have identical sets of columns you can get by with a single ListViewCustomSort instance.

Then you write your Compare Event handler(s) to perform the custom sort comparisons.

To perform the custom sort you set ListViewCustomSort's .Ascending (Boolean) and .SortKey (Long: ListView column index, base 0) properties, and optionally its .TextMax (Long: max text width, default 256). Then you call the .Sort() method passing the ListView control reference.


The Demo

ListViewCustomSort is included in the attached archive which includes a self-contained demonstration project. This demo creates three columns of random data: a String, a Date, and a Single column.

ListViewCustomSort isn't need for the first column's data, but it is used for the other two which require some extra effort to make sorting work properly.

Name:  sshot.png
Views: 78
Size:  36.4 KB

The source code of Form1.frm may help make usage a little clearer:

Code:

Option Explicit

Private WithEvents ListViewCustomSort As ListViewCustomSort

Private Function MakeName() As String
    Const LETTERS As String = "abcdefghijklmnopqrstuvwxyz"
    Dim I As Long
    Dim IMax As Long
    Dim J As Long
    Dim Words() As String

    IMax = Int(3 * Rnd()) + 1
    ReDim Words(IMax)
    For I = 0 To IMax
        For J = 1 To Int(8 * Rnd()) + 2
            Words(I) = Words(I) & Mid$(LETTERS, Int(26 * Rnd()) + 1, 1)
        Next
        Words(I) = StrConv(Words(I), vbProperCase)
    Next
    MakeName = Join$(Words, " ")
End Function

Private Sub cmdSortBy_Click(Index As Integer)
    Select Case Index
        Case 0
            With ListView1
                .SortKey = 0
                .SortOrder = IIf(chkAscending.Value = vbChecked, lvwAscending, lvwDescending)
                .Sorted = True
            End With

        Case 1, 2
            ListViewCustomSort.Sort ListView1, Index, chkAscending.Value = vbChecked
    End Select
End Sub

Private Sub Form_Load()
    Dim I As Long

    Randomize

    Set ListViewCustomSort = New ListViewCustomSort

    With ListView1.ColumnHeaders
        .Add , , "Col 0", 3600, lvwColumnLeft
        .Add , , "Col 1", 1080, lvwColumnRight
        .Add , , "Col 2", 1080, lvwColumnRight
    End With
    With ListView1
        With .ListItems
            For I = 1 To 1000
                With .Add(, , MakeName()) 'String.
                    .SubItems(1) = Format$(DateAdd("d", -Int(1000 * Rnd()), Date), "m/d/yyyy") 'Date.
                    .SubItems(2) = CStr(20000! * Rnd() - 10000!) 'Single.
                End With
            Next
        End With
        Set .SelectedItem = Nothing
    End With
End Sub

Private Sub Form_Resize()
    If WindowState <> vbMinimized Then
        With Picture1
            .Move 0, ScaleHeight - .Height
            ListView1.Move 0, 0, ScaleWidth, .Top
        End With
    End If
End Sub

Private Sub ListViewCustomSort_Compare( _
    ByVal SortKey As Long, _
    ByVal Ascending As Boolean, _
    ItemText1 As String, _
    ItemText2 As String, _
    Cmp As Long)

    Dim Parts() As String
    Dim Date1 As Date
    Dim Date2 As Date
    Dim Single1 As Single
    Dim Single2 As Single

    Select Case SortKey
        Case 1
            Parts = Split(ItemText1, "/")
            Date1 = DateSerial(CInt(Parts(2)), CInt(Parts(0)), CInt(Parts(1)))
            Parts = Split(ItemText2, "/")
            Date2 = DateSerial(CInt(Parts(2)), CInt(Parts(0)), CInt(Parts(1)))
           
            Cmp = Sgn(CLng(Date1) - CLng(Date2))

        Case 2
            Single1 = CSng(ItemText1)
            Single2 = CSng(ItemText2)

            Cmp = Sgn(Single1 - Single2)
    End Select
    If Not Ascending Then Cmp = -Cmp
End Sub

Attached Images
 
Attached Files

Viewing all articles
Browse latest Browse all 1530

Trending Articles