Userform listbox click code does not trigger - excel

I created a userform in Excel 2016 with two ListBoxes, using the Tools menu. I double clicked them to create subs and inserted code to check whenever one is selected.
Here is the code:
Private sub SaleType_Click ()
If SaleType.Value ="Core" then
'make sale label visible
QTDV.visible =true
' show core option btn
Core.Visible = true
End if
End sub
When I have a ListBox created from the toolbox this works, but every other time the form is run the saletype ListBox will be value null and this is a problem because I have a check to make sure the ListBox is not empty. Code follows:
If saletype = "" then
Dim msg as string Msg = " please select sale type"
Msgbox msg, and vbcritical
End if
If the ListBox presents value null it will not see it as empty and skip the check if I try saletype = null it still skips it.
I searched and it seems creating ListBoxes on the tool box is weird because Excel does not know what kind of control it is. I opted for creating the ListBoxes in VBA.
Private sub userform_initialize()
Dim saletype as msforms.Listbox
Set saletype = me.Controls.Add("Forms.ListBox.1", "SaleType")
But when running the form and selecting any option on the ListBox the SaleType_Click sub does not trigger.

If you want to implement event handling (like SaleType_Click) you need to declare the object with the WithEvents keyword:
Dim WithEvents saletype as msforms.Listbox
And if a variable/property is not set then its value doesn't exist, so instead of empty string ("") you need to validate for NULL - the IsNull function can do that (= NULL doesn't work as = only works with values):
If IsNull (saletype.Value) then

I just had a problem with my listbox_Click not being fired "every other time". Maybe it was when the same selection was desired twice in a row. Anyway, put this in the sheet code for the sheet that is "Show"ing the userform:
userformXXX.listboxYYY.ListIndex = -1
userformXXX.Show
This doesn't work if it is in the userform code.

Related

Object required error enabling/disabling combobox/checkbox based on a combobox

I'm working on a sheet that has a repeating series of one combobox linked to one other combobox and a checkbox.
The first box has four selectable options.
If either of the first two options is selected, both the second combobox and the checkbox should be disabled.
If either of the last two options is selected, the second box and checkbox should both become enabled.
When I first set up this code, everything worked. I accidently threw myself into an endless loop and had to start with the "Excel recovered" worksheet, which scrubbed all my controls.
I re-did the controls. Now when I open the workbook, I have to click through fifty (yes, no joke, five-zero) instances of an "object required" run-time error. The same thing happens when I close the workbook. But when I clear all the errors, the code runs. Using "Option Explicit" gives me a "variable not defined" error.
I can't identify any variables which need defining.
Sub ComboBox1_Change()
If ComboBox1.ListIndex = 2 Or ComboBox1.ListIndex = 3 Then
ComboBox6.Enabled = True
CheckBox1.Enabled = True
Else: ComboBox6.Enabled = False
CheckBox1.Enabled = False
End If
End Sub
This is for one instance. I have twenty-five of these repeated, one after the other, in my project.
FYI you can avoid most of that replicated code by using a naming scheme which allows you to associate your sets of 3 controls: eg see below. Then you can have one single procedure which performs the checks, given the first combobox as an argument.
e.g. (you can probably come up with more-meaningful names based on what your controls actually represent):
ComboBox1 - ComboBox1_2 - chkComboBox1
ComboBox2 - ComboBox2_2 - chkComboBox2
ComboBox3 - ComboBox3_2 - chkComboBox3
Then your code can look like this:
Option Explicit
Private Sub ComboBox1_Change()
ProcessChange ComboBox1
End Sub
Private Sub ComboBox2_Change()
ProcessChange ComboBox2
End Sub
'process the supplied combobox value and set properties of
' any related controls
Sub ProcessChange(cmbo As ComboBox)
Dim en As Boolean
en = cmbo.Value = 2 Or cmbo.Value = 3
Me.OLEObjects(cmbo.Name & "_2").Object.Enabled = en
Me.OLEObjects("chk" & cmbo.Name).Object.Enabled = en
End Sub

Assign Macro To Listbox OnSelectionChange (not OnAction)

How to assign macro to the listbox on the Excel spreadsheet not OnAction, but on Selection_Change? Listbox is added via "Developer/Insert/Form Controls. It is NOT the listbox from Userforms.
The problem is if I try to scroll the options in the listbox, then the macro launches, because scrolling is considered as action by Excel. However I'd like macro to run only in case if the user chooses (selects/deselects) some option from the listbox.
I was trying to find some method for the "Shapes" collection. However, did not find any.
Store your Listindex in a variable and check if it is changed:
(for single select:)
Public myIndex As Long
Sub ListBox1_Change()
With ActiveSheet
If .ListBoxes(1).ListIndex = myIndex Then Exit Sub
myIndex = .ListBoxes(1).ListIndex
End With
Debug.Print "your macro"
End Sub
Make sure on opening of the file myIndex gets populated with the Listindex
and Adjust name of ListBox and (1) accordingly

How can I run a userform from a macro?

I developed many UDFs and macros in VBA for Excel 2016. One of my macros uses an Inputbox to get data used subsequently by the macro. I want to replace the Inputbox with a user form. I have created the user form, with one text box. I want to activate the user form, populating the text box with the default data, and return the text box data to the macro when OK is selected. I have searched extensively for an end-to-end example for all the the code needed to do this, with no luck. Does an example for this simple problem exist?
Add a Property to your user form. For this answer, let us use the following code within the user form.
Public Property Get MyResult() As String
' You may want to do any manipulation here
' including converting to a number, in which case the return type should be changed (*)
MyResult = TextBox1.Text
End Property
(*) If you are doing conversion, you can have another function in your user form to disable the "OK" button until they have valid convertible data in the text box.
You also want to know if they have hit "Cancel"
Public Property Get Cancelled() As Boolean
Cancelled = pCancelled ' Declare pCancelled as a Boolean in the scope of the form
End Property
Public Sub CancelButton_Click() ' Standard click event for the button
pCancelled = True
Me.Hide
End Sub
Public Sub OKButton_Click() ' Standard click event for the button
pCancelled = False
Me.Hide
End Sub
In your calling macro
MyForm.Show ' This is modal, so will block execution until a response is provided
If Not MyForm.Cancelled Then
Debug.Print MyForm.MyResult
'Do something with MyForm.MyResult
End If
UnLoad MyForm ' assuming you do not want to re-use this form as part of your logic.
There is an example of how you can pass the value to a form and get the result back. The approach uses Scripting.Dictionary object created within standard module scope and passed to userform to allow values to be changed. So it makes possible to send the default values to userform, and keep the result values in the dictionary even after the userform is closed and unloaded. You may have multiple values, just add the necessary quantity of keys to the dictionary, e. g. oData("property1"), oData("property2"), etc.
Add a standard module to the project and put the below code into it:
Option Explicit
Sub Test()
Dim oData
' Set default value and show form
Set oData = CreateObject("Scripting.Dictionary")
oData("") = "Some default text"
UserForm1.ShowForm oData
' Wait until user close form
Do While IsUserFormLoaded("UserForm1")
DoEvents
Loop
' Output returned value
MsgBox oData("")
End Sub
Function IsUserFormLoaded(UserFormName As String) As Boolean
Dim oUF As Object
For Each oUF In UserForms
If LCase(oUF.Name) = LCase(UserFormName) Then
IsUserFormLoaded = True
Exit Function
End If
Next
End Function
Add a userform module named UserForm1 to the project, place controls as shown:
And put the below code into the userform module :
Private opData
Public Sub ShowForm(oData)
Set opData = oData
Me.TextBox1.Value = opData("")
Me.Show
End Sub
Private Sub UserForm_Initialize()
If TypeName(opData) <> "Dictionary" Then Set opData = CreateObject("Scripting.Dictionary")
End Sub
Private Sub CommandButton1_Click()
Unload Me
End Sub
Private Sub CommandButton2_Click()
opData("") = Me.TextBox1.Value
Unload Me
End Sub

Listbox is being set to Null somehow in excel-vba user form

Context: I am coding a user form which will have some filters to run a procedure and fill a worksheet with the return value.
I am having trouble with one of my filters. I was able to reproduce my issue in a reduced version. This filter should load data into a listbox based on the selected combobox option:
I didn't rename anything, the components are: UserForm1, ListBox1 and ComboBox1.
My broken code (commented):
Option Explicit
'sub that fill data in the list box columns
Sub loadList(list As ListBox, id As Integer)
list.Clear
If (id > 0) Then
list.AddItem
list.Column(0, 0) = "Item 1"
list.AddItem
list.Column(0, 1) = "Item 2"
End If
End Sub
'event that will trigger the loadList sub
Private Sub ComboBox1_Change()
Dim id As Integer
id = ComboBox1.ListIndex
loadList ListBox1, id
End Sub
'the combo options is auto initialized
Private Sub UserForm_Initialize()
ComboBox1.AddItem
ComboBox1.Column(0, 0) = "Option 1"
ComboBox1.AddItem
ComboBox1.Column(0, 1) = "Option 2"
End Sub
When I set a brekpoint I can see the problem. The ListBox1 is being set to Null, but I don't know how to work around it:
The error says:
Run-time error '13': Type mismatch
But it is obvious because the ListBox1 is being set to Null somehow.
Have anyone experienced this behaviour before? How to work around it? Thanks in advance.
Strange as it looks, there are two classes named ListBox from different libraries, and VBA confuses them (the same applies to all controls actually). It depends on whether you are using the MSForms controls or the ActiveX controls.
In your case, you should disambiguate with MSForms.ListBox which is the actual type of your listbox.
Sub loadList(list As MSForms.ListBox, id As Integer)
' ^^^^^^^
To avoid such doubts, you can also use list As Object, (would make your sub handle both types as long as you use only the common methods).

excel vba: show message on dropdown list selection change if changed more than once?

I am trying to create a piece of vba code which will generate a message to the user when a user selects a value from a dropdown list/validation list in excel.
So far my script does this fine. However, I want the user to be able to select their first value from the dropdown list without getting a message, and then on the second, third or fourth time etc, if they should change their selection in the dropdown list I want the message to display.
Can someone please show me a way of doing this? Thanks in advance
'Check number of times a user has changed their selection
Dim rM As Range
Set rM = Range("M" & ActiveCell.Row).Cells.SpecialCells(xlCellTypeAllValidation)
If Intersect(Target, rM) Is Nothing Then
Else
MsgBox "changed"
End If
Add ..
Private BooRangeSelected as Boolean
... at the very top of the VBA code.
Set this value to False in the Initialize event.
Set this value to True when the dropdown list is updated.
If the value is already True when the dropdown list is selected then issue the message.
I'm assuming this macro is attached to a Workbook rather than a Form stored in "personal.xlsb". In Excel / view code double click the "ThisWorkbook" icon (see below
Private Sub Workbook_open()
Private BooRangeSelected as Boolean
BooRangeSelected = False
End Sub
This sets the variable to False once the Worksheet is opened. You can then set this to True once the dropdown has been selected
BooRangeSelected = True

Resources