查找 VBA 控件对象的部分或页面

Posted

技术标签:

【中文标题】查找 VBA 控件对象的部分或页面【英文标题】:Find the section or page of a VBA controls object 【发布时间】:2017-07-04 14:31:10 【问题描述】:

如何识别控件对象(例如 acTextBox)是否是 VBA 中页面集合的成员?

当一个控件对象有焦点时,会调用一个函数来根据所使用的键的类型将焦点移动到下一个 control.tabindex。我设法用 Sendkeys "TAB" 做到了这一点,但我想改变它,因为这种方法会不断地禁用键盘上的 NUMLOCK。

到目前为止,下面的函数可以工作,但该过程考虑了一个表单中的所有控件。它应该只考虑调用函数的同一部分或页面中的控件。为此,我需要知道活动控件是否位于页面和/或部分内,如果是,则此页面/部分的名称或索引。我找不到执行此操作的代码。

Public Function GotoNextTab()
    Dim ctlNext, ctlCurrent As Control
    Dim frmCurrent As Form
    Dim lngNextTab As Long
    Set frmCurrent = Screen.Activeform
    Set ctlCurrent = Forms(frmCurrent.Name).ActiveControl

    lngNextTab = Val(ctlCurrent.TabIndex) + 1

    Do Until lngNextTab = frmCurrent.Controls.Count
        For Each ctlNext In frmCurrent.Controls
            Select Case ctlNext.ControlType
                Case acCheckBox, _
                     acComboBox, _
                     acCommandButton, _
                     acListBox, _
                     acOptionButton, _
                     acSubform, _
                     acTabCtl, _
                     acTextBox, _
                     acToggleButton
                        If ctlNext.TabIndex = lngNextTab Then
                            If ctlNext.TabStop = True Then
                                'Make sure that the focus can be set here!
                                If ctlNext.Visible = True And ctlNext.Enabled = True Then
                                    ctlNext.SetFocus
                                    Exit Function
                                Else
                                    'Focus could not be moved, so increase lngNextTab
                                    lngNextTab = lngNextTab + 1
                                End If
                            Else
                                'This was the last tab, so exit
                                Exit Function
                            End If
                        End If
            End Select
        Next ctlNext
    Loop
End Function

【问题讨论】:

关于表单的pages collection是什么意思?你的意思是Access 2003 feature?如果您可以分享这个有趣表格的屏幕截图。这个函数在哪里被调用?什么触发事件(OnOpen、OnClick、AfterUpdate)? 我在 v2010 中工作,但是是的,这正是我的意思。这些控件位于选项卡控件对象的不同页面上。 tabindex 值的范围仅限于标签页中的控件数量(否则我只会简单地连续编号)。这就是为什么我想知道控件位于哪个页面( Pages(Index) )上, 【参考方案1】:

考虑使用TabControl.Pages() 集合来访问特定标签页上的控件。

下面是一个例子:首先找到活动控件的对应页面,循环遍历每个标签页中的所有控件;然后分配当前页面并循环遍历其所有控件。按名称检查是可靠的,因为表单上带有或不带有选项卡的每个控件都必须是唯一的。

...
Dim currpage As Page
Dim tabCtrl As Control
Dim pagename As String

' FIND CURRENT PAGE OF ACTIVE CONTROL
For Each currpage In Forms!myForm!TabCtl.Pages
    For Each tabctrl In currpage.Controls
       If tabctrl.Name = ctlCurrent.Name
           pagename = currpage.Name
       End If
    Next tabctrl     
Next currpage

If Len(pagename) > 0 Then
   ' ASSIGN CURRENT TAB PAGE
   Set currpage = Forms!myForm!mytabCtl.Pages(pagename)

   ' LOOP THROUGH ALL CONTROLS ON CURRENT PAGE  
   For Each tabctrl In currpage.Controls
       '...PROCESS EACH CTRL OF CURRENT TAB PAGE
   Next tabctrl      

   Set tabctrl = Nothing
   Set currpage = Nothing
End If

【讨论】:

【参考方案2】:

感谢您的回答,这帮助我朝着正确的方向前进。我发现 parent 属性总是指向上一级的控件(在本例中为 Page 对象)。当到达最后一个控件时,我仍然必须插入一个功能以返回父控件集合中的第一个可用控件。到目前为止它没有给出我想要的结果,所以我会坚持现在的程序。

Private Sub Form_Load()
    KeyPreview = True
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    Dim ctl As Control
    If KeyCode = vbKeyReturn Then
        'Disregard textboxes with multiple lines
        Set ctl = Me.ActiveControl
        If ctl.ControlType = acTextBox Then
            If ctl.EnterKeyBehavior Then
                Exit Sub
            End If
        End If
        GotoNextTab
    End If
End Sub

Public Function GotoNextTab()
' This function will move the focus to the next control if
' a) This control is a specified type
' b) The control is visible and enabled
' c) The control has a tabstop set to true
'
' If the controls are within a page (TabControl), the focus is cycled within the controls on that page.
' The function disregards sections as it is assumed that there is no need to cycle controls on a form header or footer
' The focus does not cycle within subforms.

On Error Resume Next

    Dim ctlNext as Control
    Dim ctlCurrent As Control
    Dim frmCurrent As Form
    Dim lngNextTab As Long
    Set frmCurrent = Screen.Activeform
    Set ctlCurrent = Forms(frmCurrent.Name).ActiveControl
    If ctlCurrent.Parent.ControlType = acOptionGroup Then
        Set ctlCurrent = ctlCurrent.Parent
    End If
    lngNextTab = ctlCurrent.TabIndex

    Do Until lngNextTab > ctlCurrent.Parent.Controls.Count
        lngNextTab = lngNextTab + 1
        For Each ctlNext In ctlCurrent.Parent.Controls
            Select Case ctlNext.ControlType
                Case acCheckBox, _
                    acComboBox, _
                    acCommandButton, _
                    acListBox, _
                    acSubform, _
                    acTabCtl, _
                    acTextBox, _
                    acToggleButton, _
                    acOptionGroup
                        If ctlNext.TabIndex = lngNextTab Then
                            'Make sure that the focus can be set here!
                            If ctlNext.TabStop = True And ctlNext.Visible = True And ctlNext.Enabled = True Then
                                ctlNext.SetFocus
                                Exit Function
                            Else
                                Exit For 'restart for/next and search the next value
                            End If
                        End If
            End Select
        Next ctlNext
    Loop
End Function

【讨论】:

以上是关于查找 VBA 控件对象的部分或页面的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 VBA 设置访问选项卡控件的页面名称

vba,设置,excel,wps ,页面设置

VBA(Visual Basic):ComboBox(表单控件) - 对象不支持此属性或方法

第 1 页之后的页面上未显示 VBA 报告标题(列名称)

查找页面中的所有 datetimepicker 控件

在具有母版页的页面上查找控件