问题
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
回答1:
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
回答2:
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
回答3:
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
回答4:
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
来源:https://stackoverflow.com/questions/19276861/how-to-prevent-activex-events-firing-in-vba