使vba代码适用于所有框

时间:2014-01-02 19:48:43

标签: excel excel-vba vba

你好,我想做的是让这个代码适用于所有Check Box的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

4 个答案:

答案 0 :(得分:1)

我看到了几个选项(因为这是VBA所以没有一个选项)。

  • 选项1 :为您的所有复选框生成代码。这可能是最可维护的。您首先要为所有复选框选择合理的名称(您可以通过在Excel中选择它们并在左上角重命名来分配它们,或运行代码,如果您已经有很多复选框,它将为您执行此操作。{{ 3}}可能有用)。

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

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

    完成每个复选框的所有代码后,您可以按照以下步骤进行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 :通过数组或“设置”隐藏工作表跟踪所有已检查/未检查的状态,并注意该触发的事件。您可以根据工作表的Changed事件触发,并将行号与您的CheckBox编号匹配,以便您可以取消Target的行号。

我能想到的其他选择变得更加复杂......我有兴趣看看人们有什么其他建议。谢谢!

编辑您可以使用一些代码来引用单个函数,如我的示例中所示,结合brettdj的示例来获得最佳解决方案。 BAM!

答案 1 :(得分:1)

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

的集合

假设你想在ActiveSheet上的所有ActiveX复选框上运行它,那么大量借用Bob Phillip的code from 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
    

答案 2 :(得分:0)

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

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

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

运行此 ResetCheckBoxes 一次以启用复选框并为其指定一个宏,并在即时窗口中显示相关的生成代码(您可能希望每25个复选框暂停一次因为它中的行缓冲区是有限的。)

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个测试复选框): GeneratedCodes

新年快乐伴侣!

答案 3 :(得分:0)

要构建@brettdj提供的解决方案,因为他指定了ActiveX控件,我建议在标准模块中使用以下内容:

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中将对象Key注册为Collection,以便在需要时进行有效索引。
  4. 编辑: 在发布之前我应该​​关注@brettdj提供的链接。我的解决方案使用的原理与此处概述的原理相同。希望在这里记录它也很方便吗?