我正在使用VBS Excel 2010,我正在尝试编写一个循环来将WS中的17行,5列中的单元格传输到我的用户表单,该用户表单还有17行,5列文本框。
每行文本框都为它们所在的行编制索引。例如。 txt.Name1
,txt.City1
... txt,County1
。然后下一行文本框为txt.Name2
,txt.City2
... txt,County2
...
如何遍历每一行并将其传输到等待的一行文本框,而不是为每一行编写代码?
答案 0 :(得分:0)
Cominterm是正确的,“你需要将Textbox控件放入控件数组中”。不幸的是,我发现他建议的链接特别有帮助。
我不需要按照数字访问表单控件多年,所以我生锈了。我按照我自己的方式处理了这个答案:隔离我不知道的功能并编写宏来探索该功能。我记得Controls集合,但不记得如何访问控件的类型,所以我查了一下。
表单上每个控件的详细信息都记录在Controls集合中,就像每个工作表的详细信息都记录在Worksheets集合中一样。如果txtName1
是第6个控件,则可以将其属性设置为Controls(5)
,因为控件的编号为零。例如,代替txtName1.Text = "xxxxxx"
,您可以编写Controls(5) .Text = "xxxxxx"
。
我创建了一个用户表单,并用一种或两种控件填充它。然后我以你想要的格式添加了三行:
我创建了一个包含以下内容的模块:
Option Explicit
Sub Test1()
Load UserForm1
UserForm1.Show vbModal
End Sub
我在表单中编写了以下代码:
Private Type TypeCtrl
Height As Single
Left As Single
Name As String
Parent As String
Top As Single
TypeName As String
Width As Single
End Type
Dim CtrlDtl() As TypeCtrl
Private Sub cmdExit_Click()
Unload Me
End Sub
Private Sub UserForm_Initialize()
Dim InxCtrl As Long
Dim NameLenMax As Long
Dim ParentLenMax As Long
Dim TypeNameLenMax As Long
ReDim CtrlDtl(0 To Controls.Count - 1)
For InxCtrl = 0 To Controls.Count - 1
CtrlDtl(InxCtrl).Name = Controls(InxCtrl).Name
CtrlDtl(InxCtrl).Top = Controls(InxCtrl).Top
CtrlDtl(InxCtrl).Left = Controls(InxCtrl).Left
CtrlDtl(InxCtrl).Width = Controls(InxCtrl).Width
CtrlDtl(InxCtrl).Height = Controls(InxCtrl).Height
CtrlDtl(InxCtrl).Parent = Controls(InxCtrl).Parent.Name
CtrlDtl(InxCtrl).TypeName = TypeName(Controls(InxCtrl))
If NameLenMax < Len(CtrlDtl(InxCtrl).Name) Then
NameLenMax = Len(CtrlDtl(InxCtrl).Name)
End If
If ParentLenMax < Len(CtrlDtl(InxCtrl).Parent) Then
ParentLenMax = Len(CtrlDtl(InxCtrl).Parent)
End If
If TypeNameLenMax < Len(CtrlDtl(InxCtrl).TypeName) Then
TypeNameLenMax = Len(CtrlDtl(InxCtrl).TypeName)
End If
Next
If NameLenMax < Len("Name") Then
NameLenMax = Len("Name")
End If
If ParentLenMax < Len("Parent") Then
ParentLenMax = Len("Parent")
End If
Debug.Print "Inx Name" & Space(NameLenMax - 2) & _
" Top Left Height Width Parent" & _
Space(ParentLenMax - 6) & " Type name"
For InxCtrl = 0 To UBound(CtrlDtl)
With CtrlDtl(InxCtrl)
Debug.Print Right(" " & InxCtrl, 3) & " " & _
Left(.Name & Space(NameLenMax), NameLenMax) & " " & _
Right(Space(8) & Format(.Top, "#,###.00"), 8) & " " & _
Right(Space(8) & Format(.Left, "#,###.00"), 8) & " " & _
Right(Space(8) & Format(.Height, "#,###.00"), 8) & " " & _
Right(Space(8) & Format(.Width, "#,###.00"), 8) & " " & _
Left(.Parent & Space(ParentLenMax), ParentLenMax) & " " & _
.TypeName
End With
Next
End Sub
第一个代码块读取Controls集合,提取所选属性的值并存储在类型为TypeCtrl
的数组中,我已指定该数组来保存所选属性。第二个块将数组中的值输出到立即Windows,以提供:
Inx Name Top Left Height Width Parent Type name
0 Label1 12.00 24.00 18.00 72.00 UserForm1 Label
1 Label2 12.00 114.00 18.00 72.00 UserForm1 Label
2 TextBox1 12.00 210.00 18.00 72.00 UserForm1 TextBox
3 TextBox2 12.00 294.00 18.00 72.00 UserForm1 TextBox
4 ComboBox1 12.00 390.00 18.00 72.00 UserForm1 ComboBox
5 ComboBox2 48.15 24.00 18.00 72.00 UserForm1 ComboBox
6 ListBox1 42.00 120.00 72.00 72.00 UserForm1 ListBox
7 CheckBox1 48.00 294.00 18.00 108.00 UserForm1 CheckBox
8 OptionButton1 138.00 12.00 18.00 108.00 UserForm1 OptionButton
9 ListBox2 42.00 204.00 72.00 72.00 UserForm1 ListBox
10 CheckBox2 72.00 294.00 18.00 108.00 UserForm1 CheckBox
11 OptionButton2 162.00 12.00 18.00 108.00 UserForm1 OptionButton
12 ToggleButton1 132.00 144.00 40.00 36.00 UserForm1 ToggleButton
13 ToggleButton2 132.00 192.00 40.00 36.00 UserForm1 ToggleButton
14 Frame1 120.00 246.00 42.00 66.00 UserForm1 Frame
15 Frame2 120.00 324.00 54.00 72.00 UserForm1 Frame
16 Label3 18.00 12.00 18.00 48.00 Frame2 Label
17 cmdExit 126.00 414.00 24.00 72.00 UserForm1 CommandButton
18 CommandButton2 162.00 414.00 24.00 72.00 UserForm1 CommandButton
19 TabStrip1 192.00 18.00 54.00 90.00 UserForm1 TabStrip
20 TabStrip2 198.00 120.00 48.00 66.00 UserForm1 TabStrip
21 MultiPage1 198.00 186.00 66.00 102.00 UserForm1 MultiPage
22 MultiPage2 204.00 306.00 60.00 72.00 UserForm1 MultiPage
23 ScrollBar1 204.00 390.00 63.80 12.75 UserForm1 ScrollBar
24 SpinButton1 204.00 462.00 25.50 12.75 UserForm1 SpinButton
25 Image1 270.00 18.00 72.00 72.00 UserForm1 Image
26 SpinButton2 204.00 486.00 25.50 12.75 UserForm1 SpinButton
27 ScrollBar2 204.00 414.00 63.80 12.75 UserForm1 ScrollBar
28 txtName1 282.00 108.00 18.00 42.00 UserForm1 TextBox
29 txtStreet1 282.00 156.00 18.00 42.00 UserForm1 TextBox
30 txtTown1 282.00 204.00 18.00 42.00 UserForm1 TextBox
31 txtCounty1 282.00 252.00 18.00 42.00 UserForm1 TextBox
32 txtPostcode1 282.00 300.00 18.00 42.00 UserForm1 TextBox
33 txtName2 306.00 108.00 18.00 42.00 UserForm1 TextBox
34 txtStreet2 306.00 156.00 18.00 42.00 UserForm1 TextBox
35 txtTown2 306.00 204.00 18.00 42.00 UserForm1 TextBox
36 txtCounty2 306.00 252.00 18.00 42.00 UserForm1 TextBox
37 txtPostcode2 306.00 300.00 18.00 42.00 UserForm1 TextBox
38 txtName3 330.00 108.00 18.00 42.00 UserForm1 TextBox
39 txtStreet3 330.00 156.00 18.00 42.00 UserForm1 TextBox
40 txtTown3 330.00 204.00 18.00 42.00 UserForm1 TextBox
41 txtCounty3 330.00 252.00 18.00 42.00 UserForm1 TextBox
42 txtPostcode3 330.00 300.00 18.00 42.00 UserForm1 TextBox
我相信你只需要访问这个名字,但编码可以让我记忆清楚可能的事情。当我第一次需要了解Control集合时,我会为自己编写这种宏,我推荐这种方法。我仔细选择了适用于每种控件的属性。但是,通过检查类型,我可以访问限制为特定类型的属性。
刷新了我的记忆后,我准备编写符合您要求的宏。
您没有为所有五个列命名,所以我创建了五个我自己的列。我只定义了三行足以证明这种方法。您可以在上面列表的底部看到它们。
我创建了一个工作表“Data”并在其中放置了一些数据:
我不知道您的数据是固定的还是可移动的,但是对于我的演示,我已将其修复并使用常量定义其位置。您可以替换我的常量的值或根据需要用变量替换我的常量。
我放弃了表单的原始代码,并将其替换为:
Option Explicit
Const WshtName As String = "Data"
Const RowDataTop As Long = 3
Const ColDataLeft As Long = 2
Const RowDataBot As Long = 5
Const ColDataRight As Long = 6
Dim CtrlForAddressElement(1 To ColDataRight - ColDataLeft + 1, _
1 To RowDataBot - RowDataTop + 1) As Long
Private Sub cmdExit_Click()
Unload Me
End Sub
Private Sub UserForm_Initialize()
Dim ColDataCrnt As Long
Dim ColFormCrnt As Long
Dim InxCtrl As Long
Dim RowDataCrnt As Long
Dim RowFormCrnt As Long
ReDim CtrlDtl(0 To Controls.Count - 1)
' Store index number for each control of the address block
For InxCtrl = 0 To Controls.Count - 1
If Left(Controls(InxCtrl).Name, 7) = "txtName" Then
RowFormCrnt = Val(Mid(Controls(InxCtrl).Name, 8))
CtrlForAddressElement(1, RowFormCrnt) = InxCtrl
ElseIf Left(Controls(InxCtrl).Name, 9) = "txtStreet" Then
RowFormCrnt = Val(Mid(Controls(InxCtrl).Name, 10))
CtrlForAddressElement(2, RowFormCrnt) = InxCtrl
ElseIf Left(Controls(InxCtrl).Name, 7) = "txtTown" Then
RowFormCrnt = Val(Mid(Controls(InxCtrl).Name, 8))
CtrlForAddressElement(3, RowFormCrnt) = InxCtrl
ElseIf Left(Controls(InxCtrl).Name, 9) = "txtCounty" Then
RowFormCrnt = Val(Mid(Controls(InxCtrl).Name, 10))
CtrlForAddressElement(4, RowFormCrnt) = InxCtrl
ElseIf Left(Controls(InxCtrl).Name, 11) = "txtPostcode" Then
RowFormCrnt = Val(Mid(Controls(InxCtrl).Name, 12))
CtrlForAddressElement(5, RowFormCrnt) = InxCtrl
End If
Next
' Move data from worksheet to form
With Worksheets(WshtName)
For RowDataCrnt = RowDataTop To RowDataBot
RowFormCrnt = RowDataCrnt - RowDataTop + 1
For ColDataCrnt = ColDataLeft To ColDataRight
ColFormCrnt = ColDataCrnt - ColDataLeft + 1
InxCtrl = CtrlForAddressElement(ColFormCrnt, RowFormCrnt)
Controls(InxCtrl).Text = .Cells(RowDataCrnt, ColDataCrnt).Value
Next
Next
End With
End Sub
我有一个全局数组CtrlForAddressElement
,我根据需要调整大小以处理常量定义的范围。
第一个代码块将带有索引的数组加载到15个文本框的Controls集合中。
第二个代码块使用此数组将数据从工作表移动到表单以提供:
第二段代码应该可以很容易地适应您的要求。