How to handle Checkbox value in VBA? - vba

I have the following example:
Private Sub setCheck(ByVal val1 As Boolean, ByVal val2 As Boolean, ByVal val3 As Boolean)
With userForm1
.checkboxOne.Value = val1
.checkboxTwo.Value = val2
.checkboxThree.Value = val3
End With
End Sub
Private Sub checkboxOne_Change()
Call setCheck(True, False, False)
End Sub
Private Sub checkboxTwo_Change()
Call setCheck(False, True, False)
End Sub
Private Sub checkboxThree_Change()
Call setCheck(False, False, True)
End Sub
It is possible to click a check only in one direction. That means, if I clicked the checkboxOne first time, I don't have the ability to check it again. What I need to do?

The problem that you have is after a checkbox's value has been initialized setting it's value will cause the checkbox's Click and Change events to fire. This causes an infinite loop which effectively locks the checkboxes.
The way around this is to use a class variable to ignore subsequent calls to setCheck during an update.
Private EditMode As Boolean
Private Sub setCheck(ByVal val1 As Boolean, ByVal val2 As Boolean, ByVal val3 As Boolean)
If Not EditMode Then
EditMode = True
With UserForm1
.checkboxone.Value = val1
.checkboxtwo.Value = val2
.checkboxthree.Value = val3
End With
EditMode = False
End If
End Sub
Private Sub checkboxOne_Change()
setCheck True, False, False
End Sub
Private Sub checkboxTwo_Change()
setCheck False, True, False
End Sub
Private Sub checkboxThree_Change()
setCheck False, False, True
End Sub

What about something like this?
Private Sub chkbx1_Click()
chkbx1.Enabled = False
chkbx1.Value = Checked
End Sub
Private Sub Form_Load()
Dim ctrl As Control
' reset it whenever you open the form. this could also be defined separately in the F4-properties of the checkbox
For Each ctrl In Me.Controls
If TypeName(ctrl) = "CheckBox" Then
ctrl.Enabled = True
ctrl.Value = False
End If
Next ctrl
End Sub
Not quite sure if you really want the checkbock disabled but with the Checked value per se...

since you're asking for mutually excluding control, you want Option Buttons
say you place three of them called "OptionButton1", "OptionButton2" and ""OptionButton3" then you will place the following in the Userform code pane:
Option Explicit
Private Sub OptionButton1_Click()
CheckOBs
End Sub
Private Sub OptionButton2_Click()
CheckOBs
End Sub
Private Sub OptionButton3_Click()
CheckOBs
End Sub
Sub CheckOBs()
Dim iOB As Integer
For iOB = 1 To CInt(Right(ActiveControl.Name, 1))
Controls("OptionButton" & iOB).Enabled = False
Next iOB
End Sub

Related

ActiveX Combobox doesn't close automatically

I have an ActiveX Combobox in one of my main sheet which control/update a series of charts.
Private Sub cmBoxSelect_GotFocus()
Application.ScreenUpdating = False
With Me.cmBoxSelect
.List = Array("Grand Total", "Prod1", "Prod2", "Prod3", "Prod4", "Prod5")
.ListRows = 6
.DropDown
End With
Application.ScreenUpdating = True
End Sub
Private Sub cmBoxSelect_Change()
'series of codes which manipulates the charts, based on selection...
End Sub
I noticed that when I click the ComboBox and select one of its content, it leaves a blue highlight on the selection. So to prevent that, I added:
Private Sub cmBoxSelect_DropButtonClick()
Application.ScreenUpdating = False
ActiveCell.Activate
Application.ScreenUpdating = True
End Sub
It successfully removed the highlight.
However, it has a weird drawback. cmbSelect doesn't close automatically once user didn't select anything (once the combobox is active and the user click any cell in the sheet, it doesn't close out). It was working before I added the DropButtonClick event.
Did I missed anything or any wrong steps above? Thanks for your inputs!
EDIT#1
Seems I already found a solution by trial and error. I only added a blank Label and select it to remove the focus out of the ComboBox whenever there is a change. I also changed the DropButtonClick to LostFocus.
Private Sub cmBoxSelect_GotFocus()
Application.ScreenUpdating = False
With Me.cmBoxSelect
.List = Array("Grand Total", "Prod1", "Prod2", "Prod3", "Prod4", "Prod5")
.ListRows = 6
.DropDown
End With
Application.ScreenUpdating = True
End Sub
Private Sub cmBoxSelect_LostFocus()
ActiveCell.Select
End Sub
Private Sub cmBoxSelect_Change()
'series of codes which manipulates the charts, based on selection...
Me.Label1.Select
End Sub
You need to put the SelLength to 0 in multiple events to avoid highlighting:
so:
Me.cmBoxSelect.SelLength = 0
in:
Private Sub cmBoxSelect_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Private Sub cmBoxSelect_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Private Sub cmBoxSelect_LostFocus()
Private Sub cmBoxSelect_DropButtonClick()
Private Sub cmBoxSelect_Change()
Private Sub cmBoxSelect_GotFocus()
(you could add also Me.cmBoxSelect.SelStart = 0 )
Lets try this:
Not Event-triggered by a change, but by the dropbuttonclick
Private Sub changingComboBox(String s)
'series of codes which manipulates the charts, based on selection...
End Sub
Private Sub cmBoxSelect_DropButtonClick()
Dim s As String
s = cmBoxSelect.SelText
If (cmBoxSelect.SelText = cmBoxSelect.Value) Then
cmBoxSelect.Value = ""
cmBoxSelect.Value = s
Else
call changingComboBox(cmBoxSelect.Value)
End If
End Sub
How about that ?

Using VBA code to modify OptionButton.value is activating the control.Click() Sub

I have a userform with 2 OptionButton choices, and I'm modifying the form (hiding labels and controls, and resizing frame) for the default Option (name = BwaIsNew), but then restoring the full userform when Option #2 (name = BwaIsOld) is selected. (see separate question for background).
When Option #2 is selected I'm calling a fresh userform, and coding the change in value. But this coding of the value dlgInformation.BwaIsOld.Value = True then triggers an event (?) that calls the Sub BwaIsOld_Click() code to run. This then sets up a perpetual loop.
What's the best way to solve this?
Problem code (the one looping) is:
Private Sub BwaIsOld_Click()
Unload Me
dlgInformation.BwaIsNew.Value = False
dlgInformation.BwaIsOld.Value = True
dlgInformation.Show
End Sub
Update:
Thanks #Tim & #CommonSense. I'm still not quite there yet. What am I doing wrong? Here is the code
Public EnableEvents As Boolean
Private Sub UserForm_Initialize()
Me.EnableEvents = True
End Sub
Private Sub BwaIsNew_Click()
Call changeform(280)
End Sub
Private Sub BwaIsOld_Click()
Unload Me
Me.EnableEvents = False
dlgInformation.BwaIsNew.Value = False
dlgInformation.BwaIsOld.Value = True
Me.EnableEvents = True
dlgInformation.Show
End Sub
You need to actually use that EnableEvents in the rest of your code.
BTW I would choose a different name from the built-in Application.EnableEvents property just for clarity.
Public EnableEvents As Boolean
Private Sub UserForm_Initialize()
Me.EnableEvents = True
End Sub
Private Sub BwaIsNew_Click()
'don't respond to events triggered by BwaIsOld_Click
If Me.EnableEvents Then
Call changeform(280)
End If
End Sub
Private Sub BwaIsOld_Click()
Unload Me '<< why do this here?
Me.EnableEvents = False
dlgInformation.BwaIsNew.Value = False
dlgInformation.BwaIsOld.Value = True
Me.EnableEvents = True
dlgInformation.Show
End Sub

VBA Excel Toggle Button "Latching"

I have the following code corresponding to three ToggleButtons in a VBA Program in Excel. When one button is clicked, it is supposed to stay "pressed" and the other two buttons are supposed to "release". However, with the code I have, I have to click on one button TWICE, once to release the other buttons and the other to keep the original one pressed.
However, if I add "ToggleButtonX.Value = True" to each of the Subs, when one button is clicked, it cannot release even after clicking another button. How could one configure this so that when one clicks on one button, that button stays pressed AND the other buttons get released?
EDIT: I would like to KEEP TOGGLEBUTTONS.
Private Sub ToggleButton1_Click()
ToggleButton2.Value = False
ToggleButton3.Value = False
End Sub
Private Sub ToggleButton2_Click()
ToggleButton1.Value = False
ToggleButton3.Value = False
End Sub
Private Sub ToggleButton3_Click()
ToggleButton1.Value = False
ToggleButton2.Value = False
End Sub
In addition to the OptionButton answer, which is probably easier and cleaner to implement, there's another way to do it as well by using logic that will only change the values of the other two buttons when one button is clicked. The code for the other buttons Click event will fire, but the variable sButton will determine that the code will only fire on the button that was physically pressed by the user.
Also note the use of Not Me.ToggleButton1.Value. This will ensure that button 2 and 3 are the opposite of button 1 with each click. The way your code was written, it would always revert the other buttons to False no matter what if the clicked button was True or False.
Option Explicit
Public sButton As String
Private Sub ToggleButton1_Click()
ButtonLoad 1
End Sub
Private Sub ToggleButton2_Click()
ButtonLoad 2
End Sub
Private Sub ToggleButton3_Click()
ButtonLoad 3
End Sub
Sub ButtonLoad(iButton As Integer)
Select Case iButton
Case 1
If sButton = "" Then
sButton = "1" 'set so that other buttons don't trigger
Me.ToggleButton2.Value = Not Me.ToggleButton1.Value
Me.ToggleButton3.Value = Not Me.ToggleButton1.Value
sButton = "" 'reset for next button click
End If
Case 2
If sButton = "" Then
sButton = "2"
Me.ToggleButton1.Value = Not Me.ToggleButton2.Value
Me.ToggleButton3.Value = Not Me.ToggleButton2.Value
sButton = ""
End If
Case 3
If sButton = "" Then
sButton = "3"
Me.ToggleButton2.Value = Not Me.ToggleButton3.Value
Me.ToggleButton1.Value = Not Me.ToggleButton3.Value
sButton = ""
End If
End Select
End Sub
By calling ToggleButtonx.Value = False you are simulating a click on that button and so it own code will run, and set the value of the button you just clicked to false.
Use instead the MouseDown event:
Private Sub ToggleButton1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ToggleButton2.Value = False
ToggleButton3.Value = False
End Sub
Private Sub ToggleButton2_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ToggleButton1.Value = False
ToggleButton3.Value = False
End Sub
Private Sub ToggleButton3_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ToggleButton1.Value = False
ToggleButton2.Value = False
End Sub
This is easily done with Option Buttons (If that works with the rest of your implementation)
Private Sub OptionButton1_Click()
OptionButton1.Value = True
OptionButton2.Value = False
OptionButton3.Value = False
End Sub
Private Sub OptionButton2_Click()
OptionButton1.Value = False
OptionButton2.Value = True
OptionButton3.Value = False
End Sub
Private Sub OptionButton3_Click()
OptionButton1.Value = False
OptionButton2.Value = False
OptionButton3.Value = True
End Sub

capture option button status to a Boolean variable

I have three groups of Option buttons on a user form, and I want to capture the status of each group to a Boolean variable. For instance, a frame called “Process Subfolders” contains two opt. buttons called “OptBTN_Subfoldes_yes” and “OptBTN_Subfoldes_no” which are marked in red in picture below.
I wrote a code to assign the group status to a variable called “SubFolderStatus”.
The same code repeats at the time of form activation event and opt. button change event, my question is: is there a cleaner, more efficient code to get the same results?
Here is my Code
Private Sub OptBTN_Subfoldes_no_Change()
Select Case OptBTN_Subfoldes_no.Value
Case True
SubFolderStatus = False
Case False
SubFolderStatus = True
End Select
End Sub
Private Sub OptBTN_Subfoldes_yes_Change()
Select Case OptBTN_Subfoldes_yes.Value
Case True
SubFolderStatus = True
Case False
SubFolderStatus = False
End Select
End Sub
for the form activate event:
Private Sub UserForm_Activate()
Select Case OptBTN_Subfoldes_yes.Value
Case True
SubFolderStatus = True
Case False
SubFolderStatus = False
End Select
End Sub
Instead of using the Case just assign the SetFolderStatus to the Value of the Yes Option Button and this is placed into the Initialize / Activate Sub as well as the OptBTN_Subfoldes_yes_Change.
You can set the "Yes" Button value to True by default using the properties.
For your use you can remove the Me.Label1.Caption = ButtonValue as it is just to show for testing purposes.
So you will just have one line of code in each as oppose the the Case selection.
See example below
Option Explicit
Dim ButtonValue As Boolean
Private Sub OptionButton1_Change()
ButtonValue = Me.OptionButton1.Value
Me.Label1.Caption = ButtonValue
End Sub
Private Sub UserForm_Initialize()
ButtonValue = Me.OptionButton1.Value
Me.Label1.Caption = ButtonValue
End Sub
You could define a public Function to call from all event handlers
Public Function SetSubFolderStatus(OptBtnVal as boolean, boolSwitch as boolean) as boolean
SetSubFolderStatus = not (boolSwitch XOr OptBtnVal)
End Function
And the call would be like
Private Sub UserForm_Activate()
SubFolderStatus = SetSubFolderStatus(OptBTN_Subfoldes_yes.value, True)
End Sub

How to call the DateTimePicker from a textbox in UserForm

I have created a TextBox1 within my UserForm.
I have create a Sub called
Sub TextBox1_Enter()
End Sub
where by clicking the textbox I want to open the DateTimePicker control to choose a date, and after the date is chosen the chosen date should be the TextBox1.Value
I have the DateTimePicker from mscomct2.ocx
I really don't figure out how to call the control; any tips with code and a good explanation anyone?
I'm not sure if this is exactly what you are looking for but you could take a look as this. It is very well explained.
My goal was to have an empty DatePicker at form startup, and was told to use a textbox to load the DTPicker upon clicking.
But I found this solution that keep the DTPicker Value empty as form startup
Private Sub DTPicker1_CloseUp()
FormatDTPicker
End Sub
Private Sub DTPicker1_Format(ByVal CallbackField As String, FormattedString As String)
If CallbackField = "X" Then FormattedString = ""
End Sub
Private Sub DTPicker1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal_
x As stdole.OLE_XPOS_PIXELS, ByValy As stdole.OLE_YPOS_PIXELS)
With DTPicker1
If .Value = vbNull Then
.Value = Now
End If
End With
End Sub
Private Sub UserForm_Initialize()
DTPicker1.Value = vbNull
FormatDTPicker
End Sub
Private Sub FormatDTPicker()
With DTPicker1
If .Value = vbNull Then
.Format = dtpCustom
.CustomFormat = "X"
Else
.Format = dtpShortDate
End If
End With
End Sub
http://www.mrexcel.com/forum/excel-questions/666685-dtpicker-value-null.html