Basically Im a vba programmer and Iam facing a serious problem with the checkbox controls of the VBA.I have to select and deselect the checkboxes as per user selection. I believe this is a general question for vb.net also.
some sample code
sub chk3_Click()
if userform.chk3.value = true then
userform.chk4.value = true
userform.chk2.value = true
end if
end sub
sub chk4_click()
if userform.chk4.value = true then
userform.chk3.value=true
userform.chk1.value=true
end if
end sub
This is the sample code, I have to turn on the other checkboxes based on user selection of the checkboxes.but the problem Im facing is when it executes the statement
userform.chk4.value = true in the sub chk3_click
it is invoking the sub chk4_click sub and again finding the
userform.chk3.value=true in sub chk4_click(), invoking the sub chk3_click
I am unable to understand how to solve it .
I have tried with various events mousedown, mouseup and change in value also after update but none worked.These events are crashing the tool I dont understand why but they are crashing so I just ignored to use those events.
Finally I have used a flag which is defined globally in the workbook and using the if condition I have did it but its looking to bad style of coding. Could anyone help me with these ?
This is what I have done to resolve the problem . It works but I dont think its good style of programming.
dim i as integer
sub ch3_click()
if i = 0 then
i = 1
if userform.chk3.value=true then
userform.chk4.value =true
userform.chk2.value=true
end if
i = 0
end if
end sub
sub chk4_click
if i = 0 then
i = 1
if userform.chk4.value = true then
userform.chk3.value=true
userform.chk1.value=true
end if
i = 0
end if
end sub
Any help greatly appreciated.
That is actually a very valid way to approach the problem, you just need to have a more descriptive name and type for i, such as
Dim InClickEvent As Boolean
Then change your click event code to something like:
if Not InClickEvent then
InClickEvent = True
if userform.chk3.value=true then
userform.chk4.value =true
userform.chk2.value=true
end if
InClickEvent = False
end if
Even better is if your version of VBA supports Try/Finally, which I believe it does, you can make sure the flag is always cleared even if you have errors with the following version of the code:
if Not InClickEvent then
Try
InClickEvent = True
if userform.chk3.value=true then
userform.chk4.value =true
userform.chk2.value=true
end if
Finally
InClickEvent = False
End Try
end if
Take a look at Application.EnableEvents
sub chk3_Click()
Application.EnableEvents =false
if userform.chk3.value = true then
userform.chk4.value = true
userform.chk2.value = true
end if
Application.EnableEvents =true
end sub
sub chk4_click()
Application.EnableEvents =false
if userform.chk4.value = true then
userform.chk3.value=true
userform.chk1.value=true
end if
Application.EnableEvents =true
end sub
Related
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
I currently have it set up so that two checkboxes can not be checked at the same time, if they are then it will pop up an error and set the checkbox unchecked again. However currently it is popping up the message twice. How to fix this?
Private Sub CheckBox1_Click()
If CheckBox2.Value = True Then
MsgBox "Must be sent separate."
CheckBox1.Value = False
End If
End Sub
I think you simply need to change it too : the reason is it is running the check when switching checkbox1
Private Sub CheckBox1_Click()
If CheckBox2.Value = True And CheckBox1.Value = True Then
MsgBox "Must be sent separate."
CheckBox1.Value = False
End If
End Sub
I have an excel worksheet that is being used as a database front end for access. When a user changes data in a cell it will run the Worksheet_changed event to run codes that updates the access database.
However - I also have a refresh button that, you guessed it, refreshes the spreadsheet. This also causes the worksheet_changed event to run which will sometimes error out the program.
Private Sub RefreshButton_Click()
Refreshbuttons
ActiveWorkbook.RefreshAll
End Sub
How do I stop the work sheet changed event from happening when the refresh button is pressed? I have tried a Boolean flag which will stop the worksheet changed event from running when refreshed button is pressed - but it stops it from running at all (example of what I did)
Private Sub RefreshButton_Click()
Dim Flag as Boolean
Flag = True
Refreshbuttons
ActiveWorkbook.RefreshAll
Flag = False
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Flag = true then
Exit Sub
Else
[...] {Rest of code below here}
I am stuck - any help is greatly appreciated!!!
Thanks,
Ethan
EDIT
Thanks Tim! you pointed me in the right direction. I ended up going with (code below) and it worked beautifully. I appreciate everyones help!
Private Sub RefreshButton_Click()
For Each objConnection In ThisWorkbook.Connections
'Get current background-refresh value
bBackground = objConnection.OLEDBConnection.BackgroundQuery
'Temporarily disable background-refresh
objConnection.OLEDBConnection.BackgroundQuery = False
'Refresh this connection
objConnection.Refresh
If ActiveSheet.FilterMode = True Then
ActiveSheet.ShowAllData
Else
End If
'Set background-refresh value back to original value
objConnection.OLEDBConnection.BackgroundQuery = bBackground
Next
MsgBox "Refresh Complete"
End Sub
Private Sub RefreshButton_Click()
On Error Goto haveError
Refreshbuttons
Application.EnableEvents = False
ActiveWorkbook.RefreshAll
haveError:
Application.EnableEvents = True
End Sub
Declare Flag as global like below. It should work.
Public Flag as Boolean
All office applications have a built-in function to control this behavior. Simply add:
Application.EnableEvents = False to the beginning of the RefreshButton_Click event and
Application.EnableEvents = True to the end of the event.
I was trying to emphasis the option button from activeX control when it is selected by user. I decided to show the shadow when it is selected and then hide the shadow when user selects other option button. The first process is working whereas the shadow cannot be removed even though I select other button. My VBA code is shown below:
Private Sub OptionButton1_Click()
OptionButton1.Shadow = False
If OptionButton1.Value = True Then
OptionButton1.Shadow = True
Else
OptionButton1.Shadow = False
End If
End Sub
Can anyone please help me to solve this?
In case of FORMS buttons you can use
Sub RemoveFormsButtonShadows()
'A.Leine 21/10/2015
For Each Button In ActiveSheet.Shapes
Button.Select
Selection.ShapeRange.Shadow.Visible = False
Next Button
End Sub
For that you have to create one sub which needs to be called from all the option buttons that you have. This common sub will simply remove the shadow from all option buttons. Here I am taking the example of 3 option buttons.
Option Explicit
Private Sub OptionButton1_Click()
RemoveShadow
If OptionButton1.Value = True Then _
OptionButton1.Shadow = True
End Sub
Private Sub OptionButton2_Click()
RemoveShadow
If OptionButton2.Value = True Then _
OptionButton2.Shadow = True
End Sub
Private Sub OptionButton3_Click()
RemoveShadow
If OptionButton3.Value = True Then _
OptionButton3.Shadow = True
End Sub
Sub RemoveShadow()
Dim objOpt As OLEObject
With ActiveSheet
For Each objOpt In .OLEObjects
If TypeName(objOpt.Object) = "OptionButton" Then
objOpt.Shadow = False
End If
Next
End With
End Sub
I am searching for a better way to disable ActiveX events from triggering in an Excel workbook (though this would apply to all Office apps with ActiveX objects).
Hopefully something similar to Application.EnableEvents = false, though this does not work with ActiveX.
In the below example it's trivial to use a global boolean but I have a lot of event handlers for my ActiveX objects and it would be immensely easier for something I could universally apply to temporarily disable ActiveX events. I don't really want to add an if/exit sub statement to every single one of these methods.
To demonstrate this problem, create an ActiveX combobox in a worksheet and add the following to that sheet module
Public initializingContent As Boolean
Private Sub intializeAllActiveXContent()
'this doesn't apply to activeX events :'(
Application.EnableEvents = False
'this could work but is not really elegant
'change this to false to show my problem in
'the intermediate window (called not once but twice)
initializingContent = True
ComboBoxTest.Clear
ComboBoxTest.AddItem ("item1")
ComboBoxTest.AddItem ("item2")
ComboBoxTest.AddItem ("item3")
'select the top value in the box
ComboBoxTest.value = "item1"
initializingContent = False
Application.EnableEvents = True
End Sub
Private Sub ComboBoxTest_Change()
'I really don't want to have to wrap EVERY single ActiveX method
'with something like this for a whole variety of reasons...
If initializingContent Then Exit Sub
Debug.Print "do stuff I don't want to happen when intializeAllActiveXContent() runs " & _
"but I do when user changes box"
End Sub
I know this is really old. But anyone who looks this up (first hit on google) might want a simple answer:
Lets say you have a Private Sub ActiveXControl_Change() that is getting called during an Application.EnableEvents = False and you want it to skip this just go:
Private Sub ActiveXControl_Change()
If Application.EnableEvents = True Then
'enter you code here
End If
End Sub
Why not disable them? That ways you don't have to worry about their individual codes as well.
Try this
Sub DisableActiveXControls()
Dim ws As Worksheet
Dim OLEobj As OLEObject
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
For Each OLEobj In ws.OLEObjects
If TypeOf OLEobj.Object Is MSForms.ComboBox Then
OLEobj.Enabled = False
End If
Next OLEobj
End With
End Sub
Before/After ScreenShots:
FOLLOWUP FROM COMMENTS:
Also turns out this breaks hard core on objects which are grouped together but I can ungroup objects (they are no longer in "Sheet1.OLEobjects" I guess). I still don't really like this since it relies on this fact and there will be times when I do want to group objects.. – enderland 17 mins ago
To disables ActiveX Controls in a group, you don't need to ungroup them. Use this code. The below code will disable Comboboxes in a group.
Sub Disable_ActiveX_Controls_In_A_Group()
Dim shp As Shape, indvShp As Shape
Dim OLEobj As OLEObject
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
For Each shp In ws.Shapes
If shp.Type = msoGroup Then
For Each indvShp In shp.GroupItems
Set objOLE = indvShp.OLEFormat.Object
If objOLE.progID = "Forms.ComboBox.1" Then _
objOLE.Enabled = False
Next
End If
Next
End Sub
came across this post when searching for a similar issue. I decided the answer posted here would not suit my situation, and came up with something else. My approach may be useful here also.
In my workbook, I have a set of 20 (Activex) checkboxes. These essentially filter on/off 20 categories of product to be included in a report. There is a routine that runs each time one of these checkboxes is changed, simply by calling the routing from the CheckBox_Click routine.
Then I also have a combobox that selects various groups of these checkboxes. The trouble is that when EACH of the 20 checkboxes is (un)selected by the combobox code, the calculation routine is triggered.
What I wanted was to run the calculation routine only ONCE at the end of the combobox, but still have it work if I change an individual checkbox manually.
My solution - put in a TRUE/FALSE code in some cell on a hidden worksheet, somewhere it's out of the way and won't interfere.
Then the CheckBox_Click code becomes (for each of the 20 checkboxes):
Private Sub CheckBox6_Click()
If (Sheets("Data").Range("G60")) Then
Call RangeFind
End If
End Sub
The combobox code modifies this same cell, appropriately:
Private Sub ComboBox28_Change()
Sheets("Data").Range("G60").Value = False
Select Case Sheets("Data").Range("F50").Value
Case "1"
CheckBox1.Value = False
CheckBox2.Value = False
CheckBox3.Value = False
....
End Select
' This turns the checkboxes back on
Sheets("Data").Range("G60").Value = True
' This now actually calls the calculation ONCE
Call RangeFind
ActiveSheet.Range("A1").Activate
End Sub
Cheers,
Michael
Here is one option:
Private Sub ToggleButton1_Click()
If Application.EnableEvents = True Then
'This next line forces at least 1 of the toggle's to be selected at all
'times; remove it from all routines if this is not desired.
If Not ToggleButton1.Value Then ToggleButton1.Value = True
Application.EnableEvents = False
ToggleButton2.Value = False
ToggleButton3.Value = False
Application.EnableEvents = True
End If
End Sub
Private Sub ToggleButton2_Click()
If Application.EnableEvents = True Then
If Not ToggleButton2.Value Then ToggleButton2.Value = True
Application.EnableEvents = False
ToggleButton1.Value = False
ToggleButton3.Value = False
Application.EnableEvents = True
End If
End Sub
Private Sub ToggleButton3_Click()
If Application.EnableEvents = True Then
If Not ToggleButton3.Value Then ToggleButton3.Value = True
Application.EnableEvents = False
ToggleButton1.Value = False
ToggleButton2.Value = False
Application.EnableEvents = True
End If
End Sub