(See attachment)
I need help sorting items inside a listbox, the problem is, i'm using columns; so i don't know the algorithm if i want to sort it like this :
See the combo box in my program?
If "A" is selected, i want the items to be sorted based the values of A, descending down from the biggest number to smallest number, and the same applies the other letters.
ex :
A B C D
3 2 8 5
6 5 4 2
8 6 3 2
7 5 7 5
4 7 4 8
8 6 4 0
Select "A"
A B C D
8 6 3 2
8 6 4 0
7 5 7 5
6 5 4 2
4 7 4 8
3 2 8 5
Select "B"
A B C D
4 7 4 8
8 6 3 2
8 6 4 0
7 5 7 5
6 5 4 2
3 2 8 5
Select "C"
A B C D
3 2 8 5
7 5 7 5
8 6 4 0
6 5 4 2
4 7 4 8
8 6 3 2
select "D"
A B C D
4 7 4 8
7 5 7 5
3 2 8 5
8 6 3 2
6 5 4 2
8 6 4 0
(these numbers are just an example, they're not in the prog. )
Thx in advance.
Last edited by Deny Winarto; Apr 22nd, 2005 at 06:16 PM.
I'm sorry to say that this cannot be easily done with the listbox. The ListView would be a better choice - it supports multiple columns, and a sort can be based on any one of those columns.
I've tried listview before, but i couldn't seem to create any columns on it.
(I'm still new at VB) I increased the columns from the property page, but it doesn't show any columns when i run it... what's wrong? Or..could you show me an example for this thing ?
I will whip up an example for you and post it later today.
BTW - You did not see your columns probably because you did not set the view property to lvwReportView ...
Thanks BIOstall, that was a useful site, but it doesn't show how to sort items..
Bruce, when i run your program ; on this line :
"Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader"
I get this message :
"compile error user-defined type not defined"
And i can't change the code...
What version of VB / service pack do you have?
I assume you opened the .vbp (project file), not just the form (.frm)?
Also, try removing "MSComctlLib.".
Let me know if you still have trouble.
I think something's wrong with my VB, everytime i try to run a code that i got from this board, it always shows error message..
I have an idea..
Maybe it'd work if you just copy-paste the code into my form. (see attachment)
I just did an experiment, and the error you describe would occur if, when you unzipped my attachment, you tried to open the project by double-clicking on the "Form1.frm" file rather than the "Project1.vbp" file.
Please try the following:
Shut down VB.
In the folder where you downloaded and unzipped my attachment, double-click on the Project1.vbp file. This should open the project without error.
Thanks... It worked, but there's a problem ..
when you increase the number to 2 digits (>10) or more, instead of sorting it the normal way, the program will sort it like this,
1-10 :
1
10
2
3
4
.
.
.
.
9
See the problem?
how do i fix this?
Oh and, is it possible to make listview to highlight the entire rows instead of just the first item?
e.g :
a1 a2 a3 a4
b1 b2 b3 b4
When you choose the first row, it will highlight a1 right?
Is there anyway to make it highlight a1,a2,a3 and a4 at the same time?
i need to make the rows to act as options, so i want them to be highlighted at the same time..is there anyway to do this?
And one last question, just to make sure cause i'm not familiar with listview..:P
how do i select combobox' content from a listview?
ex :
a combobox contains A, B, C
If the first row of listview is selected (clicked) this combobox will show A,
second row = B, and third row = C
For the numbers to sort properly, you have to format them in such a way so that they will sort correctly based on a character sort - the LV only sorts by character values - this is why the numbers in my example were formatted with "@@@@", which right-justifies and left-space-fills the value.
To be able to highlight an entire row, set the FullRowSelect property to True.
To allow multiple rows to be selected, set the MultiSelect property to True.
For the last item, you'll need to be more specific as far as what you want to do. In general to synch up the listview with another control, use the SelectedItem property of the Listview to get the currently selected value and then populate the corresponding control with that value. If you are starting with the other control, then you must loop through the ListItems of the Listview until you find a matching value and set the ListItem found to be the SelectedItem.
Thanks,
as for my last question, this is what i meant :
Code:
Option Explicit
'-----------------------------------------------------------------------------
Private Sub Form_Load()
'-----------------------------------------------------------------------------
Dim objLI As ListItem
Dim lngX As Long
With ListView1.ColumnHeaders
.Add , , "Str", ListView1.Width \ 4
.Add , , "Mag", ListView1.Width \ 4
.Add , , "Spd", ListView1.Width \ 4
.Add , , "Spr", ListView1.Width \ 4
End With
Set objLI = ListView1.ListItems.Add(, , Format$(1, "@@@@"))
objLI.SubItems(1) = Format$(3, "@@@@")
objLI.SubItems(2) = Format$(2, "@@@@")
objLI.SubItems(3) = Format$(2, "@@@@")
Set objLI = ListView1.ListItems.Add(, , Format$(10, "@@@@"))
objLI.SubItems(1) = Format$(31, "@@@@")
objLI.SubItems(2) = Format$(12, "@@@@")
objLI.SubItems(3) = Format$(12, "@@@@")
Set objLI = ListView1.ListItems.Add(, , Format$(4, "@@@@"))
objLI.SubItems(1) = Format$(6, "@@@@")
objLI.SubItems(2) = Format$(3, "@@@@")
objLI.SubItems(3) = Format$(7, "@@@@")
Combo1.AddItem "A"
Combo1.AddItem "B"
Combo1.AddItem "C"
End Sub
'-----------------------------------------------------------------------------
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
'-----------------------------------------------------------------------------
Dim objCH As ColumnHeader
With ListView1
If (.Sorted) And (ColumnHeader.SubItemIndex = .SortKey) Then
If .SortOrder = lvwAscending Then
.SortOrder = lvwDescending
Else
.SortOrder = lvwAscending
End If
Else
.Sorted = True
.SortKey = ColumnHeader.SubItemIndex
.SortOrder = lvwAscending
End If
For Each objCH In .ColumnHeaders
If objCH.Index = ColumnHeader.Index Then
.ColumnHeaders(objCH.Index).Icon _
= IIf(.SortOrder = lvwAscending, "Up", "Down")
Else
.ColumnHeaders(objCH.Index).Icon = 0
End If
Next
.Refresh
End With
End Sub
'-----------------------------------------------------------------------------
Private Sub combo1_click()
'-----------------------------------------------------------------------------
Select Case ListView1
Case
Combo1.ListIndex = 1
case
Combo1.ListIndex = 2
case
Combo1.ListIndex = 3
End Select
End Sub
When user select the first row, the combo box below it will show the first item, which is "A" in this case.
and selecting the second row would make the combobox to show "B",
what should i put after 'case' above?
Thanks microapls, but bruce already answered that..
...hmmm bruce, that's not exactly what i want,
i want to know how to highlight any content of the combobox using listview, not highlight it in the same order of the listview.
that was just an example...
What if.. say... there are 2 more combo boxes :
Combo3.AddItem "X"
Combo3.AddItem "Y"
Combo3.AddItem "Z"
Is it possible to do it this way?
Private Sub Combo1_Click()
Select Case ListView1
Case <-- (represent the first row in listview)
Combo1.ListIndex = 0 <--(A in the combobox1)
Combo2.ListIndex = 2 <--(3 in the combobox2)
Combo3.ListIndex = 1 <--(Y in the combobox2)
case <-- 2nd row
Combo1.ListIndex = 1 <--(B)
Combo2.ListIndex = 1 <--(2)
Combo3.ListIndex = 0 <--(X)
case <-- 3rd row
Combo1.ListIndex = 2 <--(C)
Combo2.ListIndex = 0 <--(1)
Combo3.ListIndex = 2 <--(Z)
End Select
End Sub
If it's possible,
What should i put after the "case" ?
That's just an example though, it doesn't have to be in that order.
Basically, what i want to know is how to select any content from the comboboxes using listview.
You see, my program has 5 comboboxes,
and when a row in the listview is selected,
it will show certain combinations of the items from the combo boxes..(like above example)
So each row represents a combination from the combo boxes.
That's why i'm trying to do it one by one..
When you select a listview item, you might be interested in a particular column. If you want the first column, you can reference it as ListView1.SelectedItem.Text, if you want the second column, you reference it as ListView1.SelectedItem.SubItems(1), if you want the third, it's ListView1.SelectedItem.SubItems(2), and so on. For the sake of argument, let's say we want to match the first column (ListView1.SelectedItem.Text) to an item in a combo box. That can be done as follows:
VB Code:
Private Sub ListView1_ItemClick(ByVal Item As MSComctlLib.ListItem)
' in this ItemClick event, the "Item" parameter coming in
Columns? But i was talking about rows...?
Or are you trying to say that it's not possible to select an item as a row?
And i don't understand the code you posted, no matter what column i select, it always shows "item not found in the combobox" message..
Is my question too confusing? Maybe it'd be clearer if i use real a example :
Code:
Option Explicit
'-----------------------------------------------------------------------------
Private Sub Form_Load()
'-----------------------------------------------------------------------------
Dim objLI As ListItem
Dim lngX As Long
With ListView1.ColumnHeaders
.Add , , "A", ListView1.Width \ 4
.Add , , "B", ListView1.Width \ 4
.Add , , "C", ListView1.Width \ 4
.Add , , "D", ListView1.Width \ 4
End With
Set objLI = ListView1.ListItems.Add(, , Format$(1, "@@@@"))
objLI.SubItems(1) = Format$(3, "@@@@")
objLI.SubItems(2) = Format$(2, "@@@@")
objLI.SubItems(3) = Format$(2, "@@@@")
Set objLI = ListView1.ListItems.Add(, , Format$(10, "@@@@"))
objLI.SubItems(1) = Format$(31, "@@@@")
objLI.SubItems(2) = Format$(12, "@@@@")
objLI.SubItems(3) = Format$(12, "@@@@")
Set objLI = ListView1.ListItems.Add(, , Format$(4, "@@@@"))
objLI.SubItems(1) = Format$(6, "@@@@")
objLI.SubItems(2) = Format$(3, "@@@@")
objLI.SubItems(3) = Format$(7, "@@@@")
Combo1.AddItem "A"
Combo1.AddItem "B"
Combo1.AddItem "C"
Combo2.AddItem "1"
Combo2.AddItem "2"
Combo2.AddItem "3"
Combo3.AddItem "X"
Combo3.AddItem "Y"
Combo3.AddItem "Z"
End Sub
'-----------------------------------------------------------------------------
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
'-----------------------------------------------------------------------------
Dim objCH As ColumnHeader
With ListView1
If (.Sorted) And (ColumnHeader.SubItemIndex = .SortKey) Then
If .SortOrder = lvwAscending Then
.SortOrder = lvwDescending
Else
.SortOrder = lvwAscending
End If
Else
.Sorted = True
.SortKey = ColumnHeader.SubItemIndex
.SortOrder = lvwAscending
End If
For Each objCH In .ColumnHeaders
If objCH.Index = ColumnHeader.Index Then
.ColumnHeaders(objCH.Index).Icon _
= IIf(.SortOrder = lvwAscending, "Up", "Down")
Else
.ColumnHeaders(objCH.Index).Icon = 0
End If
Next
.Refresh
End With
End Sub
Now what i want is something like this :
click the first row (1, 3, 2, 2)
A in the combobox1
3 in the combobox2
Y in the combobox3
click 2nd row (10, 31, 12, 12)
B in the combobox1
2 in the combobox2
X in the combobox3
click 3rd row (4, 6,3,7)
C in the combobox1
1 in the combobox2
Z in the combobox3
I'm not sure what more I can do here - I am not seeing the relationship between items in your listview and the item you want selected in your combo boxes. Let me give a few more general pieces of info, maybe you can use these to achieve your objectives.
(1) when you click a row in this ListView, the ItemClick event should fire, and "Item.Index" will tell you what the row is:
VB Code:
Private Sub ListView1_ItemClick(ByVal Item As MSComctlLib.ListItem)
MsgBox "You just clicked row # " & Item.Index
End Sub
(2) To pre-select an item from a combo box in code, you can loop through the items in the combo box testing the List property, and if the List(whatever_index) property is the one you want, then set the ListIndex property of the combo box to whatever_index. For example, let's say I want to pre-select the item "A" in the combobox, wherever in the list it may be:
VB Code:
Dim lngX As Long
For lngX = 0 To Combo1.ListCount - 1
If Combo1.List(lngX) = "A" Then
' found what I want, set ListIndex and exit loop
Combo1.ListIndex = lngX
Exit For
End If
Next
I hope this gives you the tools to proceed in the desired direction.
Rhinobull : I think you've shown me that program in my other thread, it doesn't show me what i want, but thanks anyway.
Bruce : I'm just using those numbers as examples, it doesn't have to be like that or in that order,
and there's no mathematical-relation between listview items and the combobox items if that's what you mean,
The relation's just like this :
Each row represent a set of items from the combo boxes, so when that row is clicked, the comboboxes will show the represented items
Now in my example, i want it to work like this :
click the first row (1, 3, 2, 2)
A in the combobox1
3 in the combobox2
Y in the combobox3
click 2nd row (10, 31, 12, 12)
B in the combobox1
2 in the combobox2
X in the combobox3
click 3rd row (4, 6,3,7)
C in the combobox1
1 in the combobox2
Z in the combobox3
Or maybe you'll understand it if you compare it with this listbox program
(See attachment)
Click each row in the listbox, the combo boxes next to it will show a set of items.
All i want to know is how do i make listview to work like that, it's that simple..
Yes, that's what i mean..
So it's like this, right?
Code:
Option Explicit
'-----------------------------------------------------------------------------
Private Sub Form_Load()
'-----------------------------------------------------------------------------
Dim objLI As ListItem
Dim lngX As Long
' Set up LV columns: 4 columns, each 1/4 the width of the LV
With ListView1.ColumnHeaders
.Add , , "A", ListView1.Width \ 4
.Add , , "B", ListView1.Width \ 4
.Add , , "C", ListView1.Width \ 4
.Add , , "D", ListView1.Width \ 4
End With
' populate 20 rows of the 4 columns with random numbers from 1 to 100
' format the numbers using "@@@@" meaning right-justify and space-fill
' this formatting will ensure proper numeric sorting (because the LV only does
' character-based sorts ...
Set objLI = ListView1.ListItems.Add(, , Format$(1, "@@@@"))
objLI.SubItems(1) = Format$(3, "@@@@")
objLI.SubItems(2) = Format$(2, "@@@@")
objLI.SubItems(3) = Format$(2, "@@@@")
Set objLI = ListView1.ListItems.Add(, , Format$(10, "@@@@"))
objLI.SubItems(1) = Format$(31, "@@@@")
objLI.SubItems(2) = Format$(12, "@@@@")
objLI.SubItems(3) = Format$(12, "@@@@")
Set objLI = ListView1.ListItems.Add(, , Format$(4, "@@@@"))
objLI.SubItems(1) = Format$(6, "@@@@")
objLI.SubItems(2) = Format$(3, "@@@@")
objLI.SubItems(3) = Format$(7, "@@@@")
Combo1.AddItem "A"
Combo1.AddItem "B"
Combo1.AddItem "C"
Combo2.AddItem "1"
Combo2.AddItem "2"
Combo2.AddItem "3"
Combo3.AddItem "X"
Combo3.AddItem "Y"
Combo3.AddItem "Z"
End Sub
'-----------------------------------------------------------------------------
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
'-----------------------------------------------------------------------------
Dim objCH As ColumnHeader
With ListView1
If (.Sorted) And (ColumnHeader.SubItemIndex = .SortKey) Then
If .SortOrder = lvwAscending Then
.SortOrder = lvwDescending
Else
.SortOrder = lvwAscending
End If
Else
.Sorted = True
.SortKey = ColumnHeader.SubItemIndex
.SortOrder = lvwAscending
End If
' Let's get fancy and show an up/down arrow in the column header
' indicating the sort direction ...
For Each objCH In .ColumnHeaders
If objCH.Index = ColumnHeader.Index Then
.ColumnHeaders(objCH.Index).Icon _
= IIf(.SortOrder = lvwAscending, "Up", "Down")
Else
.ColumnHeaders(objCH.Index).Icon = 0
End If
Next
.Refresh
End With
End Sub
Private Sub ListView1_ItemClick(ByVal Item As MSComctlLib.ListItem)
With ListView1.SelectedItem
If .Text = "1" And .SubItems(1) = "3" And .SubItems(2) = "2" And .SubItems(3) = "2" Then
Combo1.ListIndex = 0
Combo2.ListIndex = 2
Combo3.ListIndex = 1
ElseIf .Text = "10" And .SubItems(1) = "31" And .SubItems(2) = "12" And .SubItems(3) = "12" Then
Combo1.ListIndex = 1
Combo2.ListIndex = 1
Combo3.ListIndex = 0
ElseIf .Text = "4" And .SubItems(1) = "6" And .SubItems(2) = "3" And .SubItems(3) = "7" Then
Combo1.ListIndex = 2
Combo2.ListIndex = 0
Combo3.ListIndex = 2
End If
End With
End Sub
It still won't work though...the comboboxes won't show the items.
I've tried changing the method into select case and it won't work too...what could be wrong huh?
The example I gave you earlier formatted each number right-justified in 4 characters (using the "@@@@" format). Thus, the latest example I gave you should be like this:
VB Code:
If .Text = " 1" And .SubItems(1) = " 23" And .SubItems(2) = " 62" And .SubItems(3) = " 14" Then
- or -
VB Code:
If Val(.Text) = 1 And Val(.SubItems(1)) = 23 And Val(.SubItems(2)) = 62 And Val(.SubItems(3)) = 14 Then