【问题标题】:How to prevent ActiveX events firing in VBA?如何防止在 VBA 中触发 ActiveX 事件?
【发布时间】:2013-10-09 15:54:45
【问题描述】:

我正在寻找一种更好的方法来禁止在 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

【问题讨论】:

  • + 1 个好问题!你让我想了一会儿:)
  • 我的代码是 Excel 的示例。 MS Word/PowerPoint 的逻辑保持不变。不过不确定 MS Access/Project/Outlook。

标签: vba excel activex


【解决方案1】:

我知道这真的很老了。但是任何查找此内容的人(第一次点击谷歌)可能想要一个简单的答案:

假设您有一个 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】:

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

    试试这个

    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
    

    屏幕截图之前/之后:

    评论跟进:

    事实证明,这打破了组合在一起的对象的硬核,但我可以取消组合对象(我猜它们不再在“Sheet1.OLEobjects”中)。我仍然不太喜欢这个,因为它依赖于这个事实,而且有时我确实想对对象进行分组.. – enderland 17 分钟前

    要禁用组中的 ActiveX 控件,您无需取消组合。使用此代码。下面的代码将禁用组中的组合框。

    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
    

    【讨论】:

    • 嗯。所以这是一种有趣的方法,但不幸的是,我有一些不是组合框的对象,它们开始具有可变的启用/禁用状态 - 我可能可以构建一个包含所有名称的字典并恢复它,但这似乎也有点傻。有没有一种简单的方法来检查 OLEobject 是否是组合框? Typename() 和 .Type 都返回相同的 (?)。我发誓我以前做过这个,但我不记得是怎么做到的......
    • +1 我的编辑 - If TypeOf OLEobj.Object Is MSForms.ComboBox。事实证明,这破坏了组合在一起的对象的硬核,但我可以取消组合对象(我猜它们不再在“Sheet1.OLEobjects”中)。我仍然不太喜欢这个,因为它依赖于这个事实,而且有时我确实想对对象进行分组..
    • 我正在用那行代码编辑它:P 然后我看到了你的编辑。事实上我给你一个链接到我的另一个帖子HERE
    • 顺便说一句,您不必取消组合形状。您可以直接禁用它们;)我已经更新了上面的帖子
    • 嗯。这比 DLL 地狱更糟糕,因为我认为我将不得不包装我的每一个 _change() 方法,这些方法会以某种保护方式更新其他文本框,以免引发连锁反应。因为即使我在组合框的初始填充中使用启用/禁用,每次修改一个会影响其他组合框时,我都会再次启动该过程......所以每个都必须包含一个 if isUpdating then exit sub 方法其次是isUpdating = true(或禁用/启用工作表上的所有组合框,就像你建议的那样)
    【解决方案3】:

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

    在我的工作簿中,我有一组 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
    

    干杯,

    迈克尔

    【讨论】:

      【解决方案4】:

      这是一种选择:

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-03
        • 1970-01-01
        • 2010-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多