PDA

Click to See Complete Forum and Search --> : How can i sort a Listview Control?


badal
Jan 27th, 2000, 07:52 PM
hello everyone

the listview control in visual basic can sort on any column simply. my problem is that it behaves like it is sorting strings. i cannot get it to correctly sort on numbers or dates.

eg. it sorts numbers 1 to 23 like this....

1
10
11
12
13
14
15
16
17
18
19
2
20
21
22
23
24
3
4
5
6
7
8
9

same problem with dates it thinks they are strings. i have investigated the following:
(*) the columnheader objet does not have a property where i can define the data type of the column values that it will hold
(*) you cannot create a hidden column to sort on. ie. somehow fake the sort

the windows explorer uses a similar or probably the same control. click on the size and see the column values are not sorted as if they were strings, they are actually sorted in correct order of file size.

ANY IDEAS/SOLUTION/ALTERNATIVE.


also see the control (listview) used by winzip. do you think these are the same as what we the vb-developers have been provided with.


[This message has been edited by badal (edited 01-28-2000).]

Jan 27th, 2000, 10:39 PM
Hello badal,

The only way I was able to get around this was to format my numbers with 0.

1 = 01
2 = 02

That works out the sorting.
Good Luck

------------------
Boothman
There is a war out there and it is about who controls the information, it's all about the information.

HDR
Jan 28th, 2000, 12:30 AM
These are as good as you're going to get. Unfortunately, ListView uses a simple sort that doesn't take into account whether it's a date or an integer or a string. It just treats everything like a string.

badal
Jan 28th, 2000, 11:08 AM
thanx guys,

that's exactly what i thought, vb listview cannot handle anything but strings. this does not solve my problem, i wonder how they have done in winzip and windows explorer or what control are they using. thanx anyway.

do you know of an equivalent control, anything but not the grid unless it has a columnclick event like listview does?

OneSource
Jan 28th, 2000, 11:21 AM
Greetings Badal.

As for Dates, if you format the values so that the years are first, then the months, then the days, I believe that ascending and descending sorts will be correct. I'm not sure about this, however, because I haven't tested it.

For example: format(Date,"yyyy/mm/dd")Hope this helps.
------------------
OneSource
The truth may be out there, but it's in here too!.

[This message has been edited by OneSource (edited 01-28-2000).]

Serge
Jan 31st, 2000, 12:05 AM
Here is an example of how to sort the ListView by Date or Number. Copy this code to a module:


Private Declare Function LockWindowUpdate Lib "user32" (ByVal hWndLock As Long) As Long
Public Enum eSortType
eByDate = 1
eByNumber = 2
eByString = 3
End Enum
Public Sub SortListView(pListView As ListView, pSortType As eSortType, pColumnHeaderIndex As Integer)
Dim l As Long
Dim strFormat As String
Dim strData() As String
Dim lngCursor As Long
Dim lngIndex As Long

On Error Resume Next


With pListView
' Display the hourglass cursor whilst sorting
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

lngIndex = pColumnHeaderIndex - 1
Select Case pSortType
Case eByDate
' Sort by date.
strFormat = "YYYYMMDDHhNnSs"
With .ListItems
If (lngIndex > 0) Then
For l = 1 To .Count
With .Item(l).ListSubItems(lngIndex)
.Tag = .Text & vbNullChar & .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 & vbNullChar & .Tag
If IsDate(.Text) Then
.Text = Format(CDate(.Text), _
strFormat)
Else
.Text = ""
End If
End With
Next l
End If
End With

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

Case eByNumber
' Sort Numerically
strFormat = String(30, "0") & "." & String(30, "0")
With .ListItems
If (lngIndex > 0) Then
For l = 1 To .Count
With .Item(l).ListSubItems(lngIndex)
.Tag = .Text & vbNullChar & .Tag
If IsNumeric(.Text) Then
If CDbl(.Text) >= 0 Then
.Text = Format(CDbl(.Text), _
strFormat)
Else
.Text = "&" & InvertNumber( _
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 & vbNullChar & .Tag
If IsNumeric(.Text) Then
If CDbl(.Text) >= 0 Then
.Text = Format(CDbl(.Text), _
strFormat)
Else
.Text = "&" & InvertNumber( _
Format(0 - CDbl(.Text), _
strFormat))
End If
Else
.Text = ""
End If
End With
Next l
End If
End With
With .ListItems
If (lngIndex > 0) Then
For l = 1 To .Count
With .Item(l).ListSubItems(lngIndex)
strData = Split(.Tag, vbNullChar)
.Text = strData(0)
.Tag = strData(1)
End With
Next l
Else
For l = 1 To .Count
With .Item(l)
strData = Split(.Tag, vbNullChar)
.Text = strData(0)
.Tag = strData(1)
End With
Next l
End If
End With

Case Else
End Select
.SortOrder = (.SortOrder + 1) Mod 2
.SortKey = pColumnHeaderIndex - 1
.Sorted = True

' Unlock the list window so that the OCX can update it
LockWindowUpdate 0&

' Restore the previous cursor
.MousePointer = lngCursor
End With
End Sub

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


Usage: SortListView ListView, SortType, ColumnHeaderIndex

Exaple:


Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
Select Case ColumnHeader
Case "DATE"
SortListView ListView1, eByDate, ColumnHeader.Index
Case "NUMBER"
SortListView ListView1, eByNumber, ColumnHeader.Index
End Select
End Sub

1buddylee
Jan 31st, 2000, 12:05 AM

Geemark
Jan 18th, 2003, 05:12 AM
I have done exactly what was in that sample, but it still does not sort by numbers even if I use "eByNumber".
What is wrong??

All I get is this:
1
11
2

Instead of:
1
2
11


Please help

jcm900
Jan 31st, 2003, 01:06 PM
:confused:

Not sure if you are getting your data from a database or not, but you can always write a method--er--sub(damn Java!) to requery the data with the ORDER BY clause on the numeric field and repopulate the listView based on that. This assumes, of course that there isn't a huge amount of data displayed in the listView. Also, this could be a big waste of time if you aren't populating with a database.

Anyway, good luck!

Geemark
Feb 5th, 2003, 09:47 AM
I am using a database, but do not want to requery every time the user changes the sorting order. However I sorted it out!

Frans C
Feb 5th, 2003, 10:05 AM
MVPS has some code on sorting listviews.
http://www.mvps.org/vbnet/index.html?code/callback/lvsortcallback.htm