【问题标题】:Loop repeated code to set userform checkbox values循环重复代码以设置用户表单复选框值
【发布时间】:2017-08-27 14:29:39
【问题描述】:

我有一个仪表板,它使用带有复选框的用户表单框字段来选择要在图表上显示的数据。

我的代码非常复制粘贴。

Private Sub CommandButton21_Click()
UserForm1.Show
If Worksheets("Data Directorate").Range("X4").Value = True Then UserForm1.CheckBox1 = True
If Worksheets("Data Directorate").Range("X5").Value = True Then UserForm1.CheckBox2 = True
If Worksheets("Data Directorate").Range("X6").Value = True Then UserForm1.CheckBox3 = True

有没有办法使用循环来做到这一点?

我后面有更多重复的代码:

Private Sub CheckBox1_Click()
  Select Case CheckBox1.Value
  Case True
  Worksheets("Data Directorate").Range("X4").Value = True
  Case False
  Worksheets("Data Directorate").Range("X4").Value = False
End Select
End Sub

这会重复 24 个复选框。可以循环播放吗?

【问题讨论】:

    标签: excel vba loops


    【解决方案1】:

    在这个帖子中发布了所有很棒的建议,所以我想添加一些可能有助于简化循环的内容。控件有一个Tag 属性,据我所知,它除了存储有关控件的附加信息外什么也不做。

    利用这一点,我们可以在每个复选框的Tag 属性中包含链接单元格。 (例如,在Tag 中输入X4 以链接到单元格X4)。这允许更少的信息被硬编码,从而使其更具适应性。

    最后,代码将如下所示。

    Private Sub UserForm_Click()
        For Each octrl In Me.Controls
            If TypeName(octrl) = "CheckBox" Then
                Sheet1.Range(octrl.Tag).Value = octrl.Value
            End If
    
        Next octrl
    End Sub
    

    【讨论】:

    • 哇,太好了,我从来没有想过这个!谢谢!
    • 太棒了!从来不知道这存在!我会对其进行一些错误检查,因为不能保证表单编辑器(人)会记得设置每个 CheckBox 的 .tag 属性 - 特别是如果它在将来的某个时候被修改......
    • @FreeMan 我绝对同意。我通常希望发布者会接受建议并根据需要进行开发。错误检查是必须的,否则空标签会抛出异常。
    • @FreeMan 对不起,我是新手,你所说的一些“错误检查”和 CheckBox 的“标签”属性是什么意思
    • @PatSearle,此答案取决于您将复选框 = 的 .tag 属性设置为存储其选中值的单元格。由于它依赖于您(或在您之后进行维护的人)来手动设置它,因此值得围绕语句编写一些代码以确保在尝试使用之前将 .tag 实际上设置为可用值。即在尝试使用它之前确保你有一个可用的值。
    【解决方案2】:

    我在这种情况下的方法是:

    将复选框的ControlSource 属性设置为适当的单元格,仅保留: UserForm1.Show

    【讨论】:

    • 谢谢,这比编码简单多了!我不知道 ControlSource 是什么。感谢您的帮助。
    【解决方案3】:

    要简化的一件事:不要使用 If 语句,只需使两侧相等即可。像这样:

    Private Sub CommandButton21_Click()
    UserForm1.Show
    
    UserForm1.CheckBox1 = Worksheets("Data Directorate").Range("X4").Value
    

    还有一个:

    Private Sub CheckBox1_Click()
      Worksheets("Data Directorate").Range("X4").Value = CheckBox1.Value
    End Sub
    

    我建议使用更改事件而不是点击事件。有些用户可能会使用TabSpace,则不会触发点击事件。像这样:

    Private Sub CheckBox1_Change()
    ...
    

    关于遍历 CommandButton21_Click 事件中的复选框,这取决于复选框和表格的顺序。这可能有效,但你必须在你的桌子上尝试它(复选框的顺序与单元格的顺序相比可能会破坏游戏......)

    Dim contr As control
    dim i as integer
    i=4
    For Each contr In UserForm1.Controls
      If TypeName(contr) = "CheckBox" Then
        contr.Value = cells(i,24).Value 'column 24 is column X
        i=i+1
      End If
    Next
    

    当 CheckBox 未按预期顺序或被添加/删除时可能会发生变化:

    Dim contr As control
    Dim J as Integer
    Dim Offset as Integer
    
    Offset = 3  'set this to the difference between 1 and the first row containing data
    
    For Each contr In UserForm1.Controls
      If TypeName(contr) = "CheckBox" Then
        'set j to the checkboxes "number"
        J = cInt(right(contr.name, len(contr.name) - len("CheckBox")))
        'use the checkbox number + offset to find the row we want
        contr.Value = cells(J + Offset,24).Value 'column 24 is column X
      End If
    Next
    

    希望这会有所帮助。

    【讨论】:

    • 你的最后一个循环很聪明,但是非常依赖于控制顺序!虽然它可能第一次起作用,但以后对表单的任何更改都可能会破坏它。
    • 是的,但这对于任何尝试迭代复选框的循环来说基本上都是正确的。这就是为什么我不建议使用它。只需复制粘贴即可,无需 If 语句。
    • 酷...你提到过,我只是想为新手强调一下。我将编辑一个适用于这个特定问题的更改(以及其他稍作修改的问题)。如果您不喜欢,请随时删除修改。
    • @FreeMan 和 vaccip。我喜欢使用Tag 属性将单元格直接链接到控件,而不是在实际源代码中以硬编码的方式链接它们。请参阅下面的解决方案以获取替代选项。
    【解决方案4】:

    关于你问题的第二部分:

    Private Sub CheckBox1_Click()
      Worksheets("Data Directorate").Range("X4").Value = CheckBox1.Value
    End Sub
    

    【讨论】:

    • 在那个顶部,我需要循环通过不同的 X 值以及 CheckBox 值。例如 X4=CheckBox1,X5=CheckBox2。我可以让 X 部分循环但是当我尝试添加另一个整数时,例如CheckBoxL,它不会循环通过。它只是说 CheckBoxL 找不到
    • 是的,看到并编辑了。使用Jeanno's answer for that, and mine for your second issue
    • 谢谢。我试试看!
    【解决方案5】:

    您可以在给定框架内对复选框进行分组并尝试以下操作

    Sub Test()
        Dim i As Long
        i = 5
        For Each cb In UserForm1.Frame1.Controls
            If Worksheets("Data Directorate").Range("X" & i).Value = True Then cb.Value = True
            i = i + 1
        Next cb
    End Sub
    

    【讨论】:

    • 这里不需要if语句,只要两边相等即可。此外,cells(i,26)range("X" & i) 快一些。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 2015-10-29
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    相关资源
    最近更新 更多