【问题标题】:Creating a Dynamic CheckBox Variable创建动态 CheckBox 变量
【发布时间】:2019-12-10 02:29:55
【问题描述】:

我创建了一个用户表单,它根据多个工作表上的单元格值填充了复选框。我根据单元格值命名复选框(它们都不相同),但单元格的数量会随着时间而变化,所以我希望有一个代码填充用户表单,而不是手动放入每个复选框。我希望能够如果单击其复选框但我的代码不起作用,则调用特定的单元格值信息。我想我需要创建一个每次都会更改的动态复选框变量。除了最后一个复选框,我目前无法调用任何复选框。

    Public chkBox As MSForms.CheckBox

    Public Sub UserForm_Initialize()

    MemNumCombo.Clear

    Dim o As Long
    Dim chkL As Double
    Dim chkT As Double
    Dim chkH As Double
    Dim chkW As Double

    chkL = 125
    chkT = 5
    chkH = 15
    chkW = 80

    o = 2
    Do Until Worksheets("Operations").Cells(o, 1).Value = "Division:"

        Set chkBox = Me.Controls.Add("Forms.CheckBox.1", Worksheets("Operations").Cells(o, 1).Value & Worksheets("Operations").Cells(o, 3).Value & "Check")

        chkBox.Caption = Worksheets("Operations").Cells(o, 1).Value & " " & Worksheets("Operations").Cells(o, 3).Value

        chkBox.Left = chkL
        chkBox.Top = chkT + (o - 1) * 20
        chkBox.Height = chkH
        chkBox.Width = chkW

        o = o + 1
    Loop

'...
   End Sub

我知道当代码运行时 chkBox 的名称是正确的,但我以后不能通过它的名称调用 chkBox。代码运行完成后,我只能调用最后一个 chkBox。

【问题讨论】:

    标签: excel vba controls userform


    【解决方案1】:

    (不能)按名称调用 chkBox...

    您在循环中将chkBox 对象设置为内存,从而将一个复选框覆盖为下一个复选框;在代码之后的某处通过chkBoxchkBox.Value 单独引用变量将返回(设置对象本身或例如值)last 复选框。

    通过Controls 集合调用复选框

    通过Set chkBox = Me.Controls.Add("Forms.CheckBox.1", Worksheets("Operations").Cells(o, 1).Value & Worksheets("Operations").Cells(o, 3).Value & "Check") 使用Controls.Add 方法,您已经定义了名称(由工作表“操作”中的两列加上后缀“检查”连接而成)。

    您可以通过Controls 集合调用这些名称之一的复选框;假设您的其中一个复选框实际上被命名为 "XY47Check",您可以通过 Me.Controls("XY47Check") 对其进行寻址。

    列出复选框名称

    一个非常简单且有用的方法是将所有复选框名称分配给一个数组,您可以按预定义的工作表顺序通过索引来寻址。

    只需[1]在你的用户表单代码模块的声明头中声明一个变量数组Dim ChkNames()[2]添加调用代码行

        FillChkNames
    

    到您的Userform_Initialize 过程以及[3] 以下帮助程序Sub FillChkNames() 到您的用户表单模块:

    Private Sub FillChkNames()
    ' Purpose: populate array ChkNames at userform module level
    ReDim ChkNames(Me.Controls.Count - 1)
    Dim ctl As MSForms.Control, i&
    For Each ctl In Me.Controls
        If TypeName(ctl) = "CheckBox" Then ChkNames(i) = ctl.Name: i = i + 1
        Debug.Print ctl.Name, ctl.Value, TypeName(ctl)
    Next ctl
    ReDim Preserve ChkNames(i - 1)
    
    End Sub
    
    
    

    这允许您按名称获取所有复选框

    用户表单代码模块中任何地方的一些示例调用

    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' List all combo names in array
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      Debug.Print Join(ChkNames, "|")
    ' List all combo names plus values
      Dim chkName As Variant
      For Each chkName In ChkNames
          Debug.Print chkName, Me.Controls(chkName)
      Next chkName
    
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' List single value - e.g. the third check box in array
    ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      Dim myNum As Long: myNum = 2                          ' zero-based index 2 refers to third item in array
      If myNum <= UBound(ChkNames) Then
          Debug.Print "Index no " & myNum & " ~> Value: " & Me.Controls(ChkNames(myNum))
      Else
          Debug.Print "Invalid index :-(" & myNum & ")"
      End If
    
    

    高级方法

    或者,您可以使用 对象集合 而不是单个对象,并使用类研究 SO 中的其他大量示例,例如在assign event handlers to controls on userform created dynamically

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-26
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      相关资源
      最近更新 更多