如何防止在VBA中触发ActiveX事件?

时间:2013-10-09 15:54:46

标签: excel vba excel-vba activex

我正在寻找一种更好的方法来禁止在Excel工作簿中触发ActiveX事件(尽管这适用于所有带有ActiveX对象的Office应用程序)。

希望类似于Application.EnableEvents = false,但这不适用于ActiveX。

在下面的例子中,使用全局布尔值是微不足道的,但是我的ActiveX对象有很多事件处理程序,对于我可以普遍应用于暂时禁用ActiveX事件的东西来说会非常容易。我真的不想为这些方法中的每一个添加if / exit子语句。

要演示此问题,请在工作表中创建ActiveX组合框并将以下内容添加到该工作表模块

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 个答案:

答案 0 :(得分:4)

为什么不禁用它们?这样你也不必担心他们的个人代码。

试试这个

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

ScreenShots之前/之后:

enter image description here

从评论中跟进:

  

事实证明,这会破坏分组在一起的对象的硬核,但我可以取消组合对象(我猜它们不再是“Sheet1.OLEobjects”)。我仍然不喜欢这个,因为它依赖于这个事实,有时我会想要分组对象.. - enderland 17分钟前

要禁用组中的ActiveX控件,您无需取消组合它们。使用此代码。以下代码将禁用组中的Combobox。

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 :(得分:2)

我知道这真的很老了。但任何看起来如此(谷歌首次出现)的人可能都想要一个简单的答案:

假设您有一个Private Sub ActiveXControl_Change(),它在Application.EnableEvents = False期间被调用,您希望它跳过这一步:

Private Sub ActiveXControl_Change()
If Application.EnableEvents = True Then
'enter you code here

End If
End Sub

答案 2 :(得分:1)

在搜索类似问题时遇到了这篇文章。我觉得这里发布的答案不适合我的情况,并提出了其他的建议。我的方法在这里也很有用。

在我的工作簿中,我有一组20个(Activex)复选框。这些基本上过滤/关闭要包含在报告中的20类产品。每次更改其中一个复选框时都会运行一个例程,只需通过从CheckBox_Click例程调用路由即可运行。

然后我还有一个组合框,可以选择这些复选框的各种。麻烦的是,当组合框代码选中(取消)20个复选框中的每个复选框时,会触发计算例程。

我想要的是仅在组合框结尾处运行 ONCE 的计算例程,但如果我手动更改单个复选框,仍然可以使用它。

我的解决方案 - 在隐藏工作表的某个单元格中放入一个TRUE / FALSE代码,它在某个地方不会受到影响并且不会干扰。

然后CheckBox_Click代码变为(对于20个复选框中的每一个):

Private Sub CheckBox6_Click()
If (Sheets("Data").Range("G60")) Then
    Call RangeFind
End If
End Sub

组合框代码适当地修改了这个相同的单元格:

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

干杯,

迈克尔

答案 3 :(得分:0)

这里是一种选择:

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