使vba代码适用于所有框

你好,所以我想要做的是使这个代码适用于所有checkbox的1-50我希望代码只影响被点击的框。

Private Sub CheckBox1_Click() If MsgBox("Do you want to lock this box?", vbYesNo, "Warning") = vbYes Then ActiveSheet.CheckBox2.Enabled = False Else End If End Sub 

我看到几个选项(其中没有一个是漂亮的,因为这是VBA)。

  • 选项1 :为您的所有checkbox生成代码。 这可能是最可维护的。 您首先会为所有checkboxselect合理的名称(您可以通过在Excel中select并在左上angular重命名来指定它们,或者运行代码,如果您已经有很多checkbox,将会为您执行此操作)。有用)。

    然后,您可以生成代码,并使您的每个子程序如下所示:

     'example code for one checkbox Private Sub chkBox_1_Click() Call lockMeUp(Sheet1.chkBox_1.Object) End Sub 

    完成每个checkbox的所有代码后,可以按如下所示使用lockMeUp子过程:

     Sub lockMeUp(chkBox as Object) If MsgBox("Do you want to lock this box?", vbYesNo, "Warning") = vbYes Then chkBox.Enabled = False End If End Sub 
  • 选项2 :通过arrays或“设置”隐藏表logging所有您选中/未选中的状态,并注意触发的事件。 您可以基于表单的Changed事件启动,并将行号与您的CheckBox号码匹配,以便您可以脱离Target的行号。

我能想到的其他选项变得更加复杂…我有兴趣看看有什么其他的build议。 谢谢!

编辑您可以使用一些代码来引用一个单一的function,在我的例子中,结合brettdj的例子来获得您的最佳解决scheme。 巴姆!

简单的方法是编写一个class module ,将一个代码例程应用于Checkboxes的集合

假设yu想在ActiveSheet所有ActiveXcheckbox上运行这个,然后从Bob Phillip的VBAX代码中大量借用

  1. 插入一个名为clsActiveXEvents类模块

    选项显式

     Public WithEvents mCheckboxes As MSForms.CheckBox Private Sub mCheckboxes_Click() mCheckboxes.Enabled = (MsgBox("Do you want to lock this box?", vbYesNo, "Warning") = vbNo) End Sub 
  2. 在一个正常的模块中使用这个代码

     Dim mcolEvents As Collection Sub Test() Dim cCBEvents As clsActiveXEvents Dim shp As Shape Set mcolEvents = New Collection For Each shp In ActiveSheet.Shapes If shp.Type = msoOLEControlObject Then If TypeName(shp.OLEFormat.Object.Object) = "CheckBox" Then Set cCBEvents = New clsActiveXEvents Set cCBEvents.mCheckboxes = shp.OLEFormat.Object.Object mcolEvents.Add cCBEvents End If End If Next End Sub 

如果你不知道,所有的表单控件被视为工作表中的形状。

我有一个解决scheme,你需要创build一个新的模块,复制粘贴在下面的代码,然后从立即窗口到相同的模块。 有一些假设:

  • 所有checkbox对象都被命名为“ checkbox# ”,其中是一个数字
  • 工作簿的任何其他模块中没有名为ResetCheckBoxes()的macros
  • 工作簿的任何其他模块中没有名为CheckBox#_Click()的macros

运行这个ResetCheckBoxes一次启用checkbox并为您指定一个macros,并在相应的生成代码在直接窗口中(您可能希望在循环中每隔25个checkbox放置一个暂停,因为行缓冲区是有限的)。

 Sub ResetCheckBoxes() Dim oWS As Worksheet, oSh As Shape, sTmp As String Set oWS = ThisWorkbook.ActiveSheet For Each oSh In oWS.Shapes With oSh If .Type = msoFormControl Then If InStr(1, .Name, "Check Box", vbTextCompare) = 1 Then .ControlFormat.Enabled = True sTmp = "CheckBox" & Replace(oSh.Name, "Check Box ", "") & "_Click" .OnAction = sTmp Debug.Print "Sub " & sTmp & "()" Debug.Print vbTab & "ActiveSheet.Shapes(""" & .Name & """).ControlFormat.Enabled = False" Debug.Print "End Sub" & vbCrLf End If End If End With Next End Sub 

示例立即窗口输出(2个testingcheckbox): GeneratedCodes

新年快乐伴侣!

为了构build@brettdj提供的解决scheme,由于他指定了ActiveX控件,因此我将在标准模块中提出以下build议:

 Dim mcolEvents As Collection Sub Test() Dim cCBEvents As clsActiveXEvents Dim o As OLEObject Set mcolEvents = New Collection For Each o In ActiveSheet.OLEObjects If TypeName(o.Object) = "CheckBox" Then Set cCBEvents = New clsActiveXEvents Set cCBEvents.mCheckboxes = o.Object mcolEvents.Add cCBEvents, o.Name End If Next End Sub 

差异是:

  1. 我使用OLEObjects Collection因为它更直接,并且不浪费时间在非OLE形状上。
  2. 我使用TypeName而不是(神秘的) TypeOf运算符,因为(显然)后者不区分OptionButtonCheckBox
  3. 我将对象Name注册为Collection Key ,以便在需要时进行高效的索引。

编辑:我应该在发布之前遵循@brettdj提供的链接。 我的解决scheme使用了与此处概述的相同的原则。 希望它能方便地把它logging在这里呢?