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
Related
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.
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).
I have imported a table with check-boxes from Access to Excel. Is it possible to set the check-boxes where only one check-box can be selected from that imported table when using Excel?
In the comments Jeeped made an excellent point that radio buttons already have the functionality that you are looking for. On the other hand -- if you prefer the aesthetics of checkboxes then you can certainly use them. I created a userform with two checkboxes in a frame (and no other controls in the frame) and also included a label for displaying the chosen option. The following code deselects all other checkboxes in the frame when one is selected. I used a non-local Boolean variable to circumvent the other checkbox's event handlers while they were being changed to avoid a sort of echo effect I ran into where the events were firing when I didn't want them to (perhaps there is a less kludgy way to do that). The code easily extends to any number of checkboxes in a grouping frame.
Dim selecting As Boolean 'module level variable
Private Sub SelectOne(i As Long)
Dim c As Control
selecting = True
For Each c In Frame1.Controls
If c.Name <> "CheckBox" & i Then c.Value = False
Next c
DoEvents
Label1.Caption = i & " selected"
selecting = False
End Sub
Private Sub CheckBox1_Click()
If Not selecting Then SelectOne 1
End Sub
Private Sub CheckBox2_Click()
If Not selecting Then SelectOne 2
End Sub
I think this works best and its much easier - at least for a few boxes - for more you could write some formulas in excel and drag down then copy as values and copy paste text from excel into vba. Anyway, here it's how I did it:
I went and created code under each button - quite basic
Private Sub DateCheckBox1_Click()
If DateCheckBox1.Value = True Then
DateCheckBox2.Value = False
DateCheckBox3.Value = False
End If
End Sub
Private Sub DateCheckBox2_Click()
If DateCheckBox2.Value = True Then
DateCheckBox3.Value = False
DateCheckBox1.Value = False
End If
End Sub
Private Sub DateCheckBox3_Click()
If DateCheckBox3.Value = True Then
DateCheckBox2.Value = False
DateCheckBox1.Value = False
End If
End Sub
I have a macro which is basically working as I want (alerting the user when two conflicting checkboxes are selected) - code below. The 1 in G2 is the value generated to indicate this case.
The error message fires on SelectionChange, but this appears to be only when another cell is selected by mouse. The worksheet contains a series of checkboxes for the user to select from, and the intention is for the user to only use the checkboxes, never needing to select or input directly into cells. In which case, the error message would never fire even when the scenario described has occurred.
Is there a way of having a msgbox macro trigger by the update of any checkbox on the sheet?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("G2") = 1 Then
MsgBox "ERROR - Select AND Reject checked"
End If
End Sub
Also, I would like to extend the range to apply to all the cells in column G, I just can't seem to get this to work for me. I have seen a few examples citing "G:G" but I have so far only got this to work for one cell.
Apologies in advance for any glaring errors, I've used Excel for a while now - but I'm brand new to using VBA.
Mutually exclusive options are usually indicated with option buttons (also known as radio buttons) instead of checkboxes. Is there any reason you're not using option buttons for this task?
As far as calling the same code for all checkboxes, the checkboxes would have to be Form Controls (not ActiveX Controls), and you could assign them to this macro:
Sub CheckBox_Clicked()
Dim chk As CheckBox
Set chk = ActiveSheet.CheckBoxes(Application.Caller)
MsgBox chk.Name
End Sub
And lastly, for your SelectionChange event to monitor an entire column, it would look similar to this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim ClickedCell As Range
Dim rngClicked As Range
Application.EnableEvents = False
Set rngClicked = Intersect(Columns("G"), Target)
If Not rngClicked Is Nothing Then
For Each ClickedCell In rngClicked.Cells
If ClickedCell.Value = 1 Then MsgBox "ERROR - Select AND Reject checked"
Next ClickedCell
End If
Application.EnableEvents = True
End Sub
I have the following groups of check-boxes and radio groups and was wondering how I would validate them each separately in VBA. Can anybody point me in the right direction?
For example I would require that at least checkbox is selected in the weeks group and each of the radio button groups (priority, lecturestyle, roomstruc and roomtype) just require a selection to be made. I would appreciate any code to show me how to accomplish this.
weeks - checkboxes
chk_week1, chk_week2, chk_week3, chk_week4, chk_week5,..., chk_week15
priority - radio buttons
priority_y, priority_n
lecturestyle - radio buttons
lecturestyle_trad, lecturestyle_sem
roomstruc - radio buttons
roomstruc_tiered, roomstruc_flat
roomtype - radio buttons
roomtype_lecture, roomtype_lab
You can try something like this. Naming a frame priority could return weird results so I have renamed your frames frPriority and frLectureStyle
Sub cbValidate_Click()
Dim ctl As Control, strOption As String, lLoop As Long
For lLoop = 1 To 15
If Me.Controls("chk_week" & lLoop).Value = True Then GoTo nxtCheck0
Next
MsgBox "You didn't select a week"
nxtCheck0:
For Each ctl In Me.frPriority.Controls
If ctl.Value = True Then GoTo nxtCheck1
Next
MsgBox "You didn't select a priority"
nxtCheck1:
For Each ctl In Me.frLectureStyle.Controls
If ctl.Value = True Then GoTo nxtCheck1
Next
MsgBox "You didn't select a lecture Style"
nxtCheck1:
Unload Me
End Sub
You might try something like the below coding as it gets tedious when you have many controls in group:
Insert a userform named “MyForm with checkboxes named “chk01”, “chk02”….”chk20 or however many checkboxes you want
Put the following declaration in a code module (not the form module)
Public CheckBoxGroup(1 To 20) As New MyForm
Put the following declarations in the form code
Public WithEvents ChkBoxGrp As CheckBox
Initialize the array in the form activate event
Private Sub UserForm_Activate()
Dim i As Integer
For i = 1 To 20 (or however many checkboxes you have
set CheckBoxGroup (i).ChkBoxGrp = MyForm("chk" + Right("0" + CStr(i), 2))
Next i
End Sub
Private Sub ChkBoxGrp_Click()
Select Case val(Right(ChkBoxGrp.Name, 2))
Case 1
‘Do whaever you want for chk01 box
Case 2
‘Do whaever you want for chk01 box
……………
End Select
End Sub
You can use the same event handling for other checkbox events