如何在不调用 _Change 函数的情况下清除用户窗体文本框?

How to clear userform textbox without calling the _Change function?

我在 Excel 中有一个用户表单,其中的文本框仅用于数字数据。我想在检测到错误输入并给出错误消息时清除文本框,但我不想再次调用文本框的 _Change 函数,否则消息会弹出两次,因为我将文本更改为“”。我没有看到内置的清除功能。有更好的方法吗?

Private Sub txtbox1_Change()
    txt = userform.txtbox1.Value
    If Not IsNumeric(txt) Then
        disp = MsgBox("Please only enter numeric values.", vbOKCancel, "Entry Error")
        txtbox1.Text = ""
    End If
End Sub

阻止用户输入字母字符:

Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
    Case Asc("0") To Asc("9")
    Case Asc("-")
        If Instr(1,Me.TextBox1.Text,"-") > 0 Or Me.TextBox1.SelStart > 0 Then
            KeyAscii = 0
        End If
    Case Asc(".")
        If InStr(1, Me.TextBox1.Text, ".") > 0 Then
            KeyAscii = 0
        End If
    Case Else
        KeyAscii = 0
End Select
End Sub

希望对您有所帮助! -休格斯

实现此目的的一个简单方法是使用 _Exit() 函数:

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If Not IsNumeric(TextBox1.Value) Then
        MsgBox "Please only enter numeric values.", vbCritical, "Error"
End If
End Sub

只要文本框失去焦点就会触发。

似乎因为没有内置的东西可以做我想做的事,这将是处理问题的最简单方法:

Private Sub txtbox1_Change()
txt = userform.txtbox1.Value
If (Not IsNumeric(txt)) And (txt <> "") Then
    disp = MsgBox("Please only enter numeric values.", vbOKCancel, "Entry Error")
    txtbox1.Text = ""
End If
End Sub

可以这样操作,如图here

Private Sub TextBox1_Change()
    OnlyNumbers
End Sub

Private Sub OnlyNumbers()

    If TypeName(Me.ActiveControl) = "TextBox" Then

        With Me.ActiveControl

            If Not IsNumeric(.Value) And .Value <> vbNullString Then

                MsgBox "Sorry, only numbers allowed"

                .Value = vbNullString

            End If
        End With
    End If
End Sub

你可以在最开始加入这一行

sub txtbox1_Change()
    If txtbox1.Text = "" Or txtbox1.Text = "-" Then Exit Sub  '<~~~

或者,我发现这个更短更有趣:

Private Sub txtbox1_Change()
    If Not IsNumeric(txtbox1.Text & "0") Then
       disp = MsgBox("Please only enter numeric values.", vbOKCancel, "Entry Error")
       txtbox1.Text = ""
    End If
End Sub

有趣的是,它接受输入诸如“.2”、“-3.2”以及 “5e3” 之类的内容,最后一种情况是不允许的其他方法!

将它变成一个 while 循环可以只删除最后一个错误输入的字符:

Private Sub txtbox1_Change()
    t = txtbox1.Text
    Do While t <> "" And Not IsNumeric(t) And Not IsNumeric(t & "0")
       t = Mid(t, 1, Len(t) - 1)
    Loop
    txtbox1.Text = t
End Sub

声明一个全局布尔值,并在每个子函数的开头添加一个 if 语句,如果布尔值为真,则退出子函数。当您收到错误消息时,将该值设置为 true,就不会发生任何事情。然后再次设置为false。

Dim ufEventsDisabled As Boolean

Private Sub txtbox1_Change()
  'repeat the following line everywhere that you don't want to update
  if ufeventsdisabled then exit sub
  txt = userform.txtbox1.Value
  If Not IsNumeric(txt) Then
    disp = MsgBox("Please only enter numeric values.", vbOKCancel, "Entry Error")
    ufeventsdisabled = true
    txtbox1.Text = ""
    ufeventsdisabled = false
  End If
End Sub

*感谢来自 mrexcel.com

的 mikerickson

您无法阻止 _Changed 事件的触发。我建议您在您的设计中备份几个步骤,并询问您是否可以完成工作而无需首先清除它。在 FoxPro 中,我们会将 'format' 设置为 9999.99,它会自动阻止用户输入字母字符,但我认为该特定字段是 FP 独有的。您可以挂钩 _Changed 事件并在那里执行您自己的验证。我建议不要过滤单个击键,而是在每次更改时验证整个值。

If Text1.Value <> str(val(Text1.Value)) Then
    Text1.Value = previousValue
EndIf

... 这将需要为先前的值保留一个备份变量,但我相信您可以解决这个问题。在某些边缘情况下,VB 的字符串数字转换函数可能不完全匹配,例如您提到的指数表示法,因此您可能需要比这更复杂的检查。无论如何,这将导致无法输入错误的值。它还提供了更好的用户体验,因为反馈更加直接和直观。您可能会注意到值在 _Changed 事件中发生了变化,这应该会在您的脑海中发出关于无限循环的膝跳红旗。如果您这样做,请确保您之前的值已经过验证,请记住初始值将是一个空字符串。因此,递归调用将跳过 If 块,从而终止循环。无论如何,您会考虑什么 "better" 可能会因您询问的对象而有所不同,但希望我已经给了您一些思考的余地。