VBA Excel - 使用相同代码处理多个文本框
VBA Excel - Working with multiple textboxes with the same code
所以我是这个领域的新手。我只想问我是否可以尽量减少使用下面的代码,因为我确实有 13 个文本框具有相同的代码。有没有捷径可以做到这一点?
这是我正在使用的用户窗体 ->
这是代码
Private Sub tb_mtb_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If Not IsNumeric(tb_mtb.Value) Then
MsgBox "Only numbers allowed!", vbOKOnly + vbCritical, "Title"
tb_mtb.Value = ""
End If
End Sub
Private Sub tb_fil_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If Not IsNumeric(tb_fil.Value) Then
MsgBox "Only numbers allowed!", vbOKOnly + vbCritical, "Title"
tb_fil.Value = ""
End If
End Sub
我试过这个 solution 但我不能让它工作。
将其设为子例程并将控件作为参数传递
(如果您想将其放入模块中以使其可重复用于任何形式,请将其设为 Public
):
Public Sub CheckNumeric(ctl as Control)
If Not IsNumeric(ctl.Value) Then
MsgBox "Only numbers allowed!", vbOKOnly Or vbCritical, "Title"
ctl.Value = ""
End If
End Sub
然后对于窗体上的每个控件:
Private Sub tb_fil_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
CheckNumeric tb_fil
End Sub
不过,更好的方法可能是检查 KeyPress
事件中的 KeyAscii
值,并且根本不允许使用非数字字符。
Making VBA Form TextBox accept Numbers only
避免一遍又一遍地编写相同的事件处理程序代码(或者避免为每个类似控件编写一个“存根”处理程序)的“正常”方法是使用“控件数组”。
这是一个基本示例。
首先是一个小自定义 class clsTxt
,可用于从文本框中捕获事件:
Private WithEvents tb As MSForms.TextBox 'note the "WithEvents"
Sub Init(tbox As Object)
Set tb = tbox 'assigns the textbox to the "tb" global
End Sub
'Event handler works as in a form (you should get choices for "tb" in the
' drop-downs at the top of the class module)
Private Sub tb_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii >= 48 And KeyAscii <= 57 Then
Debug.Print tb.Name, "number"
Else
Debug.Print tb.Name, "other"
KeyAscii = 0
End If
End Sub
然后在您的用户窗体中,您可以(例如)抓取框架 frmTest
内的所有文本框并为每个文本框创建一个 clsTxt
实例,将其存储在一个集合中(这是全局和所以在 Activate
事件完成时不会超出范围。
Private colTB As Collection 'holds your class instances
' and keeps them in scope
'This performs the setup
Private Sub UserForm_Activate()
Dim c As Object
Set colTB = New Collection
'loop all controls in the frame
For Each c In Me.frmTest.Controls
'look for text boxes
If TypeName(c) = "TextBox" Then
Debug.Print "setting up " & c.Name
colTB.Add TbHandler(c) ' create and store an instance of your class
End If
Next c
End Sub
' "factory" method
Private Function TbHandler(tb As Object) As clsTxt
Dim o As New clsTxt
o.Init tb
Set TbHandler = o
End Function
设置完成后,每个“连接”文本框的事件将由 class 实例处理(如果您需要管理不同的事情,则可以向 class 添加更多事件,例如Change
等)和添加到框架的任何新文本框将自动得到处理,无需为其编写处理程序。
所以我是这个领域的新手。我只想问我是否可以尽量减少使用下面的代码,因为我确实有 13 个文本框具有相同的代码。有没有捷径可以做到这一点?
这是我正在使用的用户窗体 ->
这是代码
Private Sub tb_mtb_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If Not IsNumeric(tb_mtb.Value) Then
MsgBox "Only numbers allowed!", vbOKOnly + vbCritical, "Title"
tb_mtb.Value = ""
End If
End Sub
Private Sub tb_fil_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If Not IsNumeric(tb_fil.Value) Then
MsgBox "Only numbers allowed!", vbOKOnly + vbCritical, "Title"
tb_fil.Value = ""
End If
End Sub
我试过这个 solution 但我不能让它工作。
将其设为子例程并将控件作为参数传递
(如果您想将其放入模块中以使其可重复用于任何形式,请将其设为 Public
):
Public Sub CheckNumeric(ctl as Control)
If Not IsNumeric(ctl.Value) Then
MsgBox "Only numbers allowed!", vbOKOnly Or vbCritical, "Title"
ctl.Value = ""
End If
End Sub
然后对于窗体上的每个控件:
Private Sub tb_fil_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
CheckNumeric tb_fil
End Sub
不过,更好的方法可能是检查 KeyPress
事件中的 KeyAscii
值,并且根本不允许使用非数字字符。
Making VBA Form TextBox accept Numbers only
避免一遍又一遍地编写相同的事件处理程序代码(或者避免为每个类似控件编写一个“存根”处理程序)的“正常”方法是使用“控件数组”。
这是一个基本示例。
首先是一个小自定义 class clsTxt
,可用于从文本框中捕获事件:
Private WithEvents tb As MSForms.TextBox 'note the "WithEvents"
Sub Init(tbox As Object)
Set tb = tbox 'assigns the textbox to the "tb" global
End Sub
'Event handler works as in a form (you should get choices for "tb" in the
' drop-downs at the top of the class module)
Private Sub tb_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii >= 48 And KeyAscii <= 57 Then
Debug.Print tb.Name, "number"
Else
Debug.Print tb.Name, "other"
KeyAscii = 0
End If
End Sub
然后在您的用户窗体中,您可以(例如)抓取框架 frmTest
内的所有文本框并为每个文本框创建一个 clsTxt
实例,将其存储在一个集合中(这是全局和所以在 Activate
事件完成时不会超出范围。
Private colTB As Collection 'holds your class instances
' and keeps them in scope
'This performs the setup
Private Sub UserForm_Activate()
Dim c As Object
Set colTB = New Collection
'loop all controls in the frame
For Each c In Me.frmTest.Controls
'look for text boxes
If TypeName(c) = "TextBox" Then
Debug.Print "setting up " & c.Name
colTB.Add TbHandler(c) ' create and store an instance of your class
End If
Next c
End Sub
' "factory" method
Private Function TbHandler(tb As Object) As clsTxt
Dim o As New clsTxt
o.Init tb
Set TbHandler = o
End Function
设置完成后,每个“连接”文本框的事件将由 class 实例处理(如果您需要管理不同的事情,则可以向 class 添加更多事件,例如Change
等)和添加到框架的任何新文本框将自动得到处理,无需为其编写处理程序。