Virtual Developer Workshop: Containerized Development with Docker

ListView - Sorting by Number or Date

The ListView control that comes with MSCOMCTL.OCX isn't too bad. It supplies us with most of the things that we need, and makes them incredibly easy to code. As a VC++ developer I can tell you that most of the features that we all take for granted can be a real pig to implement using the MFC and API calls.

One thing that this control is sadly lacking in, however, is the ability to sort by number or date. It would also appear to be something that a lot of people are asking for.

My first attempt at implementing this involved using APIs to talk directly to the ListView window. It was fast and did just the job that I wanted. It did, however, have one major drawback - Microsoft, in their infinite wisdom, have given VB developers a wrapper for the ListView window which stores its own internal collection of listitem data, rather than referencing the window's own data. The result of this is not only that two copies of the data are stored in memory (Bloatware? It gets my vote...), but if you try to manipulate the listview directly, then all the VB collections go out of synch with what's displayed on-screen. BIG problem!

For my second attempt, I decided to take a step back, and try something simpler. I decided to make use of the alphabetical sort that has been implemented with the control. It involves locking the window so that no changes in the data are reflected on-screen, re-formatting the list items so that they may be sorted alphabetically, sorting them, and then restoring the original data before unlocking and refreshing the ListView. I know that this is a pig of a way to do things, but it works!

The good news it that the sort is surprisingly fast. On my machine (a PII 350 with 64Mb RAM running NT4), sorting by number takes about 0.4 milliseconds per listitem (when running in the IDE), and by date takes around 0.35ms.

This certainly isn't THE way to sort ListItems by number or date, but it'll me do until Microsoft supply a custom sort for the ListView control.

Download Zipped Project File (4k)

Screen shot


  • Still Great In 2015

    Posted by Lorin on 05/11/2015 01:21am

    Thanks for the ListView Sort for Numbers and Dates.

  • JonasK

    Posted by JonasK on 03/01/2011 10:28am

    ten points

  • Let ListView sort dates and numbers itself

    Posted by UnderMan on 04/29/2007 09:50pm

    Just add two more columns with zero lengths to retain extra data.  Pad numbers with leading zeros: Format(a, "000000"), store dates without slashes or commas: Format(d, "mmddyy"), and store them in the hidden columns.  When displayed date or amount columns are chosen, reference the sort to the hidden columns instead.  Voila, sorted without a sort routine.  It's inherently sorted from the get go.  Save all the column information, including the hidden ones, in a file for retrieval on start up.
    Private Sub Form_Load()
        'Randomly add dates, amounts, and text to listview
        'lvMain is the name of the listview box
        'Using two extra columns for the date and amount sort data
        For x = 1 To 365
            Set lx = lvMain.ListItems.Add
            l = Date + Int(Rnd * 90) + 1                '90 days from today
            m = Rnd * 250 + 1                           'Up to $250.00 spent
            lx.Text = Format(l, "MMM dd/yy")            'Displayed date
            lx.SubItems(1) = Format(m, "##0.00")        'Displayed amount
            lx.SubItems(2) = Format(l, "mmddyy")        'for date sorting, hidden
            lx.SubItems(3) = Format(m * 100, "0000000") 'for amount sorting, hidden
            d = ""
            For m = 1 To 4
                d = d + Chr(Int(Rnd * 26) + 65)
            lx.SubItems(4) = d
        'Don't want any item to be selected when form first opens
        'user selects it himself/herself
        If Not lvMain.SelectedItem Is Nothing Then
            lvMain.SelectedItem.Selected = False
            Set lvMain.SelectedItem = Nothing
        End If
    End Sub 'Form_Load
    Private Sub lvMain_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
        If ColumnHeader = "Amount" Then
            'If column is clicked once, sort in ascending order,
            'clicked a 2nd time sort in descending order
            'same goes for date and text columns
            If lvMain.Tag <> "Amount" Then
                lvMain.Tag = "Amount"
                lvMain.SortOrder = 1
            End If
            lvMain.Sorted = True
            lvMain.SortKey = 4 - 1
            lvMain.SortOrder = 1 Xor lvMain.SortOrder
        ElseIf ColumnHeader = "Date" Then
            If lvMain.Tag <> "Date" Then
                lvMain.Tag = "Date"
                lvMain.SortOrder = 1
            End If
            lvMain.Sorted = True
            lvMain.SortKey = 3 - 1
            lvMain.SortOrder = 1 Xor lvMain.SortOrder
            If lvMain.Tag <> ColumnHeader Then
                lvMain.Tag = ColumnHeader
                lvMain.SortOrder = 1
            End If
            lvMain.Sorted = True
            lvMain.SortKey = ColumnHeader.Index - 1
            lvMain.SortOrder = 1 Xor lvMain.SortOrder
        End If
    End Sub 'lvMain_ColumnClick
    Private Sub Sum_It()
        'Sum "Amount" column
        For x = 1 To lvMain.ListItems.Count
            c = c + Val(lvMain.ListItems(x).SubItems(1))
        lblTotal = c
    End Sub 'Sum_It

  • Better version of: ListView - Sorting by Number or Date

    Posted by thomasholme on 07/28/2004 11:21am

    I had to use this is a database application with more than 20 listviews, thus I have moved the sort part into it'w own function and I have added the option to sort mixed strings (e.g. 2940.65 $) wich are stored in the DB I have to interface. Please email me if you would like to get my new version of the project. thomas@openmpeg4.org Again, Thanks Pete for a great contribution

  • What a great solution, so much better than callbacks!!

    Posted by o2simple on 07/23/2004 08:51pm

    There are tons of examples using callbacks
    and they all suffer from the collecitons getting out of sync.  Do they really expect that no one will use SelectedItem after a sort?  We are using .NET now but we still have a ton of legacy code, and users are tired of double clicking a listitem and having it open the wrong one! Thanx for this great solution.  Its even way faster than my old way using callbacks.

  • very nice

    Posted by Legacy on 10/02/2003 07:00am

    Originally posted by: Willem Laarman

    Thank you very much..

    I have been looking for a function like this for a long time. It works great!

  • Thank yous

    Posted by Legacy on 07/23/2003 07:00am

    Originally posted by: Au

    Help me much...

  • A Solution At Last

    Posted by Legacy on 05/29/2003 07:00am

    Originally posted by: Terry

    Finally, a workable solution for my app!  I've been struggling with figuring out how to allow my users to sort some reports that range from a few records up to 50000+. My alternatives thusfar were unsatisfactory:

    - Text sort on every column regardless of the column data type.
    - Use the Win API sort method, but screw up the tag information.
    - Export the data to an multi dimensional array, sort it and re-populate the control, which gave me two results:
    - Use a quicksort algorithm, which was fairly fast
    but would give a stack space error when sorting
    more than 3000 records.
    - Use a slower non-recursive sort method
    (i.e. shell sort) which didn't crash but would take
    up to an hour to sort on the huge lists.

    Now I can give users good data-aware sorting without the crashing and in a reasonable amount of time (+-10 seconds for numeric sort on 50000 records.)

    It is depressing that the ListView control isn't smart enough to do this for us, but at least now we have an adequate work around. Hokey or not, it works!

    Thanks again!

  • Work great

    Posted by Legacy on 05/16/2003 07:00am

    Originally posted by: Gary

    After missing around for a few days with Microsoft solution (Article 170884) 'Sort a ListView Control by Date', I was glad to find your solution. It works great!!!.

  • Kudos

    Posted by Legacy on 04/03/2003 08:00am

    Originally posted by: Craig


    I lifted your routine and used it successfully to great acclaim from the boss after a 'whizkid' had been unable to implement this feature. All the credit is yours however and I did admit as much to him.

    Thanks for making me look good.


  • Loading, Please Wait ...

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date