I have a userform of 7 checkboxes and some labels that describe them. For each corresponding checkbox there is an array from which there will be created a report if the checkbox is checked as true. However, it doesn't loop through correctly.
I want it to loop through as A, B, C, D, E, F, G
for for each checkbox who have the TabIndex
numbers of 0, 1, 2, 3, 4, 5, 6
respectively. However it loops through in the order of 0,6,5,4,3,2,1
.
I have a main sub that defines and declares variables. My userform print code is as follows:
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
As an aside I have a similar problem in another piece of code where I loop through charts on a worksheet which is also looping in the wrong order, so perhaps the same solution concept can be applied to that.
For Each
isn't specified to guarantee an enumeration order. In all likelihood the controls are being enumerated in the order they were added to the Me.Controls
collection.
If you need a specific order, use a For
loop:
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
Note that this also removes the need to iterate controls you're not interested in