我创建了一个 Ms-Access 用户表单,其中有许多文本框。这些盒子被命名为:Box1、Box2、Box3 ...
我需要循环遍历所有框,但我不知道哪个是最后一个。为了避免循环遍历所有用户窗体控件,我想到了以下内容:
For i =1 To 20
If Me.Controls("Box" & i).value = MyCondition Then
'do stuff
End If
Next i
此错误发生在 Box6,这是第一个未找到的盒子。有没有办法捕获这个错误并退出循环?
我可以使用
On Error
,但我宁愿用代码捕获这个特定的实例。
Controls
集合是控件的简化集合(显然),并且与控件的放置顺序共享相同的顺序。
首先,即使是可创建的集合对象也缺少
Exists
或 Contains
等方法,因此您需要一个具有错误处理功能的函数来从集合中检查/提取小部件。
Public Function ExistsWidget(ByVal Name As String) As Boolean
On Error Resume Next
ExistsWidget = Not Me.Controls(Name) Is Nothing
On Error GoTo 0
End Function
如果您真的不喜欢“请求宽恕而不是许可”选项,您可以提取文本框的整个有序集合(和/或在具有类似逻辑的另一个循环中按名称检查是否存在)。
Public Function PullBoxes() As Collection
Dim Control As MSForms.Control
Set PullBoxes = New Collection
For Each Control In Me.Controls
If TypeOf Control Is MSForms.TextBox And _
Left(Control.Name, 3) = "Box" Then
Call PullBoxes.Add(Control)
End If
Next
End Function
由于小部件的名称是唯一的 - 您可以从该函数返回一个
Dictionary
,其中包含 (Control.Name, Control) 对,并且能够通过名称正确检查小部件的存在性,而无需抑制错误。
如果这对您来说是新信息,那么有一个很好的指南Dictionary
。
无论如何,无论您选择什么对象,如果用户(或代码)无法创建更多这些文本框 - 您可以将上面的
Function
转换为 Static Property Get
或仅转换为带有 Property Get
集合的 Static
内部,因此您只需迭代所有控件一次(例如,在 UserForm_Initialize
事件上)!
Public Property Get Boxes() As Collection
Static PreservedBoxes As Collection
'There's no loop, but call to PullBoxes to reduce duplicate code in answer
If PreservedBoxes Is Nothing Then _
Set PreservedBoxes = PullBoxes
Set Boxes = PreservedBoxes
End Property
毕竟,最后创建的名为
TextBox
的 Box*
将会是:
Public Function LastCreatedBox() As MSForms.TextBox
Dim Boxes As Collection
Set Boxes = PullBoxes
With Boxes
If .Count <> 0 Then _
Set LastCreatedBox = Boxes(.Count)
End With
End Function
我想现在事情对你来说更加清楚了!干杯!
注意:所有代码绝对是表单的一堆方法/属性,因此所有内容都应该放在表单模块内。
长话短说——你不能用 VBA 做你想做的事。 然而,有一个很好的方法来解决这个问题 - 创建一个布尔公式,使用
On Error
检查对象是否存在。因此,您的代码不会被它破坏。
Function ControlExists(ControlName As String, FormCheck As Form) As Boolean
Dim strTest As String
On Error Resume Next
strTest = FormCheck(ControlName).Name
ControlExists = (Err.Number = 0)
End Function
取自这里:http://www.tek-tips.com/viewthread.cfm?qid=1029435
要查看整个代码的工作情况,请像这样检查:
Option Explicit
Sub TestMe()
Dim i As Long
For i = 1 To 20
If fnBlnExists("Label" & i, UserForm1) Then
Debug.Print UserForm1.Controls(CStr("Label" & i)).Name & " EXISTS"
Else
Debug.Print "Does Not exist!"
End If
Next i
End Sub
Public Function fnBlnExists(ControlName As String, ByRef FormCheck As UserForm) As Boolean
Dim strTest As String
On Error Resume Next
strTest = FormCheck(ControlName).Name
fnBlnExists = (Err.Number = 0)
End Function
我建议按照下面的另一个程序测试是否存在:-
Private Sub Command1_Click()
Dim i As Long
i = 1
Do Until Not BoxExists(i)
If Me.Conrtols("Box" & i).Value = MyCondition Then
'Do stuff
End If
i = i + 1
Next
End Sub
Private Function BoxExists(ByVal LngID As Long) As Boolean
Dim Ctrl As Control
On Error GoTo ErrorHandle
Set Ctrl = Me.Controls("BoX" & LngID)
Set Ctrl = Nothing
BoxExists = True
Exit Function
ErrorHandle:
Err.Clear
End Function
在上面,
BoxExists
仅在盒子确实存在时返回true。
您在这里采取了错误的方法。
如果您想限制循环,您可以仅在控件所在的部分循环,例如细节。您可以使用
ControlType
属性将控件限制为 TextBox。
Dim ctl As Control
For Each ctl In Me.Detail.Controls
If ctl.ControlType = acTextBox Then
If ctl.Value = MyCondition Then
'do stuff
End If
End If
Next ctl
我相信循环会比通过辅助函数和
On Error Resume Next
检查控件名称是否存在更快。
但这只是个人意见。
我通过搜索“ms word 365 vba 如何确定文档中是否存在特定文本框”找到了这篇文章。
就我而言,我正在 MS Word 中创建绘图。我有几个组合在一起的“绘图对象”以及包含不同文本(ID 号)的相似组的多个副本。
因此,为了避免每次生成新绘图时都重新发明轮子,我打开现有绘图,使用新名称另存为,然后使用 VBA 将绘图对象重新定位在文档一侧更改绘图并将 ID 号放置在新文档上的正确位置。
根据我创建的绘图类型,某些绘图将具有特定的“绘图对象”,而其他绘图则不会。所以我使用以下方法来确定该特定对象是否存在......
Private Sub sort_Nums()
Dim grp As Shape, shp As Object
Dim id As String '<-- object id - could be a # &/or a letter
Dim flg_It_Exists As Boolean
Set doc = Application.ActiveDocument
flg_It_Exists = False
For Each grp In doc.Shapes
If grp.Type = 6 Then '<-- if shape is a group then
For Each shp In grp.GroupItems
If shp.Type = 17 Then '<-- if group contains a textbox then
'pop var "id" to get ID, trim & strip all vbCR/vbLR/vbCRLF
If IsNumeric(id) Then
'manage stuff for # ID
ElseIf [id=string ID] Then
'manage stuff for string ID
ElseIf [id=specific ID] Then
'manage stuff for specific ID
flg_It_Exists = True
End If
End If
Next shp
End If
Next grp
'reposition specific object
If flg_It_Exists Then
'move specific object to its default starting position
End If
'code to manage other objects here
Set doc = Nothing
End Sub
我意识到OP正在询问MS Access中的用户表单,但底层逻辑可能仍然适用。