用户窗体文本框中的箭头键,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 作为最后一个文本框。您应该将其更改为同一行中的最后一个文本框