locked
sort listview by date RRS feed

  • Question

  • Hi

    I have a listview control with two columns, column 1 contains a name and column 2 contains dates e.g. 11/10/2014 (D/M/YYYY)

    I need to sort it into date order

    How can I do this

    Have tried using the in-built sort commands but this only works on column 1 and only does alphabetical sorting, not by dates/numbers

    Also googled and tried a few, but it seems over complicated to achieve something so simple?


    Darren Rose


    • Edited by wingers Wednesday, October 15, 2014 11:44 PM edit: typo = meant listview not listbox
    Wednesday, October 15, 2014 10:15 PM

Answers

  • Have now got the sort working by date using code below

    The code also sorts by A-Z, numerically or by date if needed

    Added this into my main form to allow sorting by clicking on a column:-

    Private m_SortingColumn As ColumnHeader
    
        Private Sub ListView1_ColumnClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
            ' Get the new sorting column.
            Dim new_sorting_column As ColumnHeader = ListView1.Columns(e.Column)
            ' Figure out the new sorting order.
            Dim sort_order As System.Windows.Forms.SortOrder
            If m_SortingColumn Is Nothing Then
                ' New column. Sort ascending.
                sort_order = SortOrder.Ascending
            Else ' See if this is the same column.
                If new_sorting_column.Equals(m_SortingColumn) Then
                    ' Same column. Switch the sort order.
                    If m_SortingColumn.Text.StartsWith("> ") Then
                        sort_order = SortOrder.Descending
                    Else
                        sort_order = SortOrder.Ascending
                    End If
                Else
                    ' New column. Sort ascending.
                    sort_order = SortOrder.Ascending
                End If
                ' Remove the old sort indicator.
                m_SortingColumn.Text = m_SortingColumn.Text.Substring(2)
            End If
            ' Display the new sort order.
            m_SortingColumn = new_sorting_column
            If sort_order = SortOrder.Ascending Then
                m_SortingColumn.Text = "> " & m_SortingColumn.Text
            Else
                m_SortingColumn.Text = "< " & m_SortingColumn.Text
            End If
            ' Create a comparer.
            ListView1.ListViewItemSorter = New clsListviewSorter(e.Column, sort_order)
            ' Sort.
            ListView1.Sort()
        End Sub

    This uses the following class file called clsListviewSorter.vb:-

    Public Class clsListviewSorter ' Implements a comparer 
        Implements IComparer
        Private m_ColumnNumber As Integer
        Private m_SortOrder As SortOrder
        Public Sub New(ByVal column_number As Integer, ByVal sort_order As SortOrder)
            m_ColumnNumber = column_number
            m_SortOrder = sort_order
        End Sub
        ' Compare the items in the appropriate column
        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
            Dim item_x As ListViewItem = DirectCast(x, ListViewItem)
            Dim item_y As ListViewItem = DirectCast(y, ListViewItem)
            ' Get the sub-item values.
            Dim string_x As String
            If item_x.SubItems.Count <= m_ColumnNumber Then
                string_x = ""
            Else
                string_x = item_x.SubItems(m_ColumnNumber).Text
            End If
            Dim string_y As String
            If item_y.SubItems.Count <= m_ColumnNumber Then
                string_y = ""
            Else
                string_y = item_y.SubItems(m_ColumnNumber).Text
            End If
            ' Compare them.
            If m_SortOrder = SortOrder.Ascending Then
                If IsNumeric(string_x) And IsNumeric(string_y) Then
                    Return Val(string_x).CompareTo(Val(string_y))
                ElseIf IsDate(string_x) And IsDate(string_y) Then
                    Return DateTime.Parse(string_x).CompareTo(DateTime.Parse(string_y))
                Else
                    Return String.Compare(string_x, string_y)
                End If
            Else
                If IsNumeric(string_x) And IsNumeric(string_y) Then
                    Return Val(string_y).CompareTo(Val(string_x))
                ElseIf IsDate(string_x) And IsDate(string_y) Then
                    Return DateTime.Parse(string_y).CompareTo(DateTime.Parse(string_x))
                Else
                    Return String.Compare(string_y, string_x)
                End If
            End If
        End Function
    End Class
    

    And finally added this into my form to automatically sort it initially into date order by column 2 (1)

      ListView1.ListViewItemSorter = New clsListviewSorter(1, SortOrder.Ascending)
            ListView1.Sort()


    Darren Rose

    • Proposed as answer by Risa- Friday, October 17, 2014 1:27 AM
    • Marked as answer by Carl Cai Friday, October 17, 2014 2:09 AM
    Thursday, October 16, 2014 2:16 PM

All replies

  • Hi Darren,

    I guess you are using a Listview and not a Listbox, because a normally Listbox has just one column. The Question is, what is the Source of your data. In case it is a Database you can sort the data over the select Statement before adding in the Listview.

    When not you can use a own Class with Name and Date and a List (of yourClass) in connection with a Date Comparer. You have to sort your data before you add these.  The types of columns in a listbox or listview are Strings and sort by date is not possible by the control. You have to do this manually. Sorry for my not perfect English, I am not a native English speaker.

    Regards,


    Jens Gerber

    Wednesday, October 15, 2014 11:32 PM
  • Hi Jens

    Yes sorry I did mean a listview not a listbox - have corrected original post

    The source of the data is just name/date added from the result of a query against outlook contacts - no database involved


    Darren Rose

    Wednesday, October 15, 2014 11:45 PM
  • Hi Darren,

    then you have to sort the data manually before you add these. Show us a little bit code for better understanding.


    Jens Gerber

    Thursday, October 16, 2014 12:23 AM
  • Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    
            ListView1.View = View.Details
            ListView1.Columns.Add("Expiry Date", 130)
            ListView1.Columns.Add("Customer Name", 130)
            ListView1.GridLines = True
    
    
            Dim DateToday As DateTime = Date.Today
            Dim DatePlusThreeMonths = DateToday.AddMonths(+3)
            
            Dim objOutlook As Outlook._Application
            objOutlook = New Outlook.Application()
            Dim objNS As Outlook._NameSpace = objOutlook.Session
            Dim objFolder As Outlook.MAPIFolder = objNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts)
            Dim objContacts As Outlook._Items = objFolder.Items
            Dim DASLstring As String = """http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/Email%20Support%20expires/0x00000040"""
            Dim strRestrictCriteria As String = "@SQL=( " & DASLstring & " IS NOT NULL) AND (" & DASLstring & " < '" & DatePlusThreeMonths.Day & "/" & DatePlusThreeMonths.Month & "/" & DatePlusThreeMonths.Year & "') AND (" & DASLstring & " > '" & DateToday.Day & "/" & DateToday.Month & "/" & DateToday.Year & "')"
            Dim objADatumitems As Object = objContacts.Restrict(strRestrictCriteria)
            Dim objADatumitem As Outlook.ContactItem
            For Each objADatumitem In objADatumitems
    
                ListView1.Items.Add(New ListViewItem({objADatumitem.UserProperties.Find("Email Support expires").Value, objADatumitem.FullName}))
    
            Next
    
        End Sub


    Darren Rose

    Thursday, October 16, 2014 12:51 AM
  • if that column is Date type, then the following doc may be helpful.

    http://msdn.microsoft.com/en-us/library/ms996467.aspx


    remember make the reply as answer and vote the reply as helpful if it helps.

    Thursday, October 16, 2014 10:06 AM
  • Have now got the sort working by date using code below

    The code also sorts by A-Z, numerically or by date if needed

    Added this into my main form to allow sorting by clicking on a column:-

    Private m_SortingColumn As ColumnHeader
    
        Private Sub ListView1_ColumnClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
            ' Get the new sorting column.
            Dim new_sorting_column As ColumnHeader = ListView1.Columns(e.Column)
            ' Figure out the new sorting order.
            Dim sort_order As System.Windows.Forms.SortOrder
            If m_SortingColumn Is Nothing Then
                ' New column. Sort ascending.
                sort_order = SortOrder.Ascending
            Else ' See if this is the same column.
                If new_sorting_column.Equals(m_SortingColumn) Then
                    ' Same column. Switch the sort order.
                    If m_SortingColumn.Text.StartsWith("> ") Then
                        sort_order = SortOrder.Descending
                    Else
                        sort_order = SortOrder.Ascending
                    End If
                Else
                    ' New column. Sort ascending.
                    sort_order = SortOrder.Ascending
                End If
                ' Remove the old sort indicator.
                m_SortingColumn.Text = m_SortingColumn.Text.Substring(2)
            End If
            ' Display the new sort order.
            m_SortingColumn = new_sorting_column
            If sort_order = SortOrder.Ascending Then
                m_SortingColumn.Text = "> " & m_SortingColumn.Text
            Else
                m_SortingColumn.Text = "< " & m_SortingColumn.Text
            End If
            ' Create a comparer.
            ListView1.ListViewItemSorter = New clsListviewSorter(e.Column, sort_order)
            ' Sort.
            ListView1.Sort()
        End Sub

    This uses the following class file called clsListviewSorter.vb:-

    Public Class clsListviewSorter ' Implements a comparer 
        Implements IComparer
        Private m_ColumnNumber As Integer
        Private m_SortOrder As SortOrder
        Public Sub New(ByVal column_number As Integer, ByVal sort_order As SortOrder)
            m_ColumnNumber = column_number
            m_SortOrder = sort_order
        End Sub
        ' Compare the items in the appropriate column
        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
            Dim item_x As ListViewItem = DirectCast(x, ListViewItem)
            Dim item_y As ListViewItem = DirectCast(y, ListViewItem)
            ' Get the sub-item values.
            Dim string_x As String
            If item_x.SubItems.Count <= m_ColumnNumber Then
                string_x = ""
            Else
                string_x = item_x.SubItems(m_ColumnNumber).Text
            End If
            Dim string_y As String
            If item_y.SubItems.Count <= m_ColumnNumber Then
                string_y = ""
            Else
                string_y = item_y.SubItems(m_ColumnNumber).Text
            End If
            ' Compare them.
            If m_SortOrder = SortOrder.Ascending Then
                If IsNumeric(string_x) And IsNumeric(string_y) Then
                    Return Val(string_x).CompareTo(Val(string_y))
                ElseIf IsDate(string_x) And IsDate(string_y) Then
                    Return DateTime.Parse(string_x).CompareTo(DateTime.Parse(string_y))
                Else
                    Return String.Compare(string_x, string_y)
                End If
            Else
                If IsNumeric(string_x) And IsNumeric(string_y) Then
                    Return Val(string_y).CompareTo(Val(string_x))
                ElseIf IsDate(string_x) And IsDate(string_y) Then
                    Return DateTime.Parse(string_y).CompareTo(DateTime.Parse(string_x))
                Else
                    Return String.Compare(string_y, string_x)
                End If
            End If
        End Function
    End Class
    

    And finally added this into my form to automatically sort it initially into date order by column 2 (1)

      ListView1.ListViewItemSorter = New clsListviewSorter(1, SortOrder.Ascending)
            ListView1.Sort()


    Darren Rose

    • Proposed as answer by Risa- Friday, October 17, 2014 1:27 AM
    • Marked as answer by Carl Cai Friday, October 17, 2014 2:09 AM
    Thursday, October 16, 2014 2:16 PM