如何通过MS Word中的宏设置制表符顺序?

时间:2018-06-20 03:59:19

标签: vba ms-word tab-ordering

我有一个带有ActiveX控件的MS Word表单(不是表单控件)。假设我有两个文本框和两个选项按钮,如下所示:

Name: [textBox1]
Address: [textBox2]
Gender: [opt1] Male [opt2] Female

现在,如果我想按Tab键排序,则必须添加以下宏:

Private Sub textBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Then
textBox2.Activate
End If
End Sub

Private Sub textBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Then
opt1.Activate
End If
End Sub

Private Sub opt1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Then
opt2.Activate
End If
End Sub

现在,在我的真实表单中,有20个文本框和12个选项按钮,因此为每个表单字段写下keydown事件非常无聊。我该如何编写一个宏,以便它首先在keydown上获取当前表单字段的名称(并将其验证为tab keydown),然后转到下一个表单字段?

为了制表符顺序,我将按时间顺序重命名所有表单域,例如field1,field2,field3 .........,等等,这样,随着代码的增加,代码可以将制表符移至下一个表单字段。

这是我在表单中使用的ActiveX工具的屏幕截图:

enter image description here

我也有cross-posted this topic到VbaExpress论坛。

1 个答案:

答案 0 :(得分:2)

与我上次回答相比,您不会比这个问题更快乐。

问题在于,按键或KeyDown仅由焦点位于ActiveX控件中的事实触发,并且将特定于该控件。因此,除了每个控件的KeyDown事件之外,您别无选择。您可以将事件中的代码保持最少,但是...

无法通过名称直接将文档表面上的控件标识为 string ThisDocument.ControlName是可能的,但是没有类似ThisDocument.Controls(“ ControlName”)的东西可以让您替换名称,也不允许您标识当前控件的名称。

有一种方法可以做到,但是令人费解。由于这些文本与文本一致(无文本换行),因此它们属于文档的InlineShapes集合。它们的编程接口只能通过InlineShape的OLEFormat.Object属性来解决。这意味着代码需要循环InlineShapes集合两次:一次标识按下键的ActiveX控件,一次标识下一个控件。

以下代码说明了原理。它所做的是

  • 可用于9个以上的控件-这需要代码从名称的右边检查数字中有多少个字符
  • 如果焦点位于最后一个控件,请返回第一个控件

请注意,可能 可以绕开每个控件的事件代码。它将涉及使用Windows API,这意味着它将在用户每次按下Tab键时触发 。但是我不知道当焦点位于控件内部时是否会捕获按键。而且,如果是这种情况,则每次都必须进行测试-并且仍然必须能够确定焦点所在的控件。

Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    GoToNextControl KeyCode, ThisDocument.TextBox1.Name
End Sub


Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    GoToNextControl KeyCode, ThisDocument.TextBox2.Name
End Sub

Sub GoToNextControl(KeyCode As MSForms.ReturnInteger, controlName As String)
    Dim ils As Word.InlineShape, ils2 As Word.InlineShape
    Dim c As MSForms.Control
    Dim baseName As String, nextName
    Dim nameCounter As Long
    baseName = Mid(controlName, 1, Len(controlName) - 1)
    nameCounter = Right(controlName, 1)

    If KeyCode = 9 Then
        For Each ils In ThisDocument.InlineShapes
            If ils.Type = wdInlineShapeOLEControlObject Then
                If ils.OLEFormat.Object.Name = controlName Then
                    nextName = baseName & nameCounter + 1
                    For Each ils2 In ThisDocument.InlineShapes
                       If ils2.Type = wdInlineShapeOLEControlObject Then
                           If ils2.OLEFormat.Object.Name = nextName Then
                                ils2.Select
                                Exit Sub
                            End If
                        End If
                    Next
                End If
            End If
        Next
    End If
End Sub

总而言之,坚持旧版表单字段或内容控件,或者将其移至UserForm,然后再写入文档,可能更有意义。