VBA: Prevent _Click Event from Triggering at Value Change - vba

I have been had this issue in mind for months and it remains unresolved after so much research. I'm working with Excel Checkboxes and trying to make the system foolproof whereas "if A & B cannot occur together, if A is clicked and you click B, then the macro unclicks A for you".
However, the issue I'm running into is that this starts (as shown in my code below) an infinite loop,
The first Sub:
Private Sub CheckBoxD11_Click()
If CheckBoxD12.Value = True Then
CheckBoxD12.Value = False
Worksheets("Dynamic_Parking_Sheet").Range("D9").Interior.ColorIndex = 20
CheckBoxD11.Value = True
Worksheets("Dynamic_Parking_Sheet").Range("B8:E8").Interior.ColorIndex = 2
End If
TextBox1_Change
TextBox2_Change
If CheckBoxD11.Value = True Then
Worksheets("Dynamic_Parking_Sheet").Range("B9:E9").Interior.Color = RGB(221, 221, 221)
Worksheets("Dynamic_Parking_Sheet").Range("D8").Interior.ColorIndex = 4
Else
Worksheets("Dynamic_Parking_Sheet").Range("B9:E9").Interior.ColorIndex = 20
Worksheets("Dynamic_Parking_Sheet").Range("D8").Interior.ColorIndex = 2
End If
End Sub
.. and the second Sub:
Private Sub CheckBoxD12_Click()
If CheckBoxD11.Value = True Then
CheckBoxD11.Value = False
Worksheets("Dynamic_Parking_Sheet").Range("D8").Interior.ColorIndex = 2
CheckBoxD12.Value = True
Worksheets("Dynamic_Parking_Sheet").Range("B9:E9").Interior.ColorIndex = 20
End If
TextBox1_Change
TextBox2_Change
If CheckBoxD12.Value = True Then
Worksheets("Dynamic_Parking_Sheet").Range("B8:E8").Interior.Color = RGB(221, 221, 221)
Worksheets("Dynamic_Parking_Sheet").Range("D9").Interior.ColorIndex = 4
Else
Worksheets("Dynamic_Parking_Sheet").Range("B8:E8").Interior.ColorIndex = 2
Worksheets("Dynamic_Parking_Sheet").Range("D9").Interior.ColorIndex = 20
End If
End Sub
I tried working a bit with public flags, but the issue persisted.
Any advice?
Thank you,
~Deut

When you want checkboxes to uncheck each other, try simplifying your code to something like this:
CheckBoxD12.Value = Not CheckBoxD11.value
It would work quite well and there should be no loops.
Or something like this, made simple:
Private Sub chb_A_Click()
If chb_A Then chb_B = False
End Sub
Private Sub chb_B_Click()
If chb_B Then chb_A = False
End Sub
The idea here is that it only checks for being checked to allow the option for both checkboxes to be unchecked.

Related

Textbox not support for property and menthod in VBA ppt

Here is my code
Sub Loadde()
If Slide3.Shapes("MA_VONG") = 1 Then
Slide5.Shapes("Q1").TextFrame.TextRange = Slide6.Shapes("1").TextFrame.TextRange
Slide5.Shapes("Q2").TextFrame.TextRange = Slide6.Shapes("2").TextFrame.TextRange
Slide5.Shapes("Q3").TextFrame.TextRange = Slide6.Shapes("3").TextFrame.TextRange
Slide5.Shapes("Q4").TextFrame.TextRange = Slide6.Shapes("4").TextFrame.TextRange
Slide5.Shapes("Q5").TextFrame.TextRange = Slide6.Shapes("5").TextFrame.TextRange
ElseIf Slide3.Shapes("MA_VONG") = 2 Then
Slide5.Shapes("Q1").TextFrame.TextRange = Slide7.Shapes("1").TextFrame.TextRange
Slide5.Shapes("Q2").TextFrame.TextRange = Slide7.Shapes("2").TextFrame.TextRange
Slide5.Shapes("Q3").TextFrame.TextRange = Slide7.Shapes("3").TextFrame.TextRange
Slide5.Shapes("Q4").TextFrame.TextRange = Slide7.Shapes("4").TextFrame.TextRange
Slide5.Shapes("Q5").TextFrame.TextRange = Slide7.Shapes("5").TextFrame.TextRange
End If
End Sub
At first, it work fine but after that, it showed an error that the Qs (in Slide 5) were not supported
I tried to make it more simple and it still does not work.
Sub Loadde()
If Slide3.Shapes("MA_VONG") = 1 Then
Slide5.Shapes("Q1").TextFrame.TextRange = Slide6.Shapes("1").TextFrame.TextRange
Slide5.Shapes("Q2").TextFrame.TextRange = Slide6.Shapes("2").TextFrame.TextRange
Slide5.Shapes("Q3").TextFrame.TextRange = Slide6.Shapes("3").TextFrame.TextRange
Slide5.Shapes("Q4").TextFrame.TextRange = Slide6.Shapes("4").TextFrame.TextRange
Slide5.Shapes("Q5").TextFrame.TextRange = Slide6.Shapes("5").TextFrame.TextRange
End If
End Sub
Can somebody explain to me what is wrong with this code?
A few suggestions:
First, it's not clear whether you've DIMmed your variables elsewhere.
Next, Slide3.Shapes("some name") = 1 will fail. There's no such property. What exactly are you trying to test for here? The text in the shape or that the shape exists at all? Or something else?
Finally, just to be sure, IS there actually a shape named 1 on Slide6 or are you trying to reference the first shape on the slide, in which case you'd use Slide6.Shapes(1) (not "1" in quotes).
Sub Loadde()
If Slide3.Shapes("MA_VONG") = 1 Then
Slide5.Shapes("Q1").TextFrame.TextRange = Slide6.Shapes("1").TextFrame.TextRange
' ...
ElseIf Slide3.Shapes("MA_VONG") = 2 Then
Slide5.Shapes("Q1").TextFrame.TextRange = Slide7.Shapes("1").TextFrame.TextRange
' ...
End If
End Sub

Looping through Control Names and hiding all controls that contain the right number within a frame

What I am trying to do is on a Word Userform, if I select a number in a combo box (cb_CountCohorts) (options are 1-10) then any control (option button or textbox that contains that number +1 (so if I select 5, those controls that have 6-10) will not be visible.
With that being said, I did get it to work but I know that it is not efficient.
Below is the beginning but I realize for each case, there would have to be 10 more sets of what you see below times 10 different If statements. Is there a way to say something like if cb_Countcohrts ="1" find all controls in this frame that does not contain Cohort 1 and hide it...if cb_countcohorts ="5" then hide everything that contains cohort 6, 7, 8, 9, 10? Thanks in advance for all and any help
Private Sub cb_CountCohorts_Change()
If cb_CountCohorts = "1" Then
txt_cohort1.Visible = True
txt_cohort2.Visible = False
txt_cohort3.Visible = False
txt_cohort4.Visible = False
txt_cohort5.Visible = False
txt_cohort6.Visible = False
txt_cohort7.Visible = False
txt_cohort8.Visible = False
txt_cohort9.Visible = False
txt_cohort10.Visible = False
I tried this too but it doesnt seem to work like I want either
Private Sub cb_CountCohorts_Change()
For i = 2 To 10
Set VarText = frm_master.Controls("txt_cohort" & i)
If cb_CountCohorts.Value > VarText.Value Then
VarText.Visible = False
End If
Next i
End Sub
Something like this:
Private Sub cb_CountCohorts_Change()
Dim v As Long, i As Long
v = CLng(cb_CountCohorts.Value)
For i = 2 To 10
Me.Controls("txt_cohort" & i).Visible = (i <= v)
'any other controls here....
Next i
End Sub
If you want something generic for all controls (assuming a consistent naming convention) -
Private Sub cb_CountCohorts_Change()
Dim v As Long, c, i As Long, arr
v = CLng(cb_CountCohorts.Value)
For Each c In Me.Controls
If c.Name Like "txt_cohort#*" Then
arr = Split(c.Name, "_")
i = CLng(Replace(arr(1), "txt_cohort", ""))
c.Visible = (i <= v)
End If
Next c
End Sub
...basically expanded from Robert's suggestion
Untested, but this should work:
Dim c As Control
For Each c In Me.Controls
If InStr(TypeName(c),"cohort") Then
c.Visible = False
End If
Next

Simplify toggle button change BackColor Code VBA

im new in VBA making, so all code below is still working tho but it takes a lot of line of codes. Even it is easier to maintain but if someone can simplify my noob-code to cut some lines and more eye-pleasing?
there are more than 20 toggle buttons in my userform
this is the example of my code, need help for make it simpler
Private Sub tgglC_Result1_Click()
If tgglC_Result1.Value = True Then
tgglC_Result1.BackColor = &HFF00&
tgglNC_Result1.Enabled = False
lblResult1.Caption = Now
lblResult1.Visible = True
Else
tgglC_Result1.BackColor = &H8000000F
tgglNC_Result1.Enabled = True
lblResult1.Visible = False
End If
End Sub
Private Sub tgglC_Result2_Click()
If tgglC_Result2.Value = True Then
tgglC_Result2.BackColor = &HFF00&
tgglNC_Result2.Enabled = False
lblResult2.Caption = Now
lblResult2.Visible = True
Else
tgglC_Result2.BackColor = &H8000000F
tgglNC_Result2.Enabled = True
lblResult2.Visible = False
End If
End Sub
Private Sub tgglC_Result3_Click()
If tgglC_Result3.Value = True Then
tgglC_Result3.BackColor = &HFF00&
tgglNC_Result3.Enabled = False
lblResult3.Caption = Now
lblResult3.Visible = True
Else
tgglC_Result3.BackColor = &H8000000F
tgglNC_Result3.Enabled = True
lblResult3.Visible = False
End If
End Sub
Private Sub tgglC_Result4_Click()
If tgglC_Result4.Value = True Then
tgglC_Result4.BackColor = &HFF00&
tgglNC_Result4.Enabled = False
lblResult4.Caption = Now
lblResult4.Visible = True
Else
tgglC_Result4.BackColor = &H8000000F
tgglNC_Result4.Enabled = True
lblResult4.Visible = False
End If
End Sub
best way should be using a Class
but a more "conventional" way could help you reducing typing burden, too:
define a unique toggle control handling sub
Private Sub tgglC_Result_Click()
Dim NC As Control
With Me
Set NC = .Controls(VBA.Replace(.ActiveControl.Name, "tgglC", "tgglNC")) '<--| set the "counter part" toggle button control of the "Active" control (i.e. the one being currently toggled)
With .ActiveControl
.BackColor = IIf(.Value, &HFF00&, &H8000000F)
NC.Enabled = Not .Value
End With
End With
End Sub
call it from any of your event handler
Private Sub tgglC_Result1_Click()
tgglC_Result_Click
End Sub
Private Sub tgglC_Result2_Click()
tgglC_Result_Click
End Sub
Private Sub tgglC_Result3_Click()
tgglC_Result_Click
End Sub
...
Not really a simplifying solution, but this is what I used when I needed to supply logic to 60+ controls on an Access subform (similar task to yours):
Sub makeCode()
Dim i As Integer
For i = 1 To 4
Debug.Print "Private Sub tgglC_Result" & i & "_Click()"
Debug.Print "tgglC_Result" & i & ".BackColor = &HFF00&"
Debug.Print "tgglNC_Result2.Enabled = False"
Debug.Print "lblResult" & i & ".Caption = Now"
Debug.Print "lblResult" & i & ".Visible = True"
Debug.Print "End Sub"
Debug.Print ""
Next
End Sub
Copy the result from the Immediate window into the code editor. It's easy to change all the subroutines, too: just change the loop body, run it, and replace old code.

DblClick call in VBA - close on double click without running function

Good Afternoon,
Bear with me, I am new to VBA. I have a Sub that opens a text box when its double clicked, not only do I want it to open the text box (expands it), i also want it to run a sub called EMSpull. This all works perfectly except for the fact I want to then double click to close the textbox without running EMSpull again.
Also, can someone explain "Control", especially for this situation (i didnt write the adjustheight )
Code is below
Private Sub txtEMS_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Call AdjustHeight(txtEMS, lblEMS)
Call EMSpull
End Sub
Public Sub AdjustHeight(cControl As Control, cLabel As Control)
On Error GoTo errhand
If bExpandedMode = False Then
dOldTop = cControl.Top
dOldLeft = cControl.Left
dOldWidth = cControl.Width
dOldHeight = cControl.Height
cControl.Top = lblDescription.Top + 50
cControl.Width = cControl.Width * 2
cControl.Height = 500
cControl.Left = lblResults.Left
bExpandedMode = True
Call HideAllTxt(cControl)
lblDescription.Visible = True
lblDescription.Caption = cLabel.Caption
If Len(cControl.Text) > 2 Then
cControl.CurLine = 0
End If
Else
bExpandedMode = False
Call ShowAllTxt
lblDescription.Visible = False
cControl.Top = dOldTop
cControl.Left = dOldLeft
cControl.Width = dOldWidth
cControl.Height = dOldHeight
End If
Exit Sub
errhand:
Resume Next
End Sub
I'm assuming you have a global boolean named bExpandedMode at the top of the subs? If so this should work fine:
Private Sub txtEMS_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Call AdjustHeight(txtEMS, lblEMS)
if bExpandedMode = true then Call EMSpull 'Calls it only when it expanded in AdjustHeight
End Sub
Public Sub AdjustHeight(cControl As Control, cLabel As Control)
On Error GoTo errhand
If bExpandedMode = False Then
dOldTop = cControl.Top
dOldLeft = cControl.Left
dOldWidth = cControl.Width
dOldHeight = cControl.Height
cControl.Top = lblDescription.Top + 50
cControl.Width = cControl.Width * 2
cControl.Height = 500
cControl.Left = lblResults.Left
bExpandedMode = True
Call HideAllTxt(cControl)
lblDescription.Visible = True
lblDescription.Caption = cLabel.Caption
If Len(cControl.Text) > 2 Then
cControl.CurLine = 0
End If
Else
bExpandedMode = False
Call ShowAllTxt
lblDescription.Visible = False
cControl.Top = dOldTop
cControl.Left = dOldLeft
cControl.Width = dOldWidth
cControl.Height = dOldHeight
End If
Exit Sub
errhand:
Resume Next
End Sub
Basically if that boolean exists and is used like I think it is, it just check whether the box is expanded right now or not. When it's not, the boolean is False, and AdjustHeight expands it, then turns it to true. Conversely when it is set to True, it closes it instead, and sets it to False.
So my fix just checks that same boolean and only runs it 1 way (when it just expanded)

monitor variable value within class object WITHOUT watch windows and WITHOUT OnTime call, in VBA

Hello I am looking to see if there is a way to monitor and execute code when a variable in a class object has changed value during run time.
Here is one way I tried to pull it off....
Create this class:
Option Compare Database
Option Explicit
Private p_bVarToMonitor As Boolean
Public Property Get bVarToMonitor() As Boolean
bVarToMonitor = p_bVarToMonitor
End Property
Public Property Let bVarToMonitor(v As Boolean)
p_bVarToMonitor = v
If v = False Then
GoTo bVarToMonitorFalse
End If
End Property
Then test it in a module (not in the class module):
Sub test()
Dim m As clsVarMonitorBoolean
Set m = New clsVarMonitorBoolean
m.bVarToMonitor = False 'this should make it goto bVarToMonitorFalse:
'Code to skip when bVarToMonitor = False
Exit Sub
bVarToMonitorFalse:
'other alternative code to run when bVarToMonitor = False
End Sub
...however, it doesn't work because the goto label is in a different module. Note, I need to use the class object in a regular code module, not within the same class module.
Update:
If I can't do this I have to do something like this
test()
Dim b As Boolean
b = SomeFunctionCall(input1)
if b = False then
goto altcode
end if
b = SomeFunctionCall(input1)
if b = False then
goto altcode
end if
b = SomeFunctionCall(input2)
if b = False then
goto altcode
end if
b = SomeFunctionCall(input3)
if b = False then
goto altcode
end if
'etc....repeat serveral times
end Sub
I.e. I have to do a ton of if statements throughout the code for each input to SomeFunctionCall.