我有一个包含7个复选框的用户窗体和一些描述它们的标签。对于每个对应的复选框,都有一个数组,如果该复选框被选中为true,则会从该数组创建报告。但是,它无法正确循环。
对于每个具有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
顺便说一句,我在另一段代码中遇到了类似的问题,即我在工作表中的图表之间循环,而图表又以错误的顺序循环,因此也许可以将相同的解决方案概念应用于此。
答案 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阵列。将Tabindex
和CheckBox
名称存储在数组中。在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