Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ListBox Sort Order 1

Status
Not open for further replies.

Error7

Programmer
Jul 5, 2002
656
GB
I'm stumped.
I've been trying to figure out a fairly simple way of loading file names in these formats into a list box but in this order.

ref1.jpg
ref2.jpg
ref3.jpg
ref4.jpg
ref10.jpg
ref11.jpg
ref12.jpg
ref1p1.jpg
ref1p2.jpg
ref1p3.jpg
ref1p4.jpg
ref1p10.jpg
ref1p11.jpg
refdrk1.jpg
refdrk2.jpg
refdrk3.jpg
refdrk1p1.jpg
refdrk1p2.jpg
refdrk1p3.jpg
refdrk2p1.jpg
refdrk2p2.jpg
refdrk2p3.jpg
refdrk10p1.jpg
refdrk10p2.jpg
refdrk10p10.jpg
refdrk10p11.jpg
refdrk10p12.jpg

I tried setting the list box Sorted property to True but that doesn't do the job. I tried adding leading zero's but that got messy.




[gray]Experience is something you don't get until just after you need it.[/gray]
 

Which order do they come in?
What does your code looks like?

Have fun.

---- Andy
 
I'm just trying an alternative method to select the image using 2 arrays of command buttons. This is probably the best way to go.

[gray]Experience is something you don't get until just after you need it.[/gray]
 

I tried setting the list box Sorted property to True but that doesn't do the job

If that is what you are getting, then your Sort works OK:
[tt]
ref1.jpg
ref10.jpg
ref11.jpg
ref12.jpg
ref1p1.jpg
ref1p10.jpg
ref1p11.jpg
ref1p2.jpg
ref1p3.jpg
ref1p4.jpg
ref2.jpg
ref3.jpg
ref4.jpg
refdrk1.jpg
refdrk10p1.jpg
refdrk10p10.jpg
refdrk10p11.jpg
refdrk10p12.jpg
refdrk10p2.jpg
refdrk1p1.jpg
refdrk1p2.jpg
refdrk1p3.jpg
refdrk2.jpg
refdrk2p1.jpg
refdrk2p2.jpg
refdrk2p3.jpg
refdrk3.jpg
[/tt]

Have fun.

---- Andy
 
Error7, what you are trying to achieve is called 'logical' sorting in Windows, when numeric portions of the string are compared numerically, rather than alphabetically.

This enables Windows to sort files in the order "file1, file2, file10" instead of "file1, file10, file2" as it was done in Windows 98 and 2000.

The sort order you showed in your original post is also not exactly the documented logical sort order. Logically, ref1p1.jpg to ref1p11.jpg should come before ref2.jpg. You can verify this by looking at how Windows Explorer sorts these files in a folder. It will show ref2.jpg after all ref1p*.jpg files.

The default sorting feature of list box is not capable of doing this type of sort, as it is based on simple alphabetic sorting. You need to write your own sort algorithm to sort your items "logically".

When Windows compares two items, it splits the given file names or items in an alternating chain of alphabets and numbers (like "refdrk10p12.jpg" is split as "refdrk", 10, "p", 12, ".jpg"), and compares corresponding subitems in both items from left to right. If the subitems being compared are string, they are compared alphabetically, but if both subitems are numbers, they are compared numerically. The result is decided as soon as a mismatch is found and further comparison is stopped.

You can write your own code to do this type of comparison, but fortunately, Microsoft have added an API function in Windows XP and later, which does the same.

See the following code which shows how to do the logical sorting in a list box. Add a list box on your form (not sorted). Add the above file names in any order in the list box and run the following program.
___
[tt]
Option Explicit
Private Declare Function StrCmpLogicalW Lib "shlwapi" (ByVal lpStr1 As Long, ByVal lpStr2 As Long) As Long
Private Function StrCmpLogical(String1 As String, String2 As String) As Long
StrCmpLogical = StrCmpLogicalW(StrPtr(String1), StrPtr(String2))
End Function
Private Sub Form_Load()
SortListBoxLogical List1
End Sub
Private Sub SortListBoxLogical(LB As ListBox)
'do a bubble sort
Dim Count As Long, Sorted As Boolean, Swap As String
Count = LB.ListCount
Do
Sorted = True
For Count = 0 To Count - 2
If StrCmpLogical(LB.List(Count), LB.List(Count + 1)) = 1 Then 'swap
Swap = LB.List(Count)
LB.List(Count) = LB.List(Count + 1)
LB.List(Count + 1) = Swap
Sorted = False
End If
Next
Loop Until Sorted
End Sub[/tt]
___

After sorting, the list looks like as below, and it exactly matches the way Windows Explorer sorts these files in a folder.
[tt]
ref1.jpg
ref1p1.jpg
ref1p2.jpg
ref1p3.jpg
ref1p4.jpg
ref1p10.jpg
ref1p11.jpg
ref2.jpg
ref3.jpg
ref4.jpg
ref10.jpg
ref11.jpg
ref12.jpg
refdrk1.jpg
refdrk1p1.jpg
refdrk1p2.jpg
refdrk1p3.jpg
refdrk2.jpg
refdrk2p1.jpg
refdrk2p2.jpg
refdrk2p3.jpg
refdrk3.jpg
refdrk10p1.jpg
refdrk10p2.jpg
refdrk10p10.jpg
refdrk10p11.jpg
refdrk10p12.jpg
[/tt]
See StrCmpLogicalW function for more details.
See also this article which show how Windows allows you to change the default sort behaviour in Windows XP and later.
 
Thanks Hypetia, that is exactly what I'm trying to achieve but I'm not able to test it until Monday. Your sort is the same as how Explorer in Windows XP lists the filenames and that is what I need to emulate.


[gray]Experience is something you don't get until just after you need it.[/gray]
 
Also, it is not necessary to sort the list after it is filled with items randomly. You can also make sure that items are always sorted, and are placed at correct positions when you add them to the list.

StrCmpLogical function can help in this approach as well. To see this, place two list boxes on your form. Insert file names (in random order) in the first list box (List1). Following code will add them to the second list box (List2) maintaining logical order.
___
[tt]
Option Explicit
Private Declare Function StrCmpLogicalW Lib "shlwapi" (ByVal lpStr1 As Long, ByVal lpStr2 As Long) As Long
Private Function StrCmpLogical(String1 As String, String2 As String) As Long
StrCmpLogical = StrCmpLogicalW(StrPtr(String1), StrPtr(String2))
End Function

Private Sub Form_Load()
Dim I As Long, J As Long, S As String
For I = 0 To List1.ListCount - 1
S = List1.List(I)
For J = 0 To List2.ListCount - 1
If StrCmpLogical(List2.List(J), S) = 1 Then Exit For
Next
List2.AddItem S, J
Next
End Sub[/tt]
___

One more thing to note that, the return value of StrCmpLogical function is compared with 1 (String1 > String2) which results in an ascending sort. If you compare it with -1 (String1 < String2), the sort order will be reversed (descending sort). This also applies to the code I posted in my first post.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top