【问题标题】:VBA for loop not workingVBA for 循环不起作用
【发布时间】:2018-04-22 19:18:48
【问题描述】:

我的循环有问题。我想做一个工作表,打印它(还没有内置,我知道它是如何工作的),然后删除它。之后继续下一个 j 做同样的事情。但它正在将 j = 1 重新循环为 1,因此它试图创建第二个名为“print”的工作表,这是不可能的。

我有名称为:CheckBox1、CheckBox2、CheckBox'j' 的复选框。我想从 CheckBox1 开始,以 CheckBox25 结束。如果是真的,那么打印这张纸。

我想我需要摆脱第一个 For:
对于 Me.Controls 中的每个 ctrl
但我不知道如何。因为我需要它来指定变量'j'。

Private Sub PrintKnop_Click()

    Dim ctrl As MSForms.Control
    For Each ctrl In Me.Controls
        If TypeName(ctrl) = "CheckBox" And Left(ctrl.Name, 8) = "CheckBox" Then
            Dim j As Integer
            j = Mid(ctrl.Name, 9, 2)

            For j = 1 To 1
            'it should be possible to adjust the range.
                If ctrl.Value = True Then
                    Dim ws As Worksheet
                    With ThisWorkbook
                    Worksheets("Veiligheid").Copy _
                    before:=ActiveWorkbook.Sheets("Data")
                    Set ws = ActiveSheet
                    ws.Name = "print"
                    End With

                    'Application.DisplayAlerts = False
                    'Sheets("print").Delete
                    'Application.DisplayAlerts = True
                    'These shouldn't be comments, but if I uncomment it, it won't show the failures.

                End If
            Next

            For j = 2 To 4
                If ctrl.Value = True Then
                    With ThisWorkbook
                    Worksheets("Veiligheid").Copy _
                    before:=ActiveWorkbook.Sheets("Data")
                    Set ws = ActiveSheet
                    ws.Name = "printen"
                    End With

                    'Application.DisplayAlerts = False
                    'Sheets("printen").Delete
                    'Application.DisplayAlerts = True
                End If
            Next
        End If
    Next

End Sub

【问题讨论】:

  • 如果下一行使用j 作为for 循环的索引,那么j = Mid(ctrl.Name, 9, 2) 的意义何在?无论如何For j = 1 To 1 只会运行一次,但它嵌入在一个更大的循环中,可能会运行多次。我觉得这个问题很不清楚。如果您希望代码只运行一次,请不要将其置于循环中。
  • 如果您正在寻找这些值docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/…,您想使用 case select 而不是 for next

标签: vba excel userform


【解决方案1】:

我在这里看到的一个问题是您多次使用变量 j。

j = Mid(ctrl.Name, 9, 2)
...
For j = 1 to 1
...
For j = 2 to 4
...

行 j = Mid(ctrl.Name, 9, 2) 会给 j 赋值。

For j = 1 to 1 的行将设置 j = 1 并循环一次。

For j = 2 到 4 的行将设置 j = 2 并在每个循环中递增 j(运行 3 次)

您确定它是在 For j = to 1 循环上循环,而不仅仅是继续到第二个循环吗?

Sub test()

j = 2 + 3
Debug.Print j

For j = 99 to 99
 Debug.print j
Next

For j = 2 to 4
 Debug.print j
Next

End Sub

这会输出值 5、99、2、3、4

当值不按数字顺序排列时可能会更明显。

【讨论】:

  • 我想循环 j = 1 到 25。但是当 j = 1 到 1 时,我需要它来做某事。当 j = 2 到 4 时,我想做其他事情。等等。
  • @Steffie 如果你想从 j = 1 循环到 25,有一个包含一些 if 语句的循环。
  • 但我不想做 25 个 if 语句。
【解决方案2】:

看起来您在循环中有重复操作,并且您正在寻找类似开关的操作。我猜您的意思是将 CheckBox 的编号解析为变量j。当你得到它时,循环的其余部分是这样的:

    ... Prepare variables for this loop round ...

    If j = 1 Then
        ... do something ...
    Else
        ... do something else ...
    End If

    ... Put here the part that stays the same regardless the j value ...

并且本节不需要 For 循环。

【讨论】:

  • 是的,如果有很多情况,我会选择Select Case。
【解决方案3】:

您可能会将For j = 循环与if j = 混淆

for j = 会将您的变量设置为等于它后面的值

使用 select case j 语句可能会更好

Private Sub PrintKnop_Click()
    Dim ctrl As MSForms.Control
    For Each ctrl In Me.Controls
        If TypeName(ctrl) = "CheckBox" And Left(ctrl.Name, 8) = "CheckBox" And ctrl.Value = True Then
            Dim j As Integer
            j = Mid(ctrl.Name, 9, 2)
            Select Case j
                Case 1
                    'it should be possible to adjust the range.
                    Dim ws As Worksheet
                    With ThisWorkbook
                      Worksheets("Veiligheid").Copy _
                        before:=ActiveWorkbook.Sheets("Data")
                      Set ws = ActiveSheet
                      ws.Name = "print"
                    End With
                    'Application.DisplayAlerts = False
                    'Sheets("print").Delete
                    'Application.DisplayAlerts = True
                    'These shouldn't be comments, but if I uncomment it, it won't show the failures.
                Case 2 To 4
                    With ThisWorkbook
                      Worksheets("Veiligheid").Copy _
                        before:=ActiveWorkbook.Sheets("Data")
                      Set ws = ActiveSheet
                      ws.Name = "printen"
                    End With
                    'Application.DisplayAlerts = False
                    'Sheets("printen").Delete
                    'Application.DisplayAlerts = True
            End Select
        End If
    Next
End Sub

【讨论】:

    【解决方案4】:

    对于相同的 J,您有 2 个循环。如果您的代码需要不同的东西来获得不同的 J 值,我认为这个解决方案可能会有所帮助:

    ja = ja&"|"&Mid(ctrl.Name, 9, 2)
    j = split(ja,"|")
    for i = 0 to uBound(j)
    if cInt(j(i))=1 then do something
    if j(i)>1 AND j(i)<5 then do something 'j=2,3,4
    if j(i)>4 AND j(i)<26 then do something 'j=5-25
    next
    

    BUTMid(ctrl.Name, 9, 2) 表示您有 两个 符号,对于 CheckBox1,它是“x1”,NOT“@ 987654324@"。这意味着,在您的代码中,jx1。 您需要将复选框重命名为两位数索引,例如“CheckBox01”

    或者,您可以再添加一行:

    j = Mid(ctrl.Name, 9, 2)
    IF LEFT(j,1)="x" then j=RIGHT(j,1)
    For j = 1 to 25
    if j = 1 then....
    if j >1 then...
    next
    

    这使您只能从 x1

    获得 1

    编辑 刚刚注意到,“CheckBox1”的长度为 9。您可能需要从右侧 2 个符号中获取复选框编号:

    j = RIGHT(ctrl.Name,2)
    

    并且,去掉“x”:

    IF LEFT(j,1)="x" then j=RIGHT(j,1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      • 2013-12-31
      • 2016-05-13
      • 2018-09-09
      相关资源
      最近更新 更多