I have 5 checkboxes to set some options for a macro, one of them is a Select/Unselect All checkbox. I want to create something similar to what you have on web-based mailboxes when you select mails to delete or mark as read, etc.
When I check the Select/Unselect All checkbox, I turn the rest of the checkboxes's values to true and viceversa when I uncheck it. That's ok.
The problem comes when I also want to validate that if everything is unchecked and one by one I check the other checkboxes, if in the end I check all, then the Select/Unselect All checkbox turns to checked. And viceversa, meaning that if eveything is checked and then I uncheck one of the four others, then I turn the "All" checkbox to false (unchecked).
But it seems that even when I just set the value, for example Option1Checkbox.value = True, in the SelectAllCheckbox_Click event, it triggers both the Option1Checkbox_Click and Option1Checkbox_Change events.
Shouldn't it just trigger the Change event since I'm not actually clicking that checkbox?
What happens is that I check the SelectAll, so it turns Option1 to checked, but by doing this, Option1 triggers also the click event so it unchecks it which triggers the click event again and then unchecks again the All checkbox which in the end leaves everything unchecked, like at the beginning. Hope this part is clear enough.
How can I avoid this behavior? How can I make sure only the Change event is triggered and not the Click event?
Has anyone ever had such an arrangement of checkboxes and had a similar problem? Or how did you manage to do this without the behavior I'm getting?
The checkboxes are not on a form but simply on a worksheet. They are ActiveX controls. And what I have is nothing complicated:
Private Sub SelectAll_Click()
Option1Checkbox.Value = SelectAll.Value
Option2Checkbox.Value = SelectAll.Value
Option3Checkbox.Value = SelectAll.Value
Option4Checkbox.Value = SelectAll.Value
End Sub
Then the options checkboxes click events look like this:
Private Sub Option1Checkbox_Click()
If Option1Checkbox.Value = True And Option2Checkbox.Value = True And Option3Checkbox.Value = True And Option4Checkbox.Value = True Then
SelectAll.Value = True
Else
SelectAll.Value = False
End If
End Sub
It's quite simple, the biggest problem I see is the calls to the click events when the checkbox is not actually click.
Thanks for your help.
I would define a local variable (one defined outside the subs) and set/check that
Option Explicit
Dim ImChangingStuff As Boolean
Private Sub SelectAll_Click()
ImChangingStuff = True
Option1Checkbox.Value = SelectAll.Value
Option2Checkbox.Value = SelectAll.Value
Option3Checkbox.Value = SelectAll.Value
Option4Checkbox.Value = SelectAll.Value
ImChangingStuff = False
End Sub
then your click routines would look like this:
Private Sub Option1Checkbox_Click()
If ImChangingStuff Then Exit Sub
If Option1Checkbox.Value = True And Option2Checkbox.Value = True And Option3Checkbox.Value = True And Option4Checkbox.Value = True Then
SelectAll.Value = True
Else
SelectAll.Value = False
End If
End Sub
To solve this problem,
in your main userform (in this example it is called Mainform) add this code:
Private Sub Mainform_Initialize()
stateCheckbox = True
End Sub
Create a module to store your global variables (eg. globalVariables), and add the following, which will hold the state of the checkbox:
Public stateCheckbox as Boolean
In the _click event of your checkbox, wrap your code like this:
if stateCheckbox = false then
{ whatever your code is }
Else:
stateCheckbox = false
end if
I have had the same issue as described above. I recognized that each change of a Checkbox, no matter if by click or by changing Checkbox.Value, each time first fires the Checkbox_Change event and then the Checkbox_Click event , provided that any of these events are declared.
I would thus recommend to use only one event for each checkbox, p.e. the Checkbox_Change event, and to check if the checkbox has been changed by click or by declaration at the beginning of the Sub. This can be done by comparing the ActiveControl.Name with the Checkbox.Name:
Private Sub CheckBox1_Change()
On Error Goto Err:
If ActiveControl.Name = CheckBox1.Name Then
On Error Goto 0
'Commands for click
Exit Sub
Else
On Error Goto 0
'Commands for change from within the Userform
Exit Sub
Err:On Error Goto 0
'Commands for change from outside the Userform
End Sub
I would write a sub checking if Option1 to Option4 are all checked in an If statement. In a second if statemement, I'd check to see if they are all false:
Sub Are_O1_to_O4_All_Checked ()
If Option1Checkbox.Value = True And _
Option2Checkbox.Value = True And _
Option3Checkbox.Value = True And _
Option4Checkbox.Value = True Then
Option5Checkbox.Value = True ' select/unselect checkbox
End If
If Option1Checkbox.Value = False And _
Option2Checkbox.Value = False And _
Option3Checkbox.Value = False And _
Option4Checkbox.Value = False Then
Option5Checkbox.Value = False ' select/unselect checkbox
End If
End Sub
Then I would Call this sub at the end of each OnClick event for the check boxes.
Related
Situation
I have two form control check boxes. I am trying to write a code that will allow only either of them to be true.
my code is
Sub CheckBox2_Click()
If CheckBox1.Enabled = True Then
CheckBox2.Enabled = False
Else
If CheckBox2.Enabled = True Then
CheckBox1.Enabled = False
End If
End If
End Sub
I have this code in module and have assigned the same macro for both the checkboxes. I get run-time error 424. I beleive this is very basic problem but I unable to dela with it.
Thank you
Please, test the following way. Form check boxes do not have a click event, as ActiveX ones have. You should associate the next sub to both of them. The check boxes I tested, have their names as "Check Box 1" and "Check Box 2". You have to change yours according to the reality in your case, Please, copy the next code in a standard module and then associate it to both used check boxes:
Option Explicit
Sub FormCheckBoxChange()
If ActiveSheet.CheckBoxes(Application.Caller).value = 1 Then
Select Case Application.Caller
Case "Check Box 1": ActiveSheet.CheckBoxes("Check Box 2").value = -4146
Case "Check Box 2": ActiveSheet.CheckBoxes("Check Box 1").value = -4146
End Select
End If
End Sub
Use instead of the used check box names, the appropriate ones for your case.
In case of Form text boxes, their value is not True and False as in case of ActiveX ones. It is 1 and -4146...
Are you sure you want to enable/disable the checkboxes.
Following code makes sure that either one of both boxes is checked.
Public Sub checkbox2_onClick()
Dim oCb1 As Object
Set oCb1 = Table1.Shapes("Checkbox1").OLEFormat.Object
Dim oCb2 As Object
Set oCb2 = Table1.Shapes("Checkbox2").OLEFormat.Object
If oCb2.Value = 1 Then oCb1.Value = 0
End Sub
Public Sub checkbox1_onClick()
Dim oCb1 As Object
Set oCb1 = Table1.Shapes("Checkbox1").OLEFormat.Object
Dim oCb2 As Object
Set oCb2 = Table1.Shapes("Checkbox2").OLEFormat.Object
If oCb1.Value = 1 Then oCb2.Value = 0
End Sub
I asked a similar question this morning and i got a great answer, but then i pushed a little bit further and this is where i'm kinda stuck.
This is my initial post : Unselect an entire optionbutton group if another optionbutton outside the group is selected
But now, I would like to have this:
If OptionButton1.Value = True or OptionButton2.Value = True then Grey out OptionButton4 to OptionButton11 (Also gave it a group name : "Category").
But, If OptionButton3.Value = True, then it ungreys the OptionButton4 to OptionButton11 (Group Category).
EDIT:
I did something and it worked but once I run my userform and generate a number (userform purpose), the optionbuttons stay greyed out. Here's the code i used :
Private Sub OptionButton1_Click()
OptionButton4.Enabled = False
OptionButton5.Enabled = False
OptionButton6.Enabled = False
OptionButton7.Enabled = False
OptionButton8.Enabled = False
OptionButton9.Enabled = False
OptionButton10.Enabled = False
OptionButton11.Enabled = False
End Sub
Private Sub OptionButton2_Click()
OptionButton4.Enabled = False
OptionButton5.Enabled = False
OptionButton6.Enabled = False
OptionButton7.Enabled = False
OptionButton8.Enabled = False
OptionButton9.Enabled = False
OptionButton10.Enabled = False
OptionButton11.Enabled = False
End Sub
EDIT 2:
My solution for now is to add
Unload Me
UserForm1.Show
so it reset my userform and remove the greyed optionbuttons
That looks like you solved your own issue. Another would be to create a validation sub that would actually check everything every time an option is selected. Also there is a way to access all the forms controls something like Forms('myform').controls('mycontrol') I admit I am rusty but if you iterate through you can disable enable as wanted and call that on load
Instead of unloading and reloading the form, handle the enabling/disabling.
Create a common procedure to handle the enabling/disabling so that you do not have to duplicate the code.
You can loop through all the controls which will not only reduce the lines of the code but will be easier to maintain.
Is this what you are trying?
Option Explicit
Private Sub OptionButton1_Click()
EnableOptBtns False
End Sub
Private Sub OptionButton2_Click()
EnableOptBtns False
End Sub
Private Sub OptionButton3_Click()
EnableOptBtns True
End Sub
Private Sub EnableOptBtns(enable As Boolean)
Dim ctl As Control
Dim i As Long
For i = 4 To 11
Me.Controls("OptionButton" & i).Enabled = enable
Next i
End Sub
I want to do something like this. Don't know if it is possible in Excel VBA. On a user form, I have a checkbox and a text box.
When I check the checkbox, the checkbox's caption will be inserted into the text box, when I uncheck the checkbox, the checkbox's caption will be removed from the same text box.
When i write into the text box the caption of the checkbox, inside the text box change event, the checkbox status will be updated. And at the same moment, the checkbox click event is fired and the caption text will be doubled. How can I stop the checkbox click event from firing twice?
Checkbox's click event code:
Private Sub cbSelect_Click()
With TextBox1
.Value = IIf(cbSelect.Value, _
.Value & cbSelect.Caption, _
Replace(.Value, cbSelect.Caption, vbNullString))
End With
End Sub
Text box's change event code:
Private Sub TextBox1_Change()
If InStr(TextBox1.Value, cbSelect.Caption) Then
cbSelect.Value = 1
Else
cbSelect.Value = 0
End If
End Sub
Any idea?
When I tested your code, the checkbox status did not change which I believe is due to the use of binary values (1 / 0) instead of Boolean (True / False)
I changed your Textbox1_Changecode to the following and as soon as I delete part of the checkbox c
Private Sub TextBox1_Change()
If InStr(TextBox1.Value, cbSelect.Caption) Then
cbSelect.Value = True
Else
cbSelect.Value = False
End If
End Sub
I added a Public TextBoxFlag As Boolean at the User_Form module level, and this "flag" is being modifed and checked in both Control's events.
Once the code enters the TextBox1_Change event the flag gets a True value, and when the code reaches the cbSelect_Click event, it doesn't run the code inside if the value of TextBoxFlag = True, only if it's False (didn't came from the TextBox1_Change event, but directly from the CheckBox1 event).
Code
Option Explicit
Public TextBoxFlag As Boolean
Private Sub cbSelect_Click()
' check if event came from the value being modified in the TextBox1_Change event
If TextBoxFlag = False Then
With TextBox1
.Value = IIf(cbSelect.Value, _
.Value & cbSelect.Caption, _
Replace(.Value, cbSelect.Caption, vbNullString))
End With
End If
End Sub
Private Sub TextBox1_Change()
' raise the flag >> came from TextBox change event
TextBoxFlag = True
If InStr(TextBox1.Value, cbSelect.Caption) > 0 Then
cbSelect.Value = True
Else
cbSelect.Value = False
End If
' reset the flag
TextBoxFlag = False
End Sub
your code actually worked for me without the issue you described just substituting:
InStr(Me.TextBox1.Value, Me.cbSelect.Caption)
with :
InStr(Me.TextBox1.Value, Me.cbSelect.Caption) > 0
BTW here's some possibly useful coding advices :
I'd always use Me keyword and refer to Userform controls.
this will also have Intellisense help you in finding UserForm controls names
your cbSelect.Value setting code can be shortened to one line
as a result of all what above:
Private Sub TextBox1_Change()
Me.cbSelect= InStr(Me.TextBox1.Value, Me.cbSelect.Caption) > 0
End Sub
Private Sub cbSelect_Click()
With Me.TextBox1
.Value = IIf(Me.cbSelect, _
.Value & Me.cbSelect.Caption, _
Replace(.Value, Me.cbSelect.Caption, vbNullString))
End With
End Sub
So I'm making a userform and I have to use make a group of mutually exclusive checkboxes or only allow the user to pick one. "But just use option buttons!" you cry. Two problems with that:
I already have a separate set of option buttons in the userform (I believe you can somehow group them to allow multiple sets but I am unfamiliar with how to actually do this).
My professor specifically wants checkboxes
so I attempted to solve this problem like this
If CheckBoxBar.Value = True And CheckBoxatm.Value = True Then
GoTo Here:
End If
If CheckBoxatm.Value = True And CheckBoxmmHg.Value = True Then
GoTo Here:
End If
If CheckBoxatm.Value = True And CheckBoxpsia.Value = True Then
GoTo Here:
End If
If CheckBoxBar.Value = True And CheckBoxmmHg.Value = True Then
GoTo Here:
End If
If CheckBoxBar.Value = True And CheckBoxpsia.Value = True Then
GoTo Here:
End If
If CheckBoxmmHg.Value = True And CheckBoxpsia.Value = True Then
GoTo Here:
End If
The here leads to a message box that re initializes the userform after the msg box says "You are only allowed to select one" with code like this
Here: MsgBox "You are only allowed to select on pressure unit."
The code "works" but it always goes to the Here: statement despite only picking one of the checkboxes. Can you spot anything wrong?
Thanks for the help!
As stated by Doug Glancy in a comment, your current code is probably missing an Exit Sub before the label Here:, which is therefore allowing your code to fall into the section after the label.
Another way of achieving what you are after is just to have one If statement which checks if more than one CheckBox is checked, and then display the MsgBox if so, e.g. as follows:
If CheckBoxBar.Value + _
CheckBoxatm.Value + _
CheckBoxmmHg.Value + _
CheckBoxpsia.Value < -1 Then
MsgBox "You are only allowed to select one pressure unit."
Exit Sub
End If
Or you can rely on the .Value being the default property of a CheckBox and thus "reduce" that code to:
If CheckBoxBar + CheckBoxatm + CheckBoxmmHg + CheckBoxpsia < -1 Then
MsgBox "You are only allowed to select one pressure unit."
Exit Sub
End If
Note: This method won't work if the .TripleState property of the CheckBox is set to True. (My thanks to Comintern for pointing that out.)
You can make the checkboxes act like option buttons if you override the click function and clear the other boxes (although you can also have none selected).
Private Sub CheckBoxatm_Click()
If Me.Controls("CheckBoxatm").Value = True Then Call ClearOtherValues("CheckBoxatm")
End Sub
Private Sub CheckBoxBar_Click()
If Me.Controls("CheckBoxBar").Value = True Then Call ClearOtherValues("CheckBoxBar")
End Sub
Private Sub CheckBoxmmHg_Click()
If Me.Controls("CheckBoxmmHg").Value = True Then Call ClearOtherValues("CheckBoxmmHg")
End Sub
Private Sub CheckBoxpsia_Click()
If Me.Controls("CheckBoxpsia").Value = True Then Call ClearOtherValues("CheckBoxpsia")
End Sub
Private Function ClearOtherValues(cb As String)
Dim cbPressure() As String, i As Long
cbPressure = Split("CheckBoxBar,CheckBoxatm,CheckBoxmmHg,CheckBoxpsia", ",")
For i = 0 To UBound(cbPressure)
If cbPressure(i) <> cb Then Me.Controls(cbPressure(i)).Value = False
Next i
End Function
I have 4 form control option buttons on a sheet. I am trying to set a hard stop before print function if all 4 option buttons have been left unchecked.
I've successfully gotten all my checkboxes (used shapes not form control) to prompt if left blank but am getting nothing for the buttons.
If ActiveSheet.OptionButtons("button3") = Unchecked _
And ActiveSheet.OptionButtons("button20") = Unchecked _
And ActiveSheet.OptionButtons("button45") = Unchecked _
And ActiveSheet.OptionButtons("buttonEpic") = Unchecked Then
MsgBox "Missing"
Cancel = True
End If
End Sub
I also tried = False and .value = false. All buttons are currently unchecked but it's not prompting the message box or the hard stop.
Thanks for any help!
a very simple workaround since I am able to identify the checked option button on the worksheet but not if it's un-checked. I just identify if one of the 4 buttons is checked, do nothing if that's true and cancel if false.
Private Sub Workbook_BeforePrint (Cancel as Boolean)
With ActiveSheet
If .Optionbuttons ("button1").Value = Checked _
Or .Optionbuttons ("button2").Value = Checked _
Or .Optionbuttons ("button3").Value = Checked Then
Exit Sub
Else: Msgbox "Please select an option"
Cancel = True
End If
End With
End Sub