Access – VBA – Set Focus On Specific Document Tab

I was trying to help out in a UA thread:

 

The Question?

The question was:

How can one switch to a specific tab, when using Tab Documents?

Microsoft Access - Document Tabs

My Original Answer

One way, that I learnt a long time ago by mistake, was that you can simply try to open the object again.  If it is already open, Access simply switches to the existing instance.

Thus, you can simply use the DoCmd.Open….

So for a Form, you could do:

DoCmd.OpenForm "YourFormName"

Or, for a report:

DoCmd.OpenReport "YourReportName"

An Alternate Approach

I thought I’d quickly share another possible way to handle this using UIAutomationClient.  You could use a function such as:

'---------------------------------------------------------------------------------------
' Procedure : MDIClient_SwitchObject
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Change Document Tabs, object focus
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: UIAutomationClient
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sObjectName   : Name/Caption of the object to set the focus on
' sClass        : Class of the object to set the focus on
'                   OTable = Table, OQry = Query, OForm = Form
'                   OSplitView = Split Form, OReport = Report, OScript = Macro
'
' Output
' ~~~~~~
' Boolean -> True  = operation was successful
'            False = operation failed
'
' Usage:
' ~~~~~~
' Call MDIClient_SwitchObject("ProjectCategories", "OTable") 'Table
' Call MDIClient_SwitchObject("Past Due Invoices", "OQry") 'Query
' Call MDIClient_SwitchObject("Contacts", "OForm") 'Normal Forms
' Call MDIClient_SwitchObject("OrderDetails", "OSplitView") 'Split Forms
' Call MDIClient_SwitchObject("Accounts Accruable", "OReport") 'Report
' Call MDIClient_SwitchObject("AutoExec", "OScript") 'Macro
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2022-07-07              Initial Release
' 2         2022-07-11              Added OSplitView for Split Form per AHeyne's comment
'---------------------------------------------------------------------------------------
Public Function MDIClient_SwitchObject(sObjectName As String, sClass As String) As Boolean
    On Error GoTo Error_Handler
    Dim oUIA                  As UIAutomationClient.CUIAutomation
    Dim oAccess               As UIAutomationClient.IUIAutomationElement
    Dim oCondition            As UIAutomationClient.IUIAutomationCondition
    Dim oObject               As UIAutomationClient.IUIAutomationElement

    Set oUIA = New CUIAutomation
    Set oAccess = oUIA.ElementFromHandle(ByVal Application.hWndAccessApp)

    If Not (oAccess Is Nothing) Then
        Set oCondition = oUIA.CreateAndCondition(oUIA.CreatePropertyCondition(UIA_NamePropertyId, sObjectName), _
                                                 oUIA.CreatePropertyCondition(UIA_ClassNamePropertyId, sClass))
        Set oObject = oAccess.FindFirst(TreeScope_Subtree, oCondition)
        If Not (oObject Is Nothing) Then
            oObject.SetFocus
            MDIClient_SwitchObject = True
        Else
            Debug.Print "'" & sObjectName & "' not found."
        End If
    Else
        Debug.Print "Can't locate the database windows."
    End If

Error_Handler_Exit:
    On Error Resume Next
    If Not oObject Is Nothing Then Set oObject = Nothing
    If Not oCondition Is Nothing Then Set oCondition = Nothing
    If Not oAccess Is Nothing Then Set oAccess = Nothing
    If Not oUIA Is Nothing Then Set oUIA = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: MDIClient_SwitchObject" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occured!"
    Resume Error_Handler_Exit
End Function

The above actually works for both Overlapping Windows and Tabbed Documents alike.

10 responses on “Access – VBA – Set Focus On Specific Document Tab

  1. AHeyne

    I tried this some time ago too, but I remember there was trouble with SplitForms somehow. You should check that. 😉

    1. Daniel Pineault Post author

      It isn’t for Split Forms, it’s for Access Document Tabs, but the same principle could be employed with Split Forms, just need to adjust the class.

      1. AHeyne

        Thats correct, and also what I meant. If one of the forms already open in the Access Document Tabs is a SplitForm then there was an issue…

      2. AHeyne

        I did a little digging in the code and can now say that the problem was that a SplitForm is not the class ‘OForm’, but ‘OSplitView’. 😉

  2. Klaus Oberdalhoff

    Hi,
    i found long time ago, that you only can reliably focus on tabs, if you set focus first on the MAIN form where the tab is in and then setfocus a second time (or more often times if deeper). So i usually have no setfocus problems any longer since i do it that way. So: Always first focus on main form, then on each subform …
    mfg Klaus

  3. AHeyne

    I’ve been trying to give the UIAutomationClient approach another chance in my application, but I’ve stumbled over another rock:
    If Application.Echo is set to false, it is not working at all.

    See this sample which doesn’t work:

    Application.Echo False
    MDIClient_SwitchObject “MyForm”, “OForm”
    Application.Echo True

    1. Daniel Pineault Post author

      That’s an interesting issue, I will have to test, but if that’s the case we simply need to enable Echo prior to running. Not a big deal.

      I will try to look into this further.

      1. AHeyne

        Sure, you can enable echo beforehand and disable it afterwards. But the point of why I use Echo is to avoid screen flickering during form operations. This could interfere with it…