Excel VBA - 手动调用Userform上的TextBox退出事件?

时间:2016-07-22 20:21:07

标签: vba excel-vba textbox userform excel

我正在构建一个userform,它有两个文本框来输入日期。输入日期后,我会在Exit事件触发时验证它们。如果验证结果显示用户数据不是所需的,则会通知用户,清除文本框,并将焦点返回到文本框。

如果用户使用鼠标在框外选择而不是Tab,则会出现问题。如果使用Tab,它将完全按照预期激发,并清除该字段并返回焦点。如果使用鼠标,则不会触发。根据{{​​3}},这是预期的行为(它是针对Access的,但我没有看到类似的相关MSDN Excel文章。)

所以我尝试了AfterUpdate事件。但是,SetFocusAfterUpdate事件中不起作用,我假设是因为this article的响应中列出的事件链。因此,我没有办法在焦点被触发后将焦点返回到文本框。该线程有一个建议作为另一个控件的SetFocus的替代答案,并作为一种解决方法返回,但这对我不起作用,所以我认为这可能是一个特定于Access的解决方法。

我考虑的最后一个选项是AfterUpdate事件只调用Exit事件,但Exit事件有一个必需的参数(ByVal Cancel As MSForms.ReturnBoolean),这是怎么回事您取消退出并将用户返回到文本框。因此,没有一个值可以传递给它,但不会抛出我能找到的错误(我发现最接近的错误是Nothing但是在尝试将其设置为{{时失败了1}}稍后取消退出。)

有没有办法实现我在这里寻找的东西,或者我应该坚持True并忽略我想要实现的AfterUpdate

3 个答案:

答案 0 :(得分:1)

我知道几个月前就回答了这个问题,但提供了另一种解决方案。对于任何发现这个问题的人。

要验证Excel文本框数据,请使用BeforeUpdate事件,它在AfterUpdate事件之前触发,并且能够防止在控件上失去焦点。

根据您的要求重新设计示例代码

请记住Cancel = True停止对控件的控件更新并保持对焦。

Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    Cancel = doValidation(Textbox1.Text) 'Validation Route
End Sub

Private Function doValidation(strText) as Boolean
    'Do Validation
    if Valid then
        doValidation = False
    Else
        msgBox "Not Valid"
        doValidation = True
    End if
End Sub

在我看来,这是在Excel Userform Textbox上验证输入的最简单方法

我现在无法找到正确的MSDN文章,所有Google想要返回的是Access Results。

答案 1 :(得分:0)

Exit事件适用于所有鼠标点击,它会为表单上的另一个控件启动Enter。但是,当您单击,直接在窗体上而不是任何其他控件时,没有任何反应。

在此处,在退出并移至用户表单之前,使用ActiveControl属性确定您所在的最后一个控件。

示例代码,根据您的要求进行修改。

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Call doValidation(Me.TextBox1.Text)  '/ Validation Routine when user leaves TextBox
End Sub

Private Sub UserForm_Click()
    '/ If user clicked on the user form instead of ay other control
    If Me.ActiveControl.Name = Me.TextBox1.Name Then
        Call doValidation(Me.TextBox1.Text)  '/ Validation Routine when user leaves TextBox
    End If
End Sub

Private Sub doValidation(strText)
        MsgBox strText
End Sub

建议:对于日期输入,使用DateTimePicker代替TextBox,将来可以避免很多麻烦。

答案 2 :(得分:0)

在VBA中,您可以使用单词Call Subname调用任何已定义的子或函数: 例如调用Textbox1_exit(params)

然而,从有些令人困惑的描述中我相信你的问题是你只限于几个事件功能。我建议您探索所有事件功能,看看哪一个适合您的事件火灾。 以下是Access VBA中的事件及其序列列表: https://msdn.microsoft.com/en-us/library/office/jj249049.aspx

以及表单事件的顺序:

https://support.office.com/en-us/article/Order-of-events-for-database-objects-e76fbbfe-6180-4a52-8787-ce86553682f9

我认为对于您的应用程序,您为某些组件提供的lost_focus或got_focus可能很有用。 此外,您可以手动将焦点设置为几乎任何内置方法的组件:compName.SetFocus()