用户窗体文本框中的箭头键,VBA
Arrow key in a textbox of a userform, VBA
我正在处理一个包含多个文本框的用户表单,这些文本框的排列就像 excel 图表一样。
我已经设置了 TabIndexes,它们与 TAB/shift+TAB 完美配合。然而,按下箭头键的反应并不是我所期望的。
我这样命名这些文本框:
boxA1 boxB1 boxC1 boxD1
boxA2 boxB2 boxC2 boxD2 ...
boxA3 boxB3 boxC3 boxD3
:
:
假设焦点在boxB1。当按下箭头键时,我希望焦点转到 boxB2,但它会转到 boxA3 什么的。
我试过这个代码:
Private Sub boxB1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case vbKeyDown
boxB2.SetFocus
Case vbKeyUp
boxA10.SetFocus
End Select
End Sub
它工作正常,但是,如果我的表单中只有几个文本框,这是一个很好且清晰的解决方案。但是我的表单中大约有 70 个文本框,这会使我的代码变大并且真正重复。
我可以调整任何参数以使其正确吗?
或者有什么我可以使用的功能,如下所示?只是 sudo,你知道的。
Private Sub name_i_KeyDown(ByVal KeyCode as MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case vbKeyDown
Controls("name_" & i+1).SetFocus
Case vbKeyUp
Controls("name_" & i-1).SetFocus
End Select
End Sub
谢谢!
你走在正确的道路上。在您的表单模块中添加以下两个 UDF:
Sub SetTextBoxFocus(ByVal KeyCode As MSForms.ReturnInteger)
Dim sPrevControl As String
Dim sNextControl As String
Dim sBoxToSet As String
Dim oC As Control
' Cater for TAB key press. Setting it so that it behaves like vbKeyDown. Remove this If condition if not required
If Asc(KeyCode) = 57 Then
KeyCode = vbKeyDown
End If
' We only want to check if pressed key was either vbKeyDown or vbKeyUp and the key was pressed on a TextBox
If TypeName(Me.ActiveControl) = "TextBox" And (KeyCode = vbKeyDown Or KeyCode = vbKeyUp) Then
With Me.ActiveControl
' Lets set both previous and next text box names
If InStr(1, .Name, "boxD") > 0 Then
sPrevControl = "boxC" & GetNumFromString(.Name)
sNextControl = "boxA" & GetNumFromString(.Name) + 1
ElseIf InStr(1, .Name, "boxA") > 0 Then
sPrevControl = "boxD" & GetNumFromString(.Name) - 1
sNextControl = "boxB" & GetNumFromString(.Name)
Else
sPrevControl = "box" & Chr(Asc(Mid(.Name, 4, 1)) - 1) & GetNumFromString(.Name)
sNextControl = "box" & Chr(Asc(Mid(.Name, 4, 1)) + 1) & GetNumFromString(.Name)
End If
' Bases on which key was pressed, lets set the name of the text box to move to
Select Case KeyCode
Case vbKeyDown: sBoxToSet = sNextControl
Case Else: sBoxToSet = sPrevControl
End Select
' Loop through all controls in the form and set the focus to the control if found
For Each oC In Me.Controls
If oC.Name = sBoxToSet Then
oC.SetFocus
Exit For
End If
Next
End With
End If
End Sub
Function GetNumFromString(ByVal txt As String) As String
Dim oRe As New RegExp
With oRe
.pattern = "\d"
If .Test(txt) Then GetNumFromString = .Execute(txt)(0)
End With
End Function
现在,在每个 TextBox 的 KeyDown 中,进行以下调用:SetTextBoxFocus KeyCode
。这应该可以解决问题
注意: 我将 boxD
作为最后一个文本框。您应该将其更改为同一行中的最后一个文本框
我正在处理一个包含多个文本框的用户表单,这些文本框的排列就像 excel 图表一样。 我已经设置了 TabIndexes,它们与 TAB/shift+TAB 完美配合。然而,按下箭头键的反应并不是我所期望的。 我这样命名这些文本框:
boxA1 boxB1 boxC1 boxD1
boxA2 boxB2 boxC2 boxD2 ...
boxA3 boxB3 boxC3 boxD3
:
:
假设焦点在boxB1。当按下箭头键时,我希望焦点转到 boxB2,但它会转到 boxA3 什么的。
我试过这个代码:
Private Sub boxB1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case vbKeyDown
boxB2.SetFocus
Case vbKeyUp
boxA10.SetFocus
End Select
End Sub
它工作正常,但是,如果我的表单中只有几个文本框,这是一个很好且清晰的解决方案。但是我的表单中大约有 70 个文本框,这会使我的代码变大并且真正重复。 我可以调整任何参数以使其正确吗? 或者有什么我可以使用的功能,如下所示?只是 sudo,你知道的。
Private Sub name_i_KeyDown(ByVal KeyCode as MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case vbKeyDown
Controls("name_" & i+1).SetFocus
Case vbKeyUp
Controls("name_" & i-1).SetFocus
End Select
End Sub
谢谢!
你走在正确的道路上。在您的表单模块中添加以下两个 UDF:
Sub SetTextBoxFocus(ByVal KeyCode As MSForms.ReturnInteger)
Dim sPrevControl As String
Dim sNextControl As String
Dim sBoxToSet As String
Dim oC As Control
' Cater for TAB key press. Setting it so that it behaves like vbKeyDown. Remove this If condition if not required
If Asc(KeyCode) = 57 Then
KeyCode = vbKeyDown
End If
' We only want to check if pressed key was either vbKeyDown or vbKeyUp and the key was pressed on a TextBox
If TypeName(Me.ActiveControl) = "TextBox" And (KeyCode = vbKeyDown Or KeyCode = vbKeyUp) Then
With Me.ActiveControl
' Lets set both previous and next text box names
If InStr(1, .Name, "boxD") > 0 Then
sPrevControl = "boxC" & GetNumFromString(.Name)
sNextControl = "boxA" & GetNumFromString(.Name) + 1
ElseIf InStr(1, .Name, "boxA") > 0 Then
sPrevControl = "boxD" & GetNumFromString(.Name) - 1
sNextControl = "boxB" & GetNumFromString(.Name)
Else
sPrevControl = "box" & Chr(Asc(Mid(.Name, 4, 1)) - 1) & GetNumFromString(.Name)
sNextControl = "box" & Chr(Asc(Mid(.Name, 4, 1)) + 1) & GetNumFromString(.Name)
End If
' Bases on which key was pressed, lets set the name of the text box to move to
Select Case KeyCode
Case vbKeyDown: sBoxToSet = sNextControl
Case Else: sBoxToSet = sPrevControl
End Select
' Loop through all controls in the form and set the focus to the control if found
For Each oC In Me.Controls
If oC.Name = sBoxToSet Then
oC.SetFocus
Exit For
End If
Next
End With
End If
End Sub
Function GetNumFromString(ByVal txt As String) As String
Dim oRe As New RegExp
With oRe
.pattern = "\d"
If .Test(txt) Then GetNumFromString = .Execute(txt)(0)
End With
End Function
现在,在每个 TextBox 的 KeyDown 中,进行以下调用:SetTextBoxFocus KeyCode
。这应该可以解决问题
注意: 我将 boxD
作为最后一个文本框。您应该将其更改为同一行中的最后一个文本框