用户表单以相反的顺序循环

时间:2019-02-15 15:03:09

标签: excel vba loops userform

我有一个包含7个复选框的用户窗体和一些描述它们的标签。对于每个对应的复选框,都有一个数组,如果该复选框被选中为true,则会从该数组创建报告。但是,它无法正确循环。

对于每个具有A, B, C, D, E, F, GTabIndex的复选框,我希望它作为0, 1, 2, 3, 4, 5, 6循环通过。但是,它以0,6,5,4,3,2,1的顺序循环遍历。

我有一个主子定义和声明变量。我的用户表单打印代码如下:

Sub Get_PDF_Click()
' Creating PDF

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

PDFUserForm.Hide
i = 0
j = 0
For Each ctl In Me.Controls
    If TypeName(ctl) = "CheckBox" Then
        If ctl.Value = True Then
            j = j + 1
            Name_of_File = Array(i + 1, 1) & " report" & YYMM & ".xlsx"
            Workbooks.Open Filename:=OutputPath & Name_of_File
            Set Wkb = Workbooks(Name_of_File)
                For Each ws In Wkb.Worksheets
                    PDF_Name = Array(i + 1, 1) & " " & ws.Name & " " & YYMM
                    ws.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
                    OutputPath & PDF_Name, Quality _
                    :=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
                    :=False, OpenAfterPublish:=False
                Next ws
            Wkb.Close SaveChanges:=False
        End If ' See if checked
    i = i + 1
    Debug.Print ctl.Name
    End If ' See if checkbox
Next ctl

If j > 0 Then
    ' Notification on process time
    SecondsElapsed = Round(Timer - StartTime, 0)
    MsgBox "PDF succesfully published after " & SecondsElapsed & " seconds." & Chr(10) & "Location: " & OutputPath, vbInformation
Else
    MsgBox "No file was selected.", vbInformation
End If

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

End Sub

顺便说一句,我在另一段代码中遇到了类似的问题,即我在工作表中的图表之间循环,而图表又以错误的顺序循环,因此也许可以将相同的解决方案概念应用于此。

2 个答案:

答案 0 :(得分:3)

未指定

For Each来保证枚举顺序。很有可能按添加控件的顺序枚举控件Me.Controls集合。

如果您需要特定的订单,请使用For循环:

Dim checkboxNames As Variant
checkboxNames = Array("chkA", "chkB", "chkC", "chkD", "chkE", ...)

Dim current As Long, checkboxName As String, currentBox As MSForms.CheckBox
For current = LBound(checkboxNames) To UBound(checkboxNames)
    checkboxName = checkboxNames(current)
    Set currentBox = Me.Controls(checkboxName)
    'work with the currentBox here
Next

请注意,这也消除了迭代您不感兴趣的控件的需求

答案 1 :(得分:3)

这是另一种方法;)这不需要您为复选框的名称进行硬编码。

逻辑:创建2D阵列。将TabindexCheckBox名称存储在数组中。在Tabindex上对其进行排序,然后根据需要使用它:)

代码

Option Explicit

Private Sub Sample()
    Dim CbArray() As String
    Dim n As Long: n = 1
    Dim cbCount As Long
    Dim tindex As String, ctlname As String
    Dim ctl As Control
    Dim i As Long, j As Long

    For Each ctl In Me.Controls
        If TypeName(ctl) = "CheckBox" Then
           n = n + 1
        End If
    Next

    n = n - 1: cbCount = n

    ReDim CbArray(1 To n, 1 To 2)

    n = 1

    '~~> Sort the Tabindex and checkbox name in the array
    For Each ctl In Me.Controls
        If TypeName(ctl) = "CheckBox" Then
           CbArray(n, 1) = ctl.TabIndex
           CbArray(n, 2) = ctl.Name
           n = n + 1
        End If
    Next

    '~~> Sort the array
    For i = 1 To cbCount
        For j = i + 1 To cbCount
            If CbArray(i, 1) < CbArray(j, 1) Then
                tindex = CbArray(j, 1)
                ctlname = CbArray(j, 2)

                CbArray(j, 1) = CbArray(i, 1)
                CbArray(j, 2) = CbArray(i, 2)

                CbArray(i, 1) = tindex
                CbArray(i, 2) = ctlname
            End If
        Next j
    Next i

    '~~> Loop through the checkboxes
    For i = cbCount To 1 Step -1
        With Controls(CbArray(i, 2))
            Debug.Print .Name
            '
            '~~> Do what you want
            '
        End With
    Next i
End Sub