4
votes

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
4
+ 1 Good Question! You had me thinking for a while :)Siddharth Rout
My code is an example for Excel. The logic remains the same for MS Word/PowerPoint. Not sure about MS Access/Project/Outlook though.Siddharth Rout

4 Answers

6
votes

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
4
votes

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:

enter image description here

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
1
votes

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

0
votes

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