用户窗体以看似相反的顺序循环

Userform loops in seemingly reverse order

我有一个包含 7 个复选框和一些描述它们的标签的用户表单。对于每个相应的复选框,都有一个数组,如果复选框被选中,将从中创建一个报告。但是,它没有正确循环。

我希望它以 A, B, C, D, E, F, G 的形式循环遍历每个分别具有 TabIndex 个数字 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

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

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

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

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

逻辑:创建一个二维数组。在数组中存储 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