?
Solved

ListView sorting

Posted on 1999-08-02
7
Medium Priority
?
752 Views
Last Modified: 2012-06-21
When you click on a column header on a ListView control to sort it, it sorts alphabetically, so if you had the items 3, 5, 6, 10 in a column and clicked on the column header, 10 would appear first, because the first character '1' is less than the first character of the other items.

Therefore, is there a way to sort the list items numerically rather than alphabetically.

Thanks,

Simon Williams.
0
Comment
Question by:TheNugget
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 2

Expert Comment

by:jaywalk
ID: 1528949
The only way I've found to do that is to have an unsorted list, and do my own sorting. (which is time consuming, and boring)
0
 
LVL 8

Expert Comment

by:vettranger
ID: 1528950
Simon,

This is an OLD EDP bugaboo. When you have numbers that are going to be sorted as alpha for some reason, you need to format the 'shorter' numbers with leading zeros, i.e. :

01
02
04
10

or

001
045
100

Make the format consistent with the largest number you can enounter in the sequence.
0
 
LVL 14

Accepted Solution

by:
waty earned 300 total points
ID: 1528951
Take a look on www.vbaccelerator.com
You will find a grid (with sources) wich can replace the listview and has lots more enhancments. I use it everywhere to replace listview :)
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Expert Comment

by:fnevarez
ID: 1528952
Try:
   listview.Listitems.Add Format(Cstr(intNumber), "@@@@@")

this right-justified the number to 5 positions with blanks,
so when you sort your listview, it's ok.
0
 
LVL 4

Expert Comment

by:Juilette
ID: 1528953
the listbox can be sorted by number, date, and alpha! When I get it working if the question is still in need of answering I will answer. Just having a little problem...my understanding of things is slower because I am learning this feature as I am trying to answer your question. ...But yes, it can be done.
0
 
LVL 14

Expert Comment

by:waty
ID: 1528954
Sorting listview by number or date

VERSION 5.00
Object = "831FDD16-0C5C-11D2-A9FC-0000F8754DA1#2.0#0"; "MSCOMCTL.OCX"
Begin VB.Form Form1
Caption         =   "Form1"
ClientHeight    =   4455
ClientLeft      =   60
ClientTop       =   345
ClientWidth     =   8280
LinkTopic       =   "Form1"
ScaleHeight     =   4455
ScaleWidth      =   8280
StartUpPosition =   3  'Windows Default
Begin MSComctlLib.ListView ListView1
Height          =   4215
Left            =   120
TabIndex        =   0
Top             =   120
Width           =   8055
_ExtentX        =   14208
_ExtentY        =   7435
View            =   3
LabelWrap       =   -1  'True
HideSelection   =   -1  'True
_Version        =   393217
ForeColor       =   -2147483640
BackColor       =   -2147483643
BorderStyle     =   1
Appearance      =   1
NumItems        =   0
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit

' #VBIDEUtils#************************************************************
' * Programmer Name  : Waty Thierry
' * Web Site         : www.geocities.com/ResearchTriangle/6311/
' * E-Mail           : waty.thierry@usa.net
' * Date             : 28/06/99
' * Time             : 15:52
' **********************************************************************
' * Comments         : Sorting ListView by Number or Date
' *
' *
' **********************************************************************

'****************************************************************
' Win32 API
'----------------------------------------------------------------

Private Declare Function LockWindowUpdate Lib "user32" _
   (ByVal hWndLock As Long) As Long

Private Declare Function GetTickCount Lib "kernel32" () As Long

'****************************************************************
' Form_Load
' Initialises the list control, and populates it with random data
'----------------------------------------------------------------

Private Sub Form_Load()
   With ListView1

      ' Add three columns to the list - one for each data type.
      ' Note that the data type is set in the column header's
      ' tag in each case

      .ColumnHeaders.Add(, , "String").Tag = "STRING"
      .ColumnHeaders.Add(, , "Number").Tag = "NUMBER"
      .ColumnHeaders.Add(, , "Date").Tag = "DATE"

      ' Set the column alignment - has no bearing on the sorts.

      .ColumnHeaders(1).Alignment = lvwColumnLeft
      .ColumnHeaders(2).Alignment = lvwColumnRight
      .ColumnHeaders(3).Alignment = lvwColumnCenter

      ' Populate the list with data

      Dim l As Long
      Dim dblRnd As Double
      Dim dteRnd As Date
      With .ListItems
         For l = 1 To 1000
            With .Add(, , "ListItem " & Format(l, "0000"))
               dblRnd = (Rnd() * 10000) - 5000
               dteRnd = (Rnd() * 1000) + Date
               .ListSubItems.Add , , Format(dblRnd, "0.00")
               .ListSubItems.Add , , Format(dteRnd, _
                  "dd/mm/yyyy")
            End With
         Next l
      End With

   End With
End Sub

'****************************************************************
' ListView1_ColumnClick
' Called when a column header is clicked on - sorts the data in
' that column
'----------------------------------------------------------------

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As _
   MSComctlLib.ColumnHeader)

   On Error Resume Next

   ' Record the starting CPU time (milliseconds since boot-up)

   Dim lngStart As Long
   lngStart = GetTickCount

   ' Commence sorting

   With ListView1

      ' Display the hourglass cursor whilst sorting

      Dim lngCursor As Long
      lngCursor = .MousePointer
      .MousePointer = vbHourglass

      ' Prevent the ListView control from updating on screen -
      ' this is to hide the changes being made to the listitems
      ' and also to speed up the sort

      LockWindowUpdate .hWnd

      ' Check the data type of the column being sorted,
      ' and act accordingly

      Dim l As Long
      Dim strFormat As String
      Dim strData() As String

      Dim lngIndex As Long
      lngIndex = ColumnHeader.Index - 1

      Select Case UCase$(ColumnHeader.Tag)
         Case "DATE"

            ' Sort by date.

            strFormat = "YYYYMMDDHhNnSs"

            ' Loop through the values in this column. Re-format
            ' the dates so as they can be sorted alphabetically,
            ' having already stored their visible values in the
            ' tag, along with the tag's original value

            With .ListItems
               If (lngIndex > 0) Then
                  For l = 1 To .Count
                     With .Item(l).ListSubItems(lngIndex)
                        .Tag = .Text & Chr$(0) & .Tag
                        If IsDate(.Text) Then
                           .Text = Format(CDate(.Text), _
                              strFormat)
                        Else
                           .Text = ""
                        End If
                     End With
                  Next l
               Else
                  For l = 1 To .Count
                     With .Item(l)
                        .Tag = .Text & Chr$(0) & .Tag
                        If IsDate(.Text) Then
                           .Text = Format(CDate(.Text), _
                              strFormat)
                        Else
                           .Text = ""
                        End If
                     End With
                  Next l
               End If
            End With

            ' Sort the list alphabetically by this column

            .SortOrder = (.SortOrder + 1) Mod 2
            .SortKey = ColumnHeader.Index - 1
            .Sorted = True

            ' Restore the previous values to the 'cells' in this
            ' column of the list from the tags, and also restore
            ' the tags to their original values

            With .ListItems
               If (lngIndex > 0) Then
                  For l = 1 To .Count
                     With .Item(l).ListSubItems(lngIndex)
                        strData = Split(.Tag, Chr$(0))
                        .Text = strData(0)
                        .Tag = strData(1)
                     End With
                  Next l
               Else
                  For l = 1 To .Count
                     With .Item(l)
                        strData = Split(.Tag, Chr$(0))
                        .Text = strData(0)
                        .Tag = strData(1)
                     End With
                  Next l
               End If
            End With

         Case "NUMBER"

            ' Sort Numerically

            strFormat = String(30, "0") & "." & String(30, "0")

            ' Loop through the values in this column. Re-format the values so as they
            ' can be sorted alphabetically, having already stored their visible
            ' values in the tag, along with the tag's original value

            With .ListItems
               If (lngIndex > 0) Then
                  For l = 1 To .Count
                     With .Item(l).ListSubItems(lngIndex)
                        .Tag = .Text & Chr$(0) & .Tag
                        If IsNumeric(.Text) Then
                           If CDbl(.Text) >= 0 Then
                              .Text = Format(CDbl(.Text), _
                                 strFormat)
                           Else
                              .Text = "&" & InvNumber( _
                                 Format(0 - CDbl(.Text), _
                                 strFormat))
                           End If
                        Else
                           .Text = ""
                        End If
                     End With
                  Next l
               Else
                  For l = 1 To .Count
                     With .Item(l)
                        .Tag = .Text & Chr$(0) & .Tag
                        If IsNumeric(.Text) Then
                           If CDbl(.Text) >= 0 Then
                              .Text = Format(CDbl(.Text), _
                                 strFormat)
                           Else
                              .Text = "&" & InvNumber( _
                                 Format(0 - CDbl(.Text), _
                                 strFormat))
                           End If
                        Else
                           .Text = ""
                        End If
                     End With
                  Next l
               End If
            End With

            ' Sort the list alphabetically by this column

            .SortOrder = (.SortOrder + 1) Mod 2
            .SortKey = ColumnHeader.Index - 1
            .Sorted = True

            ' Restore the previous values to the 'cells' in this
            ' column of the list from the tags, and also restore
            ' the tags to their original values

            With .ListItems
               If (lngIndex > 0) Then
                  For l = 1 To .Count
                     With .Item(l).ListSubItems(lngIndex)
                        strData = Split(.Tag, Chr$(0))
                        .Text = strData(0)
                        .Tag = strData(1)
                     End With
                  Next l
               Else
                  For l = 1 To .Count
                     With .Item(l)
                        strData = Split(.Tag, Chr$(0))
                        .Text = strData(0)
                        .Tag = strData(1)
                     End With
                  Next l
               End If
            End With

         Case Else   ' Assume sort by string

            ' Sort alphabetically. This is the only sort provided
            ' by the MS ListView control (at this time), and as
            ' such we don't really need to do much here

            .SortOrder = (.SortOrder + 1) Mod 2
            .SortKey = ColumnHeader.Index - 1
            .Sorted = True

      End Select

      ' Unlock the list window so that the OCX can update it

      LockWindowUpdate 0&

      ' Restore the previous cursor

      .MousePointer = lngCursor

   End With

   ' Report time elapsed, in milliseconds

   MsgBox "Time Elapsed = " & GetTickCount - lngStart & "ms"

End Sub

'****************************************************************
' InvNumber
' Function used to enable negative numbers to be sorted
' alphabetically by switching the characters
'----------------------------------------------------------------

Private Function InvNumber(ByVal Number As String) As String
   Static i As Integer
   For i = 1 To Len(Number)
      Select Case Mid$(Number, i, 1)
         Case "-": Mid$(Number, i, 1) = " "
         Case "0": Mid$(Number, i, 1) = "9"
         Case "1": Mid$(Number, i, 1) = "8"
         Case "2": Mid$(Number, i, 1) = "7"
         Case "3": Mid$(Number, i, 1) = "6"
         Case "4": Mid$(Number, i, 1) = "5"
         Case "5": Mid$(Number, i, 1) = "4"
         Case "6": Mid$(Number, i, 1) = "3"
         Case "7": Mid$(Number, i, 1) = "2"
         Case "8": Mid$(Number, i, 1) = "1"
         Case "9": Mid$(Number, i, 1) = "0"
      End Select
   Next
   InvNumber = Number
End Function


0
 
LVL 14

Expert Comment

by:waty
ID: 1528955
Also here sorting listview using callback :
http://www.mvps.org/vbnet/code/callback/lvsortcallback.htm

0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Suggested Courses

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question