Excel VBA Textbox_Exit 事件处理程序
Excel VBA Textbox_Exit Event Handler
这里有一个路障。使用三个文本框的简单用户表单,一个用于用户 ID,两个用于使用手持扫描仪输入序列号。用户加载 excel 文件,userform.show 加载,用户输入 id 然后简单验证验证数字,然后将焦点设置在第一个文本框上,用户扫描条形码输入序列号,再次简单验证以确保数字和长度, 与上一个文本框相同,扫描序列号,验证第一个文本框条目是否与第二个文本框条目匹配。
手持扫描仪用于输入序列号和returns一个"return carriage"字符;例如序列号扫描后按下进入按钮。
使用 "return carriage" 触发 textbox_exit 事件处理程序。问题非常间歇但一致。我加载用户窗体,输入数据,记录完成后,数据传输到对象工作表。但是,在进行故障排除时,我首先打开工作簿和用户窗体,创建一些记录,保存并关闭。一切正常,数据被记录和归档。当我第二次加载工作簿、为一条记录输入数据、保存并开始第二条记录时,通常会出现问题。一旦将序列号输入到第一个文本框中,使用 "return carriage" 就不会触发退出事件。我可以手动将焦点转移到其他对象;例如diff 文本框,但整体运行不尽如人意
我尝试插入 application.eventhandler=true 命令、不同的事件处理程序以及大量代码更改;例如在 IF 语句结束时退出 sub,以使其工作。
我想我会联系社区以获得一些反馈。仅供参考,如果我使用 copy/paste 模拟手持扫描仪并输入密钥,问题仍然会出现。
下面第一个串行文本框的退出事件处理程序示例。
Private Sub SerialIn_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Cancel = False
If Not IsNumeric(SerialIn.Value) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
MsgBox Msg, vbCritical, "Warning" 'display msg
Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Exit Sub
Else
If Not Len(SerialIn.Value) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
MsgBox Msg, vbCritical, "Warning"
Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Exit Sub
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
Me.SerialOut.SetFocus
Exit Sub
End If
结束如果
结束子
新代码:
Private Sub SerialIn_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Cancel = ValidateSerialIn(SerialIn)
End Sub
Function ValidateSerialIn(ByVal TextBox As Object) As Boolean
If Not IsNumeric(SerialIn.Value) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning" 'display msg
SerialIn.SetFocus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
ValidateSerialIn = True
Else
If Not Len(SerialIn.Value) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning"
'Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
ValidateSerialIn = True
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
ValidateSerialIn = False
End If
End If
End Function
第三次使用 Tim 的 TextBox_Change 解决方案:
Private Sub SerialIn_Change()
Dim v
v = ScannedValue1(SerialIn.Text)
If Len(v) > 0 Then
If Not IsNumeric(v) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning" 'display msg
SerialIn.Text = vbNullString
Else
If Not Len(v) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning"
SerialIn.Text = vbNullString
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
SerialOut.SetFocus
End If
End If
End If
End Sub
'check if a value ends with vbcrlf or vblf
' - if yes strip that off and return the rest
' - otherwise returns empty string
Function ScannedValue1(vIn) As String
Dim rv As String
If Right(vIn, 2) = vbCrLf Then
ScannedValue1 = Replace(vIn, vbCrLf, "")
ElseIf Right(vIn, 1) = vbLf Then
ScannedValue1 = Replace(vIn, vbLf, "")
End If
End Function
Exit
活动的意义远不止于此。在大多数表单中,用户在文本框中输入一个值,然后单击命令按钮 "OK"。 Tbx.Exit 事件发生。如果您单击其他任何地方(例如关闭表单的按钮),也会发生这种情况。在您的系统中,CR 也会触发事件,这似乎是问题所在。
当在您的 Tbx 中输入 CR 或 TAB 时,表单的点击顺序将接管。退出发生,然后是您点击顺序中下一个控件的输入事件。 (将其与用户确定下一个控件时发生的手动焦点更改进行比较。)
因此,解决方案应该不是使用 Exit 事件,而是让 CR 发起焦点更改,使用点击顺序设置,将焦点放在 "OK" 按钮上,然后让按钮的 Enter 事件触发其 Click 事件(如果默认情况下不这样做)。
您可能想要一个循环,其中 CR 触发工作表条目并且焦点返回到 Tbx。这是不使用 Exit 事件的另一个原因,因为您不希望在退出 Tbx 以关闭表单时在工作表中创建条目。
但是,您的表单可能没有或不需要 "OK" 按钮。在那种情况下,我会推荐 Tbx 的 BeforeUpdate
事件。 Exit
和 BeforeUpdate
紧接着出现。然而顺序并不重要(虽然这不是我忘记它的原因:-))但它们的性质。在表单控件、设置焦点或响应焦点更改的上下文中使用退出事件。 BeforeUpdate
明显是指数据。这些事件中的每一个都针对自己的任务进行了微调,因此比另一个更好。
如果你想检测来自扫描仪的 "Enter" 然后使用 Change
事件来检查文本框值是否以 vbCrLf
或 vbLf
结尾(在那order): 如果是,则触发 "scan" 动作。
请注意,您需要将文本框设置为 "multiline=true" 和 "EnterKeyBehaviour = true",以便 Change 事件捕获回车键。
Private Sub TextBox1_Change()
Dim v
v = ScannedValue(TextBox1.Text)
If Len(v) > 0 Then
TriggerScanAction v
TextBox1.Value = ""
End If
End Sub
'check if a value ends with vbcrlf or vblf
' - if yes strip that off and return the rest
' - otherwise returns empty string
Function ScannedValue(vIn) As String
Dim rv As String
If Right(vIn, 2) = vbCrLf Then
ScannedValue = Replace(vIn, vbCrLf, "")
ElseIf Right(vIn, 1) = vbLf Then
ScannedValue = Replace(vIn, vbLf, "")
End If
End Function
'execute some action triggered by a scanned value
Sub TriggerScanAction(v)
MsgBox "You scanned " & v
End Sub
这里有一个路障。使用三个文本框的简单用户表单,一个用于用户 ID,两个用于使用手持扫描仪输入序列号。用户加载 excel 文件,userform.show 加载,用户输入 id 然后简单验证验证数字,然后将焦点设置在第一个文本框上,用户扫描条形码输入序列号,再次简单验证以确保数字和长度, 与上一个文本框相同,扫描序列号,验证第一个文本框条目是否与第二个文本框条目匹配。
手持扫描仪用于输入序列号和returns一个"return carriage"字符;例如序列号扫描后按下进入按钮。
使用 "return carriage" 触发 textbox_exit 事件处理程序。问题非常间歇但一致。我加载用户窗体,输入数据,记录完成后,数据传输到对象工作表。但是,在进行故障排除时,我首先打开工作簿和用户窗体,创建一些记录,保存并关闭。一切正常,数据被记录和归档。当我第二次加载工作簿、为一条记录输入数据、保存并开始第二条记录时,通常会出现问题。一旦将序列号输入到第一个文本框中,使用 "return carriage" 就不会触发退出事件。我可以手动将焦点转移到其他对象;例如diff 文本框,但整体运行不尽如人意
我尝试插入 application.eventhandler=true 命令、不同的事件处理程序以及大量代码更改;例如在 IF 语句结束时退出 sub,以使其工作。
我想我会联系社区以获得一些反馈。仅供参考,如果我使用 copy/paste 模拟手持扫描仪并输入密钥,问题仍然会出现。
下面第一个串行文本框的退出事件处理程序示例。
Private Sub SerialIn_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Cancel = False
If Not IsNumeric(SerialIn.Value) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
MsgBox Msg, vbCritical, "Warning" 'display msg
Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Exit Sub
Else
If Not Len(SerialIn.Value) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
MsgBox Msg, vbCritical, "Warning"
Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Exit Sub
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
Me.SerialOut.SetFocus
Exit Sub
End If
结束如果 结束子
新代码:
Private Sub SerialIn_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Cancel = ValidateSerialIn(SerialIn)
End Sub
Function ValidateSerialIn(ByVal TextBox As Object) As Boolean
If Not IsNumeric(SerialIn.Value) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning" 'display msg
SerialIn.SetFocus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
ValidateSerialIn = True
Else
If Not Len(SerialIn.Value) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning"
'Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
ValidateSerialIn = True
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
ValidateSerialIn = False
End If
End If
End Function
第三次使用 Tim 的 TextBox_Change 解决方案:
Private Sub SerialIn_Change()
Dim v
v = ScannedValue1(SerialIn.Text)
If Len(v) > 0 Then
If Not IsNumeric(v) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning" 'display msg
SerialIn.Text = vbNullString
Else
If Not Len(v) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning"
SerialIn.Text = vbNullString
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
SerialOut.SetFocus
End If
End If
End If
End Sub
'check if a value ends with vbcrlf or vblf
' - if yes strip that off and return the rest
' - otherwise returns empty string
Function ScannedValue1(vIn) As String
Dim rv As String
If Right(vIn, 2) = vbCrLf Then
ScannedValue1 = Replace(vIn, vbCrLf, "")
ElseIf Right(vIn, 1) = vbLf Then
ScannedValue1 = Replace(vIn, vbLf, "")
End If
End Function
Exit
活动的意义远不止于此。在大多数表单中,用户在文本框中输入一个值,然后单击命令按钮 "OK"。 Tbx.Exit 事件发生。如果您单击其他任何地方(例如关闭表单的按钮),也会发生这种情况。在您的系统中,CR 也会触发事件,这似乎是问题所在。
当在您的 Tbx 中输入 CR 或 TAB 时,表单的点击顺序将接管。退出发生,然后是您点击顺序中下一个控件的输入事件。 (将其与用户确定下一个控件时发生的手动焦点更改进行比较。)
因此,解决方案应该不是使用 Exit 事件,而是让 CR 发起焦点更改,使用点击顺序设置,将焦点放在 "OK" 按钮上,然后让按钮的 Enter 事件触发其 Click 事件(如果默认情况下不这样做)。
您可能想要一个循环,其中 CR 触发工作表条目并且焦点返回到 Tbx。这是不使用 Exit 事件的另一个原因,因为您不希望在退出 Tbx 以关闭表单时在工作表中创建条目。
但是,您的表单可能没有或不需要 "OK" 按钮。在那种情况下,我会推荐 Tbx 的 BeforeUpdate
事件。 Exit
和 BeforeUpdate
紧接着出现。然而顺序并不重要(虽然这不是我忘记它的原因:-))但它们的性质。在表单控件、设置焦点或响应焦点更改的上下文中使用退出事件。 BeforeUpdate
明显是指数据。这些事件中的每一个都针对自己的任务进行了微调,因此比另一个更好。
如果你想检测来自扫描仪的 "Enter" 然后使用 Change
事件来检查文本框值是否以 vbCrLf
或 vbLf
结尾(在那order): 如果是,则触发 "scan" 动作。
请注意,您需要将文本框设置为 "multiline=true" 和 "EnterKeyBehaviour = true",以便 Change 事件捕获回车键。
Private Sub TextBox1_Change()
Dim v
v = ScannedValue(TextBox1.Text)
If Len(v) > 0 Then
TriggerScanAction v
TextBox1.Value = ""
End If
End Sub
'check if a value ends with vbcrlf or vblf
' - if yes strip that off and return the rest
' - otherwise returns empty string
Function ScannedValue(vIn) As String
Dim rv As String
If Right(vIn, 2) = vbCrLf Then
ScannedValue = Replace(vIn, vbCrLf, "")
ElseIf Right(vIn, 1) = vbLf Then
ScannedValue = Replace(vIn, vbLf, "")
End If
End Function
'execute some action triggered by a scanned value
Sub TriggerScanAction(v)
MsgBox "You scanned " & v
End Sub