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 等)和添加到框架的任何新文本框将自动得到处理,无需为其编写处理程序。