Multi Select List Box - vb.net

I have a list box on a form and it works fine for what I want to do.
I am wanting to edit items on the form, this means populating the listbox and then selecting the relevant items.
My listbox contains a list of item sizes, i want to select the sizes which belong to the item being edited.
PLease can someone give me some pointers.
I tried me.lstItemSizes.SetSelected(i,true) but this only works for a single item.
Any help wil be much appreciated.
My Code:
Private Sub SelectItemSizes(ByVal itemID As Integer)
Dim itemSizes As IList(Of ItemSize) = _sizeLogic.GetItemSizes(itemID)
Me.lstItemSizes.SelectionMode = SelectionMode.MultiExtended
If (itemSizes.Count > 0) Then
For i As Integer = 0 To Me.lstItemSizes.Items.Count - 1
For x As Integer = 0 To itemSizes.Count - 1
If (CType(Me.lstItemSizes.Items(i), PosSize).SizeID = itemSizes(x).SizeID) Then
Me.lstItemSizes.SetSelected(i, True)
Else
Me.lstItemSizes.SetSelected(i, False)
End If
Next
Next
End If
End Sub

Did you set the selectionmode to multi?
You need to specify that in order to allow multiple selections.
Then you can do:
Dim i as Integer=0
For i=0 To Me.listBox.SelectedItems.Count -1
'display the listbox value
next i
Here is a screen shot:
After you set the property on the listbox then call setselected based on the values you want selected.
me.lstItemSizes.SetSelected(3,true)
me.lstItemSizes.SetSelected(4,true)
me.lstItemSizes.SetSelected(9,true)
Here you can add 20 numbers and only select the even.
Dim i As Integer
'load the list with 20 numbers
For i = 0 To 20
Me.ListBox1.Items.Add(i)
Next
'now use setselected
'assume only even are selected
For i = 0 To 20
If i Mod 2 = 0 Then
Me.ListBox1.SetSelected(i, True)
End If
Next
3rd edit
Look at the way you are looping, lets assume I create a list of integers, my vb.net is rusty I mainly develop in C#. But assume you did this:
Dim l As New List(Of Integer)
l.Add(2)
l.Add(6)
l.Add(20)
You only have three items in your list, so first loop based on the items on your list, then within the items in your listbox, you have it vice versa. Look at this:
Dim i As Integer
Dim l As New List(Of Integer)
l.Add(2)
l.Add(6)
l.Add(20)
'load the list with 20 numbers
For i = 0 To 20
Me.ListBox1.Items.Add(i)
Next
Dim lCount As Integer = 0
For lCount = 0 To l.Count - 1
For i = 0 To 20
If i = l.Item(lCount) Then
Me.ListBox1.SetSelected(i, True)
Exit For
End If
Next
Next
In the code my l is a list of just 3 items: 2, 6, and 20.
I add these items to l which is just a list object.
So now I have to loop using these 3 numbers and compare with my listbox. You have it the opposite you are looping on your listbox and then taking into account the list object.
Notice in my for loop that once the item in my list is found I no longer need to loop so I exit for. This ensures I dont overdue the amount of looping required. Once the item is found get out and go back to the count of your list object count.
After running my code here is the result

You have to change the ListBox.SelectionMode property in order to enable multiple-selection.
The possible values are given by the SelectionMode enum, as follows:
None: No items can be selected
One: Only one item can be selected
MultiSimple: Multiple items can be selected
MultiExtended: Multiple items can be selected, and the user can use the Shift, Ctrl, and arrow keys to make selections
So, you simply need to add the following line to the code you already have:
' Change the selection mode (you could also use MultiExtended here)
lstItemSizes.SelectionMode = SelectionMode.MultiSimple;
' Select any items of your choice
lstItemSizes.SetSelected(1, True)
lstItemSizes.SetSelected(3, True)
lstItemSizes.SetSelected(8, True)
Alternatively, you can set the SelectionMode property at design time, instead of doing it with code.

According to MSDN, SetSelected() can be used to select multiple items. Simply repeat the call for each item that needs to be selected. This is the example they use:
' Select three items from the ListBox.
listBox1.SetSelected(1, True)
listBox1.SetSelected(3, True)
listBox1.SetSelected(5, True)
For reference, this is the MSDN article.

Because my code had the following loops:
For i As Integer = 0 To Me.lstItemSizes.Items.Count - 1
For x As Integer = 0 To itemSizes.Count - 1
If (CType(Me.lstItemSizes.Items(i), PosSize).SizeID = itemSizes(x).SizeID) Then
Me.lstItemSizes.SetSelected(i, True)
Else
Me.lstItemSizes.SetSelected(i, False)
End If
Next
Next
The first loop loops through the available sizes and the second loop is used to compare the item sizes.
Having the following code:
Else
Me.lstItemSizes.SetSelected(i, False)
End If
Meant that even if item i became selected, it could also be deselected.
SOLUTION:
Remove Me.lstItemSizes.SetSelected(i, False) OR Include Exit For

Related

Transferring items from one listBox to another list

i have ListBox1 and ListBox2 and textbox
I want the following when setting a value in a TextBox. If the value in ListBox is1, then items are moved from the current value to the last items in not the first. to listbox2
Dim foo As String
Dim index As Integer = 0
Dim good As Integer = 0
foo = TextBox1.Text
ListBox2.Items.Clear()
For i = 0 To ListBox1.Items.Count - 1
If ListBox1.Items(i).ToString = foo Then
index = i
End If
If i >= index Then
ListBox2.Items.Add(ListBox1.Items(good).ToString)
End If
Next
As Lars has noted in a comment, the index is 0 at the beginning so the condition i >= index wil be always true. So you need to intialize it with Int32.MaxValue.
You add always the first item, because good is always 0. You should use the loop variable i:
ListBox2.Items.Add(ListBox1.Items(i).ToString())
Here is a LINQ version which simplifies the whole code, you don't need more:
ListBox2.Items.Clear()
Dim allAfter = ListBox1.Items.Cast(Of Object).SkipWhile(Function(item) Not TextBox1.Text.Equals(item))
ListBox2.Items.AddRange(allAfter.ToArray())

How to add multiple checkboxes in multiple columns (VBA)

I have a ListView with multiple columns. More precisely, the ListView contains 8 columns. 2 of them should be filled with checkboxes.
Currently only the first column contains checkboxes. It is defined as follows:
While Not rs.EOF
//first column with checkboxes
ListViewCustomer.ListItems.Add , , rs("Id")
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).tag = rs("Status")
//second column etc.
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).ListSubItems.Add , , rs("name")
....
//Here is the second column, which doesn't display the checkboxes
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).ListSubItems.Add , , IIf(IsNull(rs("date_from")), "", rs("date_from"))
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).tag = rs("Status2")
Wend
Do anyone have an idea how to add the checkboxes in the last column?
EDIT:
Is it possible to realize this column with adding via .Controls?
A ListView is a more expanded version of the ListBox control.
See ListBox control on msdn as well.
They both display records of rows (the ListView has more advanced formatting options). This however means that a record is a row. Therefore you select a row when you select one of the items.
The function of the checkbox is to allow the user to mark the row(s) that is the records(s) he selects.
Thus there is only one checkbox per row, at the front of the row.
Consider this code (this is Excel 2003 VBA, but gives you the idea):
Private Sub UserForm_Initialize()
Dim MyArray(6, 8)
'Array containing column values for ListBox.
ListBox1.ColumnCount = 8
ListBox1.MultiSelect = fmMultiSelectExtended
'Load integer values MyArray
For i = 0 To 5
MyArray(i, 0) = i
For j = 1 To 7
MyArray(i, j) = Rnd
Next j
Next i
'Load ListBox1
ListBox1.List() = MyArray
End Sub
You could do a custom ListBox or ListView if you really want. You could create a frame and put Labels and CheckBoxes on it. This is the only way to do this in Excel2003 where I tested. The ListBox object has no Controls child.
But this is more like a datagrid and not really a ListBox or ListView which by definition are a listing of records (rows).
Update:
I saw your update and that you really want to place the CheckBox at the end of the row.
If you only want one checkbox at the last row, you could do this custom checkbox. Again this is written for the ListBox, so need to convert it to your ListView if you want to.
Still requires a custom handling, but I had some time, so I did this code. See if you like it:
Private Sub ListBox1_Change()
For i = 0 To ListBox1.ListCount - 1
ListBox1.List(i, 3) = ChrW(&H2610)
Next i
ListBox1.List(ListBox1.ListIndex, 3) = ChrW(&H2611)
End Sub
Private Sub UserForm_Initialize()
Dim MyArray(5, 3)
'Array containing column values for ListBox.
ListBox1.ColumnCount = 4
ListBox1.MultiSelect = 0
ListBox1.ListStyle = 0
'Load integer values MyArray
For i = 0 To 5
MyArray(i, 0) = i
For j = 1 To 2
MyArray(i, j) = Rnd
Next j
MyArray(i, 3) = ChrW(&H2610)
Next i
'Load ListBox1
ListBox1.List() = MyArray
End Sub

Index out of range in listbox VB.NET

Consider the following code :
Private Sub DelButton_Click(sender As Object, e As EventArgs) Handles DelButton.Click
If OrderListBox.Text = "" = False Then
For i As Integer = OrderListBox.SelectedIndex To arr.Count - 1
arr.RemoveAt(i)
Next
OrderListBox.Items.Remove(OrderListBox.SelectedItem)
End If
calculate()
End Sub
The program crashes at arr.RemoveAt(i) and displays the following error:
Index was out of range. Must be non-negative and less than the size
of the collection.
First of all, please note that in VB.NET and C#, FOR loops are implemented differently!
In VB.NET, it works like this:
BEFORE the loop starts, you are determining start and end of the loop:
Start = OrderListBox.SelectedIndex
End = arr.Count-1
Then, the loop starts.
It is important to know, that in VB.NET, the end of the loop is NOT calculated again anymore. This is an important difference to C#. In C#, the end of the loop is calculated before each single loop.
And now, in the loop, you are DELETING records from the array.
Therefore, the count of records in the array is DECREASING.
However, your loop is going on, since you have calculated the count of records in the array before the loop started.
Therefore, you are going beyond the range of the array.
You could rewrite your code as follows:
Dim i as Integer
i = OrderListBox.SelectedIndex
while i < arr.Count
arr.RemoveAt(i)
Next
This article covers details about the for loop in VB.NET, especially the section "Technical Implementation": https://msdn.microsoft.com/en-us/library/5z06z1kb.aspx
This error will be thrown when you try to remove an item at an index greater than the size of the collection. i.e when i is greater than arr.Count - 1.
You should make sure that OrderListBox.SelectedIndex is not greater than arr.Count - 1. Because if it does, you remove an item that, well, does not exists.
This code is actually displayed in the MSDN docs. As stated, you should do something like this:
Private Sub RemoveTopItems()
' Determine if the currently selected item in the ListBox
' is the item displayed at the top in the ListBox.
If listBox1.TopIndex <> listBox1.SelectedIndex Then
' Make the currently selected item the top item in the ListBox.
listBox1.TopIndex = listBox1.SelectedIndex
End If
' Remove all items before the top item in the ListBox.
Dim x As Integer
For x = listBox1.SelectedIndex - 1 To 0 Step -1
listBox1.Items.RemoveAt(x)
Next x
' Clear all selections in the ListBox.
listBox1.ClearSelected()
End Sub 'RemoveTopItems
ListBox.SelectedIndex will return a value of negative one (-1) is returned if no item is selected.
You didn't check it in your code.
Change your code to this:
If OrderListBox.SelectedIndex >= 0 And OrderListBox.Text = "" = False Then
EDIT
Your code is this:
For i As Integer = OrderListBox.SelectedIndex To arr.Count - 1
arr.RemoveAt(i)
Next
Let's say your OrderListBox contains 3 items : [A, B, C] and the SelectedIndex is 0
Then your code will:
Remove (0) ===> [B, C]
Remove (1) ===> [B]
Remove (2) ===> Exception!
You need to reverse the loop
For i As Integer = arr.Count - 1 To OrderListBox.SelectedIndex Step -1
arr.RemoveAt(i)
Next

Using selected values in an Excel list box to formulate the legend

I am attempting to pass the selected values from a list box in Excel to legend in a chart. Specifically, I have data of certain companies in the following format
And I also have a list box, globalList, which contains the names of companies that can be selected. Selected companies' data will then be passed onto a chart using VBA.
However, the problems I encounter are in the following sections:
Initialising a variable to hold values selected in the globalList
listMax = globalList.ListCount - 1
`this creates the upper bound for the list box
For i = 0 To (globalList.ListCount - 1)
If globalList.Selected(i) = True Then
companiesSelected = companiesSelected + 1
End If
If i = listMax Then
Exit For
End If
Next i
`the above is used to retrieve the number of companies that have been selected by a user - whether =0 or > 0
Dim myLegend() As String
ReDim myLegend(0 To (globalList.ListCount - 1))
For i = 0 To (globalList.ListCount - 1)
If globalList.Selected(i) = True Then
myLegend(i) = globalList.List(i)
End If
If i = listMax Then
Exit For
End If
Next i
`this is the array object in which I intend to store company names selected in the list box.
The problem is that even though the above creates the myLegend string array, it also contains empty array items for the companies that may not have been selected by the user in the list box.
And even if I am able to remove these empty items from the array, the following problem occurs
Passing the held values from my variable to my chart
For i = 1 To companiesSelected
myChart.SeriesCollection(i).Name = myLegend(i)
Next i
Problem here is that myLegend array starts from 0, while SeriesCollection seems to start from 1. So I am unable to pass the string values for selected items to the legend of my chart's.
Could somebody please point out how to circumvent these problems?
Many thanks in advance!
Here is a code to extract the selected items into an one-based array of String (without empty items):
Dim i As Integer
Dim iCount As Integer
Dim myLegend() As String
iCount = 0
With globalList
ReDim myLegend(1 To .ListCount)
For i = 0 To .ListCount - 1
If .Selected(i) = True Then
iCount = iCount + 1
myLegend(iCount) = .List(i)
End If
Next i
End With
If iCount > 0 Then
ReDim Preserve myLegend(1 To iCount)
Else
ReDim myLegend(1 To 1)
myLegend(1) = "Nothing here!"
End If

Not able to add values in second Combobox

Here is my code.
for example TextBox1.Text= 12,34,45,67,67
Dim process_string As String() = TextBox1.Text.Split(New Char() {","})
Dim process As Integer
For Each process In process_string
Combo1.Items.Add(process)
count = count + 1
Next process
total_process.Text = count
End If
Dim array(count) As String
Dim a As Integer
For a = 0 To count - 1
array(a) = Combo1.Items(a).ToString
Next
a = 0
For a = count To 0
Combo2.Items.Add(array(a).ToString)
Next
i want to add values in reversed order in combobox2 that are available in combobox1
but when i run the application the second combobox remains empty and not showing any value.
You've specified this for loop
For a = count To 0
But you need to add STEP -1 to go backwards like that.
For a = count To 0 Step -1
2 things. First of all, K.I.S.S. Keep it simple stupid
For i As Integer = ComboBox1.Items.Count - 1 To 0 Step -1
ComboBox2.Items.Add(ComboBox1.Items(i))
Next
second: It didn't work because you forgot the Step -1 on your last loop
~~~~~~~~~~~~~~Edit~~~~~~~~~~~~~~
Sorting the data in a combo box should be done with the sorted property on a combo box
ComboBox3.Sorted = True
Sorting the data in reverse order should be done with arrays as you were trying to do before. The following code should suffice:
Dim List As ArrayList = ArrayList.Adapter(ComboBox3.Items)
List.Sort()
List.Reverse()
ComboBox4.Items.AddRange(List.ToArray)
If you wanted to get creative, you could potentially create your own combo box class and make your own version of the sorted property that allows for "sort alpha", "sort numeric", "sort alpha Desc", and "sort numeric desc" and perhaps some other options. But I'd only do that if you were going to use this in a lot of places.