Excel VBA Userform - 当某些内容发生变化时执行Sub

Ash*_*hok 7 excel vba excel-2007 excel-vba userform

我有一个包含大量文本框的用户表单.当这些文本框的值发生变化时,我需要通过调用子程序AutoCalc()来重新计算基于文本框值的最终结果值.

我有大约25个盒子,我不想单独向调用所述子例程的每个文本框添加一个Change()事件.每当某些值发生变化时,调用AutoCalc()的最快捷有效的方法是什么?

Ale*_*x P 14

这可以通过使用类模块来实现.在下面的示例中,我将假设您已经拥有一个带有一些文本框的用户窗体.

首先,在VBA项目中创建一个类模块(让我们调用它clsTextBox- 确保更改类模块的'Name'属性!)

Private WithEvents MyTextBox As MSForms.TextBox

Public Property Set Control(tb As MSForms.TextBox)
    Set MyTextBox = tb
End Property

Private Sub MyTextBox_Change()
    AutoCalc() //call your AutoCalc sub / function whenever textbox changes
End Sub
Run Code Online (Sandbox Code Playgroud)

现在,在userform中,添加以下代码:

Dim tbCollection As Collection

Private Sub UserForm_Initialize()
    Dim ctrl As MSForms.Control
    Dim obj As clsTextBox

    Set tbCollection = New Collection
        For Each ctrl In Me.Controls
            If TypeOf ctrl Is MSForms.TextBox Then
                Set obj = New clsTextBox
                Set obj.Control = ctrl
                tbCollection.Add obj
            End If
        Next ctrl
    Set obj = Nothing

End Sub
Run Code Online (Sandbox Code Playgroud)


Pau*_*aum 6

如上面的答案所示,课堂使用是一种以简洁优雅的方式处理许多控件的好策略,但是:

1)我发现使用1行创建25个事件没有问题,调用一个常见的userform私有例程,除非控件的数量是动态的.这是一个KISS哲学.

2)一般来说,我认为Change事件非常令人不安,因为他完成了每个数字输入的所有重新计算.使用Exit事件或Before Update事件更加明智和适度,因为它仅在决定值时才进行重新计算.例如,谷歌即时骚扰我试图返回响应,消耗资源,而无需用户定义问题.

3)存在验证问题.我同意您可以通过Change事件避免错误的键,但是如果您需要验证数据,则无法知道用户是否将继续键入或者数据是否已准备好进行验证.

4)您应该记住,更改退出事件不会强制用户传入文本字段,因此在尝试退出表单而不取消时需要重新验证并重新计算系统.

以下代码对于静态表单很简单但有效.

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Call  AutoCalc(Cancel)
End Sub

Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Call  AutoCalc(Cancel)
End Sub
.....
Private Sub TextBox25_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Call  AutoCalc(Cancel)
End Sub

Private Function Valid
.....
End Function 

Private Sub AutoCalc(Canc As Variant)
If Not Valid() Then Canc=True
'  Calculation
End Sub
Run Code Online (Sandbox Code Playgroud)

您沉迷于节省时间,您可以创建一个通用的VBA例程,以便以适合掩码的形式生成与控件相关的事件的代码.此代码可以在草稿表中(更安全,直接生成代码,在某些Excel版本中有错误),而不是复制并粘贴到表单模块.

 Sub GenerateEvent(Form As String, Mask As String, _
   Evento As String, Code As String)
 '  Form - Form name in active workbook
 '  Mark - String piece inside control name
 '  Evento - Event name to form procedure name
 '  Code   - Code line inside event
 Dim F As Object
 Dim I As Integer
 Dim L As Long
 Dim R As Range
 Dim Off As Long
 Set F = ThisWorkbook.VBProject.VBComponents(Form)
 Set R = ActiveCell   ' Destination code
 Off = 0
 For I = 0 To F.Designer.Controls.Count - 1
    If F.Designer.Controls(I).Name Like "*" & Mask & "*" Then
        R.Offset(Off, 0) = "Private Sub " & _
          F.Designer.Controls(I).Name & "_" & Evento & "()"
        R.Offset(Off + 1, 0) = "     " & Code
        R.Offset(Off + 2, 0) = "End Sub"
        Off = Off + 4
    End If
 Next I
 End Sub

 Sub Test()
 Call GenerateEvent("FServCons", "tDt", "Exit", _
    "Call AtuaCalc(Cancel)")
 End Sub
Run Code Online (Sandbox Code Playgroud)


Dou*_*ncy 5

看看这个如何创建一个响应任何文本框中的更改的类.该示例适用于按钮,但可以进行修改.但是,请注意,Textbox控件没有Exit事件(该事件实际上是userform的一部分),因此您必须使用Change事件.