How can I control a ComboBox after another? - vba

The code shows three ComboBox in a UserForm. Combobox2 pick four values ​​1, 2, 3, 4 from the sheet ("Data") and Combobox3 pick 6 values ​​(A, B, C, D, E, F) from the same sheet.
What should I do if I want to control Combobox3 after the value is chosen in Combobox2, such as If I choose 1 I want to just A, B, C should be in Combobox3, or if I choose 2 then only D, E found in Combobox3, etc.?
Thanks in advance for any suggestions!
Private Sub RapportFix_Initialize()
Dim ComboItems As Variant, i As Integer
Dim val As String
With RapportFix.ComboBox2 'Provtyp
.Clear ' remove existing entries from the listbox
ComboItems = Worksheets("Indata").Range("C5:C8").Value
ComboItems = Application.WorksheetFunction.Transpose(ComboItems)
' convert values to a vertical array
For i = 1 To UBound(ComboItems)
.AddItem ComboItems(i) ' populate the combobox
Next i
.ListIndex = -1 ' no items selected, set to 0 to select the first item
End With
With RapportFix.ComboBox3 'Kursplan
.Clear ' remove existing entries from the listbox
'Set sKursplanemoment = ComboBox3.Value
ComboItems = Worksheets("Indata").Range("M5:M10").Value
ComboItems = Application.WorksheetFunction.Transpose(ComboItems)
' convert values to a vertical array
For i = 1 To UBound(ComboItems)
.AddItem ComboItems(i) ' populate the combobox
Next i
.ListIndex = -1 ' no items selected, set to 0 to select the first item
End With
With RapportFix.ComboBox4 'Annat arbete
.Clear ' remove existing entries from the listbox
ComboItems = Worksheets("Indata").Range("E5:E8").Value
ComboItems = Application.WorksheetFunction.Transpose(ComboItems)
' convert values to a vertical array
For i = 1 To UBound(ComboItems)
.AddItem ComboItems(i) ' populate the combobox
Next i
.ListIndex = -1 ' no items selected, set to 0 to select the first item
End With
RapportFix.Show
End Sub

Each user form control has a number of events associated with it. The change event suggested by Cody is particularly easy to find as all you have to do is right-click the control in design view and choose "View Code", a sub outline will then be filled in.
As you can see above, there are two dropdown lists above the code page, one lists the controls and objects available and one lists the events. Choose a control and an event to get the outline sub for that event.
In this particular case, you need to use the change event of the controlling combo to first clear and then repopulate the dependent combo, just as you have done above. These are called cascading combos.
Private Sub ComboBox2_Change()
''Populate combo 3
End Sub
The only difference is you need to check that the list contains only those items that should appear for each value of the controlling combo. I would be inclined to do this with a list on a worksheet that I could easily control:
Item2 Item3
1 a
1 b
2 d
2 c
3 a
3 e
However, this does not seem possible for you, so you may wish to use Select Case
Private Sub ComboBox2_Change()
Select Case ComboBox2
Case "1", "2", "3"
''Add items x,y,z to combobox3
Case "a", "b", "c"
''Add items m,n,o to combobox3
Case Else
''Whatever
End Select
End Sub

Related

How to display Userform Scrollable Listbox value?

In a userform that I create, I add a scrollable listbox (2 columns, 7 rows) and a button.
When I click the button, the value in the third column should change, and the listbox should display the new value accordingly.
Currently particular rows fail to display the new value even I change it already. I also notice that the rows that fail to display the new value are those not showing in the scrollable list box when I click the button.
When I click the button once, the second column of each row is - as expected - increased by 1:
However, when I click the button a second time, the rows that are not displayed in the scrollable listbox at the moment, fail to increase by 1 again:
This is the code I have so far:
Private Sub CommandButton1_Click()
For i = 0 To lstProducts.ListCount - 1
lstProducts.List(i, 1) = lstProducts.List(i, 1) + 1
Next i
End Sub
Private Sub UserForm_Initialize()
Dim iCell As Long
VBA.Randomize
With lstProducts
.ColumnCount = 2
.ColumnWidths = "120;60;50"
.List = Worksheets("Product").Range("a1").CurrentRegion.Value
End With
End Sub
Replace your loop with this code
x = lstProducts.TopIndex
For i = 0 To lstProducts.ListCount - 1
lstProducts.ListIndex = i
lstProducts.List(i, 1) = lstProducts.List(i, 1) + 1
Next i
lstProducts.ListIndex = x

Microsoft Form - If Checkbox Cell Value Greater Than

First post on this forum - I have a fillable form which I would like to do the following.
There are two check boxes, (Legacy form item), labelled H and N, depending on which one is selected the value of another input box (Legacy form item) should be equal to or greater than a value. E.G if N is selected, the input cell should be greater than 0.5 if H is selected the cell should be equal to or greater than 0.5.
Can anyone impart any wisdom on this one, I would then set it to run a check once the user has input the value, based on the checkbox option and value input into the cell.
Thanks in advance,
Daniel
You have 3 objects and you need to react on any change. So I'd put something like this into the code section of the form:
Private Sub cbN_Click() ' name of checkbox N is cbN
proc_chg
End Sub
Private Sub cbH_Click()
proc_chg
End Sub
Private Sub tbx_Change() ' name of textbox is tbx
proc_chg
End Sub
Private Sub proc_chg
Dim rVal as Single
rVal = Val(Me.tbx.value)
If cbN And rVal > 0.5 Then
tbx.BackColor = vbGreen ' OK
ElseIf cbH And rVal >= 0.5 Then
tbx.BackColor = vbGreen ' OK
Else
tbx.BackColor = vbRed ' wrong
End If
End Sub
This will capture every change on the form and set the background color of the inputbox accordingly. (Please complete the logic in proc_chg, this is just an example.)

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

Comparison of two listbox in VBA

I am new at VBA.So kindly help me on this matter.
My UserForm has two ListBox controls in it, each with two columns. For example, ListBox1
Name Item
A 20
B 30
and listbox2:
Name Item
A 20
B 40
When I click a CommandButton, the procedure below attempts to compare both ListBox controls and returns whether or not the data in each column of data is correct. I believe the best approach would be to first compare Column 1 of ListBox1 with Column 1 of ListBox2. If those are identical, then compare the second columns of both ListBox controls. The procedure is supposed to return a MsgBox that says "Correct" if all columns are identical. Otherwise, the program should return a mismatch error. Here is the code I've tried so far.
Private Sub CommandButton1_Click()
Dim p As Integer, Tabl()
Redim Tabl(0)
For i = 0 To ListBox1.ListCount - 1
p = p + 1
Redim Preserve Tabl(p)
Tabl(p) = ListBox1.List(i)
Next i
For i = 0 To ListBox2.ListCount - 1
If IsNumeric(Application.Match(ListBox2.List(i), Tabl, 0)) Then
Msgbox"Correct"
End If
Next i
End Sub
Unfortunately, the program only calculates the first column repeatedly. How can I compare multiple columns?
Based on your description and a small evaluation of what your code does, you may be overthinking this. How about the following?
Private Sub CommandButton1_Click()
Dim myMsg As String
Dim byeMsg As String
myMsg = "Same name chosen."
byeMsg = "Those names don't match."
If ListBox1.Value = ListBox2.Value Then
MsgBox myMsg
Else
MsgBox byeMsg
End If
End Sub
Of course, instead of displaying a message using MsgBox, you could just as easily replace it with any code you need.

Multi Select List Box

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