Get the last selected item in multiselect box - excel

I have add a ListBox from Active X Controls in my Excel File and made it a multi select box with checkboxes.
I have also added a selection change event in the VB script against this list box.
Sub lstMultiSelectBox_Change()
If blnCheck = False Then
CheckAll
End If
End Sub
Now what I am struggling to find is that which item was last checked. With this information I want to implement Select All and Un Select All feature in this list box.

In order to make ListBox1_Change event returning the last selected list box value, you can use the solution. It can detect the selected value, independent of its position in the list:
Create a Private variable on top of the sheet module where the list box exists (in the declarations area):
Private colS As New Collection
Then copy the next adapted event code:
Private Sub ListBox1_Change()
Dim i As Long
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then
If colS.Count = 0 Then
colS.Add ListBox1.List(i), ListBox1.List(i)
Else
If Not itExists(colS, ListBox1.List(i)) Then
colS.Add ListBox1.List(i), ListBox1.List(i)
End If
End If
Else
If itExists(colS, ListBox1.List(i)) Then
colS.Remove ListBox1.List(i): Exit Sub
End If
End If
Next i
If colS.Count > 0 Then MsgBox colS(colS.Count)
End Sub
If you want it triggering only if the selected value is "Select All", then replace the last event code line with something like:
If colS.Count > 0 Then
If colS(colS.Count) = "Select All" then
'do whatever you need in such a case
'but, if you try selecting all of lines, in order to avoid the event
'being triggered again, you should use 'Application.EnableEvents = False`, before selecting and 'Application.EnableEvents = True` after
End If
End If
The simplest solution should be the one suggested in the first comment:
If Listbox1.Selected(1) = True Then
'do whatever you need
End If
But, in order to make it working as it should, the line "Select All" should be the second of the list...

Related

Excel Combo Box Refresh Dropdown?

Is there a way to refresh a combobox?
I have the following VBA code. The dropdown is populated, until the If statement where the list is cleared and populated with the matched items.
At this point, the dropdown list only shows a single item with a scroll bar. But If I close the pulldown and reopen, it's fully populated correctly.
Private Sub ComboBox_SiteName_Change()
ComboBox_SiteName.DropDown
Dim v As Variant, i As Long
With Me.ComboBox_SiteName
.Value = UCase(.Value)
If .Value <> "" And .ListIndex = -1 Then
v = Worksheets("Address").Range("Table5[[#All],[SITE NAME]]").Value
.Clear ' Clear all items
' Repopulate with matched items
For i = LBound(v, 1) To UBound(v, 1)
If LCase(v(i, 1)) Like "*" & LCase(.Value) & "*" Then
.AddItem v(i, 1)
End If
Next i
Else
' Repopulate with all items
.List = Worksheets("Address").Range("Table5[[#All],[SITE NAME]]").Value
End If
End With
End Sub
The ComboBox_Change function gets called as the user types in the combo box.. the dropdown box turns from a list into a single line with Up/Down arrows after the Clear and Repopulate matched items..
but if I close the dropdown portion and reopen it lists all the items without Up/Down arrows.
The .ListRows value = 8 by the way.
I would like a way for the dropdown potion to either close and reopen.. or a VBA function to refresh the dropdown portion, Without external buttons or controls Please
Getting the list to ONLY show values that matched the text typed by the user so far, was a nightmare. Below is what I wrote which works (but took me a while!)
Note that the MacthEntry Property of the combo box MUST be set to "2 - frmMatchEntryNone" for the code to work. (Other values cause the combo box .value property store the text of the first value that matches what the user typed, and the code relies on it storing what they typed.)
Also note, the trick to get around the behaviour you observed, ie the combo boxes list of values not being sized correctly, was to use the code lines:
LastActiveCell.Activate
ComboBox_SiteName.Activate
Also, the code will pick up any items on the list that have the letters typed by the user ANYWHERE in their text.
Anyway, here's my code:
Private Sub ComboBox_SiteName_GotFocus()
' When it first gets the focus ALWAYS refresh the list
' taking into acocunt what has been typed so far by the user
RePopulateList FilterString:=Me.ComboBox_SiteName.Value
Me.ComboBox_SiteName.DropDown
End Sub
' #4 Private Sub ComboBox_SiteName_Change()
Private Sub ComboBox_SiteName_Enter()
Dim LastActiveCell As Range
On Error GoTo err_Handler
Set LastActiveCell = ActiveCell
Application.ScreenUpdating = False
With Me.ComboBox_SiteName
If .Value = "" Then
' Used cleared the combo
' Repopulate will all values
RePopulateList
.DropDown
Else
' #4 reducdant
' LastActiveCell.Select
' .Activate
' ===========================================
' #4 new code
' CheckBox1 is another control on the form
' which can receive the focus and loose it without event firing
CheckBox1.SetFocus
' This will trigger the GotFocus event handler
' which will do a refresnh of the list
.SetFocus
' ===========================================
End If
End With
Application.ScreenUpdating = True
Exit Sub
err_Handler:
Application.ScreenUpdating = True
Err.Raise Err.Number, "", Err.Description
Exit Sub
Resume
End Sub
Private Sub RePopulateList(Optional FilterString As String = "")
Dim i As Long
Dim ValidValues() As Variant
' #2 range now refers to just the data cells
ValidValues = Worksheets("Address").Range("Table5[SITE NAME]").Value
With Me.ComboBox_SiteName
If FilterString = "" Then
' All all values
.List = ValidValues
Else
' #2: .List cannot be set to have no items.
' so remove all but one
.List = Array("Dummy Value")
' Only add values that match the FilterString parameter
For i = LBound(ValidValues, 1) To UBound(ValidValues, 1)
If LCase(ValidValues(i, 1)) Like "*" & LCase(FilterString) & "*" Then
.AddItem ValidValues(i, 1)
End If
Next i
' #2 add this line to remove the dummy item
.RemoveItem (0)
End If
End With
End Sub
Private Sub ComboBox_SiteName_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Application.ScreenUpdating = False
End Sub
======================================================================
You could: Replace all your code with this which should give acceptable functionality (as long a the data source is in alpha order), and it's easy! However, it doesn't quite do what you wanted.
Private Sub ComboBox_SiteName_GotFocus()
With Me.ComboBox_SiteName
.List = Worksheets("Address").Range("Table5[[#All],[SITE NAME]]").Value
End With
ComboBox_SiteName.DropDown
End Sub
Combo boxes can be set up to "filter as the user types" - so long as the data is in alphabetical order.
======================================================================
Note that in your code the following two lines cause the ComboBox_SiteName_Change event to start again. I suspect you need to add break points and debug you code more.
.Value = UCase(.Value)
.Clear ' Clear all items
Anyway, I hope this is job done.
this will be my first bounty if I get it, so please let me know if you need any more help. (I think it may be worth more than 50 points)
Harvey
================================================
PART 2:
To answer you comment issues:
(See the #2 tag in my code above)
To refer to a table column's data, excluding the header use:
=Table5[SITE NAME]
(This will be autogenerated when entering a formula if you click and drag over the data cells in a column).
The code has been altered accordlingly.
I used excel 2013 and 2010 and found that the .Activate event works in both.
See #3 for a minor change.
Please recopy all the code.
note that I introduced code to try and stop flickering using Application.ScreenUpdating, but it didn;t have any effect - I don't know why. I've left the code in so you can do further experiments should you need to.
NOTE the new procedure ComboBox_SiteName_KeyDown
================================================
PART 3:
To answer you comment issues:
It's a combo on a form ! - so make the change tagged with #4 above.
Harvey
Solved!
https://trumpexcel.com/excel-drop-down-list-with-search-suggestions/
You can do what is in the link with some modifications:
"ListFillRange" in combobox properties should be the last column (the one that is changing). If it is a userform the range will go under "RowSource".
And add this code:
Private Sub ComboBox1_Change()
Sheets("Where the data is").Range("B3") = Me.ComboBox1.Value
End Sub
Try changing the command from Change to DropButtonClick
This refreshes the list on a click of the drop down

Require selection - Excel VBA List Box

I have an Excel UserForm, which submits data to a worksheet. I have built in data validation that requires each text box to have a value entered, e.g.:
Private Sub Button_Submit_Click()
'Data Validation
If Me.txtCVS.Value = "" Then
Me.txtCVS.SetFocus
MsgBox "'CVs Screened' is a mandatory field. Enter daily figure or zero.", vbOKOnly, "Required Field"
Exit Function
However, I don't know what code to use to require a selection from a list box - users select their name from the list box before entering in their daily figures. Some users, it seems, can't remember to click their name(!!!).
Does anybody have a piece of workable code I can use to require a selection before submitting results? It doesn't seem to work in the same way as the text box text above.
You can use the below function which iterates through all the items in the listbox and returns true/false if anything is selected or not.
Private Sub Button_Submit_Click()
If Not IsAnythingSelected(ListBox1) Then
MsgBox "Please select your name"
End If
End Sub
Function IsAnythingSelected(lBox As Control) As Boolean
Dim i As Long
Dim selected As Boolean
selected = False
For i = 1 To lBox.ListCount
If lBox.selected(i) Then
selected = True
Exit For
End If
Next i
IsAnythingSelected = selected
End Function
Try changing
For i = 1 to lBox.ListCount
to the following:
For i = 0 To lBox.ListCount - 1

Troble with updating the list box

I have Created a excel user form with three Combo box and list box with 3 columns.
When user selects a value from drop down list and click Add button it will be displayed in the list box - Done
When user selects a item in the list box it will again displays in drop down list - done
But when user selects the item in the list box and click update button its calling the ListBox
_click () function, I dont want it to call the listbox_click function
PLease help. updating the code
Code for adding value from drop down list to list box
Private Sub cmdAdd_Click()
Call lstValues.AddItem(AddPpayTierOption(cboPpayTier.Value))
lstValues.List(UBound(lstValues.List), COL_BRAND) = cboBrandTier.Value
lstValues.List(UBound(lstValues.List), COL_GEN) = cboGenTier.Value
End Sub
when clicks the item in the list box it will display the value in drop down list
Private Sub lstValues_Click()
Dim I As Long
cmdEdit.Enabled = True
cmdRemove.Enabled = True
If lstValues.ListIndex <> -1 Then
For I = 0 To lstValues.ColumnCount - 1
If I = 0 Then
cboPpayTier.Value = lstValues.Column(I)
Else
If I = 1 Then
cboBrandTier.Value = lstValues.Column(I)
Else
If I = 2 Then
cboGenTier.Value = lstValues.Column(I)
End If
End If
End If
Next I
End If
End Sub
when user click the update button code.
when it goes to lstValues.Column(j) = cboPpayTier.Value line its calling the lstValues_Click() function I don't want code to call that function. Please Help
Private Sub cmdEdit_Click()
Dim j As Long
Dim var As Variant
If lstValues.ListIndex <> -1 Then
For j = 0 To lstValues.ColumnCount - 1
If j = 0 Then
lstValues.Column(j) = cboPpayTier.Value
Else
If j = 1 Then
lstValues.Column(j) = cboBrandTier.Value
Else
If j = 2 Then
lstValues.Column(j) = cboGenTier.Value
End If
End If
End If
Next j
End If
End Sub
please let me for more clarification.
Two options:
Use Application.EnableEvents = False to disable event processing. And Application.EnableEvents = True to re-enable. Note, this disables all event handling, so place it either side of code that would otherwise trigger an event you don't want.
Declare a global flag. Set it just before code that will trigger an event you don't want. In the Event Sub itself, examine the flag, and exit if it's set. Reset the flag either on the other side of the event triggering code, or in the event Sub itself. Doesn't stop the event firng, but stops it executing code you don't want.
As requested, example of option 2
In a standard module, at the top (just after Option Explicit), add this code
Global InhibitEvent As Boolean
In your code
' Somewhere in your code,
' when you are about to execute some logic that will trigger an event
InhibitEvent = True
'... event triggering logic here
InhibitEvent = False
In the Event Sub that you don't want to execute (eg a listBox Change event)
Private Sub ListBox1_Change()
' Look for Event Inhibit
If InhibitEvent Then Exit Sub
' rest of event code here
End Sub
Try using a List as the data source of list box. When updating, first put datasource of listbox null then equal to List

Validate that at least 1 checkbox is checked

I have search for the same question, and I saw a few of the similar post, however my Userform still can't work. I am new to VBA and Userform.
I have a total of 12 Checkboxes (12 Months), and I have to check that at least one of the CheckBox is checked.
Dim atLeastOneChecked As Boolean
atLeastOneChecked = False
Dim ctrlNCK As Control
For Each ctrlNCK In Controls
If TypeName(ctrlNCK) = "chkMonth" Then
If ctrlNCK.Value = True Then atLeastOneChecked = True
End If
Next ctrlNCK
If Not atLeastOneChecked = True Then
MsgBox "Month cannot be empty.", vbExclamation, "Input Data"
Exit Sub
End If
This is untested, but try:
If Left(ctrlNCK.Name,8) = "chkMonth" Then
I wouldn't ever expect the Type to be "chkMonth". This assumes that each relevant CheckBox name starts with "chkMonth".
If you only ever want one, and only one, month chosen, I'd consider using OptionButtons in a Frame.
If (chbindian + chbchinies + chbitalian + chbsindian) = 0 Then
MsgBox "Please select at least Two checkbox"
Exit Sub
End If
try this
(chbindian + chbchinies + chbitalian + chbsindian) replace this names with your checkbox name
Using similar approach to the question code I came up with this:
Private Sub CommandButton1_Click()
Dim chk As Control
Dim i As Long
For Each chk In Me.Controls
If TypeOf chk Is MSForms.CheckBox Then
If chk = 0 Then
i = i + 1
End If
End If
Next
If i = 12 Then
MsgBox "Please select at least one month!"
Exit Sub
End If
MsgBox "You selected at least one month!"
End Sub
To explain:
The For loop is checking one by one each CheckBox on the UserForm.
If the value of the CheckBox is 0 (False) then the counter which is the i variable equals it's own value at the end of the previous iteration (current value) + 1.
Each CheckBox with a value of 0 (False) meaning it's 'unchecked' adds 1 to the counter and thus, once the loop is complete i will equal anywhere between 0 (all CheckBoxes are checked) and 12 (no CheckBoxes are checked).
After the loop is exited the next if statement checks if the value of the counter i is equal to 12 then a MsgBox displays "Please select at least one month!" otherwise whatever is meant to happen next will now execute (In my example its another MsgBox advising "You selected at least one month!").
NOTE: If more CheckBoxes were added to the UserForm at a later time for whatever reason, my solution would be flawed as it will check ALL CheckBox commands on the form.
To work around that you can put the required CheckBoxes on a Frame on the UserForm.
Assuming the Frame is named Frame1 all you would need to do is adjust the For line to specify for each CheckBox in Frame1 on the UserForm like so: For Each chk In Me.Frame1.Controls

Disable or hide options in combo box VBA Excel

I have a combo box in a Excel Userform that consist of User Group Types.
Depending on the user access level, I would like to have some Option\item disable or not visible.
I don't want to use Removeitem, Because I would have to repopulate the list every time!
sub ComboBox_Enter()
accessLvl = 1
ComboBox.AddItem "0-Show"
ComboBox.AddItem "1-Hide or disable"
ComboBox.AddItem "2-Show"
ComboBox.AddItem "3-Show"
For i = 0 To 3
if accessLvl = 1 Then ComboBox.List(1).Hidden = True ' This not does work!! ''
Next
End sub
I just want it to be disabled\grayed out or not visible but still in the Combobox list!*
AFAIK, you can't do that but there is an alternative. The user will not be able to select certain items (whichever you specify) even though it will be visible and not disabled.
For this try this code
Dim boolC As Boolean
'~~> Add Sample data
Private Sub UserForm_Initialize()
ComboBox1.AddItem "Please Choose Again"
For i = 1 To 10
ComboBox1.AddItem i
Next i
End Sub
'~~> This will not let the user select items in 2nd
'~~> 3rd and 4th items
Private Sub ComboBox1_Change()
If Not boolC Then
boolC = True
Select Case ComboBox1.ListIndex
Case 1, 2, 3: ComboBox1.ListIndex = 0
End Select
boolC = False
End If
End Sub
Screenshot
Let's say your form looks like this on form start up.
The moment you select the 2nd ,3rd or the 4th item, you will get Please Choose Again

Resources