VBA – Find A Window By Its Title and Bring It To The Front

In my previous post:

I demonstrated a simple API that we can use to bring any window to the foreground to ensure our user see it.  This is great when automating external applications to make sure the automate app in visible to the user and not hidden underneath some other program window.

The problem being that the previous method relied on us having the window’s handle (Hwnd) for the window you wanted to bring to the front.  Now, for automating say Access, Excel, Word, … we can easily get the Hwnd to call the API, but there are many application where it isn’t as straightforward or even possible.  Microsoft simply hasn’t standardized this in any manner throughout its applications, and in some case didn’t make it possible at all. Think of PowerPoint for instance, where there is no application or presentation Hwnd property to use?!  This is where this article’s ‘more versatile’ approach comes in!


 
Let us explore a few different approaches:

Solution 1 – Using APIs

The first solution, I take no credit for whatsoever.  Many, many moons ago, when I originally had such a need, I came across the following:

I’ve simply adapted it for both 32-bit and 64-bit and converted it to my coding style.

#If VBA7 Then
    'Win32API_PtrSafe
    Private Declare PtrSafe Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
    Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long
    Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As LongPtr) As Long
    Private Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
#Else
    Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
    Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
#End If

Private Type FindWindowTitleParameters
    #If VBA7 Then
        lHwnd                     As LongPtr
    #Else
        lHwnd                     As Long
    #End If
    sFullTitle                As String
    sSearchTitle              As String
End Type

#If VBA7 Then
Public Function FindWindowByTitle(sFindWindowTitle As String, Optional bSetFocus As Boolean = True) As LongPtr
#Else
Public Function FindWindowByTitle(sFindWindowTitle As String, Optional bSetFocus As Boolean = True) As Long
#End If
    'Usage Examples:
    '    FindWindowByTitle "returning*"
    '    FindWindowByTitle "*parent*"
    '    FindWindowByTitle "*Excel"
    '    FindWindowByTitle "Inbox*"
    '    FindWindowByTitle "Document1 - Word"
    '    FindWindowByTitle "Book1 - Excel"
    Dim SearchParameters          As FindWindowTitleParameters
    
    SearchParameters.sSearchTitle = sFindWindowTitle
    Call EnumWindows(AddressOf EnumWindowProc, VarPtr(SearchParameters))
    
    FindWindowByTitle = SearchParameters.lHwnd
    If FindWindowByTitle <> 0 And bSetFocus = True Then
        '        Debug.Print FindWindowByTitle, SearchParameters.sFullTitle
        Call SetForegroundWindow(FindWindowByTitle)
    End If
End Function

#If VBA7 Then
Private Function EnumWindowProc(ByVal lHwnd As LongPtr, _
                                SearchParameters As FindWindowTitleParameters) As Long
#Else
Private Function EnumWindowProc(ByVal lHwnd As Long, _
                                SearchParameters As FindWindowTitleParameters) As Long
#End If
    Dim sWindowTitle          As String
    Dim lRetVal               As Long

    sWindowTitle = Space(GetWindowTextLength(lHwnd) + 1)
    lRetVal = GetWindowText(lHwnd, sWindowTitle, Len(sWindowTitle))
    sWindowTitle = TrimNull(sWindowTitle)

    If InStr(SearchParameters.sSearchTitle, "*") = 0 Then
        'Exact Macth Search
        If sWindowTitle = SearchParameters.sSearchTitle Then
            SearchParameters.lHwnd = lHwnd
            SearchParameters.sFullTitle = sWindowTitle
            EnumWindowProc = 0
        Else
            EnumWindowProc = 1
        End If
    Else
        'Wildcard Search
        If sWindowTitle Like SearchParameters.sSearchTitle Then
            SearchParameters.lHwnd = lHwnd
            SearchParameters.sFullTitle = sWindowTitle
            EnumWindowProc = 0
        Else
            EnumWindowProc = 1
        End If
    End If

End Function

Public Function TrimNull(ByVal sInput As String)
    Dim lPos                  As Long

    lPos = InStr(sInput, Chr(0))
    If lPos Then
        TrimNull = Left(sInput, lPos - 1)
    Else
        TrimNull = sInput
    End If
End Function

Usage Example(s)

PowerPoint is an excellent candidate for such an approach as I couldn’t find an easy way to determine its Hwnd to use the SetForegroundWindow API. Thus, we could do something like the following to ensure it is visible when we automate it.

PowerPoint

Function LaunchPowerPoint()
    Dim oPPT                  As Object
    Dim oPPTPres              As Object
    Dim bPPTOpened            As Boolean
    Dim lRetVal               As Long
    #If VBA7 Then
        Dim lPPTHwnd          As LongPtr
    #Else
        Dim lPPTHwnd          As Long
    #End If

    'Start PowerPoint
    On Error Resume Next
    Set oPPT = GetObject("PowerPoint.Application")
    If Err.Number <> 0 Then
        Err.Clear
        On Error GoTo Error_Handler
        Set oPPT = CreateObject("PowerPoint.Application")
        bPPTOpened = False
    Else    'PowerPoint was already running
        bPPTOpened = True
    End If
    On Error GoTo Error_Handler

    oPPT.Visible = True
    Set oPPTPres = oPPT.Presentations.Add

    'Bring to the Front Using FindWindowByTitle APIs and retrieve the Hwnd for future use
    lPPTHwnd = FindWindowByTitle(oPPT.Caption & " - PowerPoint")
    If lPPTHwnd = 0 Then
        'Did not get the focus for some reason
    End If

Error_Handler_Exit:
    On Error Resume Next
    Set oPPTPres = Nothing
    Set oPPT = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: LaunchPowerPoint" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

 

Solution 2 – Using UIAutomation

Because of my recent UIAutomation work, I leanrt how easy it was to create a similar function.

Personally, I find this to be an easier approach, no APIs and bitness considerations, no messing with AddressOf, …

'---------------------------------------------------------------------------------------
' Procedure : UIA_FindWindowByTitle
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Find the Window with the specified Title/Caption and returns it's Windows
'               Handle (Hwnd) if found and 0 if not located.
'               Optionally can by the window to the Forefront to ensure it is visible
'               to the user.
'               Returns the Windows Handle (Hwnd) if found, 0 if not
' 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:
' ~~~~~~~~~~~~~~~~
' sFindWindowTitle : Title/Caption of the Window to locate
'                       Can include wildcards '*'.
'                       Make sure the term is unique enough to get the intended results!
'
' Usage:
' ~~~~~~
' Debug.Print UIA_FindWindowByTitle("Book1 - Excel")
'   Returns -> Hwnd of the found window
' Debug.Print UIA_FindWindowByTitle("Book1*")
'   Returns -> Hwnd of the found window
' Debug.Print UIA_FindWindowByTitle("*Access*")
'   Returns -> Hwnd of the found window
' Debug.Print UIA_FindWindowByTitle("Document*")
'   Returns -> Hwnd of the found window
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2022-10-30              Initial Release
'---------------------------------------------------------------------------------------
#If VBA7 Then
Public Function UIA_FindWindowByTitle(sFindWindowTitle As String, Optional bSetFocus As Boolean = True) As LongPtr
#Else
Public Function UIA_FindWindowByTitle(sFindWindowTitle As String, Optional bSetFocus As Boolean = True) As Long
#End If
On Error GoTo Error_Handler
    Dim oUIAutomation         As UIAutomationClient.CUIAutomation
    Dim oUIADesktop           As UIAutomationClient.IUIAutomationElement
    Dim oUIAElements          As UIAutomationClient.IUIAutomationElementArray
    Dim oUIAElement           As UIAutomationClient.IUIAutomationElement
    Dim i                     As Long

    Set oUIAutomation = New UIAutomationClient.CUIAutomation
    Set oUIADesktop = oUIAutomation.GetRootElement
    Set oUIAElements = oUIADesktop.FindAll(TreeScope_Children, oUIAutomation.CreateTrueCondition)

    For i = 0 To oUIAElements.Length - 1
        Set oUIAElement = oUIAElements.GetElement(i)
        '        Debug.Print i, oUIAElement.CurrentName, oUIAElement.CurrentClassName
        If InStr(sFindWindowTitle, "*") = 0 Then
            'Exact Macth Search
            If oUIAElement.CurrentName = sFindWindowTitle Then
                UIA_FindWindowByTitle = oUIAElement.GetCurrentPropertyValue(UIA_NativeWindowHandlePropertyId)
                If bSetFocus = True Then oUIAElement.SetFocus
                'Could also use the Windows SetForegroundWindow API
                'Call SetForegroundWindow(UIA_FindWindowByTitle)
            End If
        Else
            'Wildcard Search
            If oUIAElement.CurrentName Like sFindWindowTitle Then
                UIA_FindWindowByTitle = oUIAElement.GetCurrentPropertyValue(UIA_NativeWindowHandlePropertyId)
                If bSetFocus = True Then oUIAElement.SetFocus
                'Could also use the Windows SetForegroundWindow API
                'Call SetForegroundWindow(UIA_FindWindowByTitle)
            End If
        End If
    Next i

Error_Handler_Exit:
    On Error Resume Next
    Set oUIAElement = Nothing
    Set oUIAElements = Nothing
    Set oUIADesktop = Nothing
    Set oUIAutomation = Nothing
    Exit Function
 
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: UIA_FindWindowByTitle" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

The code is very straightforward, I simply iterate through the topmost windows examining if their CurrentName (caption/title) matches what I am searching for. When it finds a match we determine its Hwnd so we can pass it back for further use if required and set the focus on that windows. Easy!

It also doesn’t require any API (no 32/64-bit declaration juggling!), but does require having the UIAutomationClient reference library set.

The critical things here is to supply a unique search term. Searching for the term ‘*Word*’ is probably not the best approach in case multiple Word documents are open at the same time. Such a search could set the focus on any one of them. Searching for the ‘ActiveDocument.Name & “*”‘, on the other hand, should guarantee us that the proper window is brought to the front.

Usage Example(s)

PowerPoint

Function LaunchPowerPoint()
    Dim oPPT                  As Object
    Dim oPPTPres              As Object
    Dim bPPTOpened            As Boolean
    Dim lRetVal               As Long
    #If VBA7 Then
        Dim lPPTHwnd          As LongPtr
    #Else
        Dim lPPTHwnd          As Long
    #End If

    'Start PowerPoint
    On Error Resume Next
    Set oPPT = GetObject("PowerPoint.Application")
    If Err.Number <> 0 Then
        Err.Clear
        On Error GoTo Error_Handler
        Set oPPT = CreateObject("PowerPoint.Application")
        bPPTOpened = False
    Else    'PowerPoint was already running
        bPPTOpened = True
    End If
    On Error GoTo Error_Handler

    oPPT.Visible = True
    Set oPPTPres = oPPT.Presentations.Add
    
    'Bring to the Front Using UI Automation
    lPPTHwnd = UIA_FindWindowByTitle(oPPT.Caption & "*")
    If lPPTHwnd = 0 Then
        'Did not get the focus for some reason
    End If

Error_Handler_Exit:
    On Error Resume Next
    Set oPPTPres = Nothing
    Set oPPT = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: LaunchPowerPoint" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

Excel

Now, with Excel we can use the simple SetForegroundWindow API approach because it is easy to get its Hwnd, but I still thought I’d demonstrate how we could use the UIA_FindWindowByTitle function.

Public Sub LaunchExcel()
    '#Const EarlyBind = True 'Use Early Binding, Req. Reference Library
    #Const EarlyBind = False    'Use Late Binding
    #If EarlyBind = True Then
        'Early Binding Declarations
        Dim oExcel            As Excel.Application
        Dim oExcelWrkBk       As Excel.WorkBook
        Dim oExcelWrSht       As Excel.WorkSheet
    #Else
        'Late Binding Declaration/Constants
        Dim oExcel            As Object
        Dim oExcelWrkBk       As Object
        Dim oExcelWrSht       As Object
    #End If
    Dim bExcelOpened          As Boolean
    #If VBA7 Then
        Dim lExcelHwnd        As LongPtr
    #Else
        Dim lExcelHwnd        As Long
    #End If

    'Start Excel
    On Error Resume Next
    Set oExcel = GetObject(, "Excel.Application")    'Bind to existing instance of Excel
    If Err.Number <> 0 Then    'Could not get instance of Excel, so create a new one
        Err.Clear
        On Error GoTo Error_Handler
        Set oExcel = CreateObject("Excel.Application")
        bExcelOpened = False
    Else    'Excel was already running
        bExcelOpened = True
    End If
    On Error GoTo Error_Handler

    oExcel.ScreenUpdating = True
    oExcel.Visible = True   'Keep Excel hidden until we are done with our manipulation
    Set oExcelWrkBk = oExcel.Workbooks.Add()    'Start a new workbook
    Set oExcelWrSht = oExcelWrkBk.Sheets(1)

    'Bring to the Front Using UI Automation
    lExcelHwnd = UIA_FindWindowByTitle(oExcel.Caption)
    If lExcelHwnd = 0 Then
        'Did not get the focus for some reason
    End If

Error_Handler_Exit:
    On Error Resume Next
    Set oExcelWrSht = Nothing
    Set oExcelWrkBk = Nothing
    oExcel.ScreenUpdating = True
    Set oExcel = Nothing
    Exit Sub

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

Word

Similarly, in Word we would normally use the simple SetForegroundWindow API approach because it is easy to get its Hwnd, but once again I thought I’d demonstrate how we could use the UIA_FindWindowByTitle function for illustrative purposes.

Function LaunchWord()
    Dim oWord                 As Object
    Dim oWordDoc              As Object
    Dim bWordOpened           As Boolean
    #If VBA7 Then
        Dim lWordHwnd         As LongPtr
    #Else
        Dim lWordHwnd         As Long
    #End If
    '    Const wdOrientPortrait = 0
    Const wdOrientLandscape = 1

    'Start Word
    On Error Resume Next
    Set oWord = GetObject("Word.Application")    'Bind to existing instance of Word
    If Err.Number <> 0 Then    'Could not get instance of Word, so create a new one
        Err.Clear
        On Error GoTo Error_Handler
        Set oWord = CreateObject("Word.application")
        bWordOpened = False
    Else    'Word was already running
        bWordOpened = True
    End If
    On Error GoTo Error_Handler
    oWord.Visible = True   'Keep Word hidden until we are done with our manipulation
    Set oWordDoc = oWord.Documents.Add   'Start a new document
    oWordDoc.PageSetup.Orientation = wdOrientLandscape
    
    'Bring to the Front Using UI Automation
    lWordHwnd = UIA_FindWindowByTitle(oWord.ActiveDocument.Name & "*")
    If lWordHwnd = 0 Then
        'Did not get the focus for some reason
    End If

Error_Handler_Exit:
    On Error Resume Next
    Set oWordDoc = Nothing
    Set oWord = Nothing
    Exit Function

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

If ever there was any need, we could even take things further and add a Class comparison for the window

Excel      -> XLMAIN
Notepad    -> Notepad
Outlook    -> rctrl_renwnd32
PowerPoint -> PPTFrameClass
Word       -> OpusApp
...

But I’ve never had the need thus far.

Listing Windows During Development

I thought I’d also share a simple little Sub that lists the Desktop Child Windows, so basically the top most windows/applications information. This can be very useful during development and testing to find the proper Hwnd, Title, Classs, …

'---------------------------------------------------------------------------------------
' Procedure : EnumerateDesktopChildWindows
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Displays the listing of top most windows (Desktop child windows)
' 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
'
' Usage:
' ~~~~~~
' EnumerateDesktopChildWindows
'   Returns -> Outputs results to the VBE Immediate Window
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2022-10-31              Initial Public Release
'---------------------------------------------------------------------------------------
Public Sub EnumerateDesktopChildWindows()
On Error GoTo Error_Handler
    Dim oUIAutomation         As UIAutomationClient.CUIAutomation
    Dim oUIADesktop           As UIAutomationClient.IUIAutomationElement
    Dim oUIAElements          As UIAutomationClient.IUIAutomationElementArray
    Dim i                     As Long

    Set oUIAutomation = New UIAutomationClient.CUIAutomation
    Set oUIADesktop = oUIAutomation.GetRootElement
    Set oUIAElements = oUIADesktop.FindAll(TreeScope_Children, oUIAutomation.CreateTrueCondition)
    Debug.Print oUIAElements.Length & " Windows Found"
    Debug.Print String(80, "-")
    For i = 0 To oUIAElements.Length - 1
        With oUIAElements.GetElement(i)
            Debug.Print i + 1, .GetCurrentPropertyValue(UIA_NativeWindowHandlePropertyId), .CurrentName, .CurrentClassName
        End With
    Next i

Error_Handler_Exit:
    On Error Resume Next
    Set oUIAElements = Nothing
    Set oUIADesktop = Nothing
    Set oUIAutomation = Nothing
    Exit Sub

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

 

Solution 3 – Using AppActivate

Another simpler approach is to use the AppActivate statement, you can look over the help file at:

This is pure simplisity to use and the only downside is that you don’t get the HWND of the window should you wish to do any further automation, but that is normally not a big deal and can easily be retrieved by other means.

With the AppActivate, depending on your method of dealing with errors, you may wish to trap Error 5 – Invalid procedure call or argument which occurs when it cannot find the specified window.

Also note that AppActivate tries to find an exact match and when it can’t, it performs a Like ‘SuppliedTitle*’ search. Thus, it is important to provide a unique title to bind to or it could bring the wrong window to the forefront.

To explicitly call it we would do:

Call VBA.AppActivate("Some Window Title")

Or

Call VBA.Interaction.AppActivate("Some Window Title")

but we aren’t required to include the library and class, and thus we can simplify it to simply:

Call AppActivate("Some Window Title")

Since it is a VBA command, this means it is available throughout VBA programs (Access, Excel, Outlook, PowerPoint, Word, …). I also know it has been around since at least Office 2003, but probably even earlier than that, so no worries about versioning issues here.

Usage Example(s)

Excel

For Excel, we simply need to pass the caption to the AppActivate statement, by doing something like:

Public Sub LaunchExcel()
    '#Const EarlyBind = True 'Use Early Binding, Req. Reference Library
    #Const EarlyBind = False    'Use Late Binding
    #If EarlyBind = True Then
        'Early Binding Declarations
        Dim oExcel            As Excel.Application
        Dim oExcelWrkBk       As Excel.Workbook
        Dim oExcelWrSht       As Excel.Worksheet
    #Else
        'Late Binding Declaration/Constants
        Dim oExcel            As Object
        Dim oExcelWrkBk       As Object
        Dim oExcelWrSht       As Object
    #End If
    Dim bExcelOpened          As Boolean

    'Start Excel
    On Error Resume Next
    Set oExcel = GetObject(, "Excel.Application")    'Bind to existing instance of Excel
    If Err.Number <> 0 Then    'Could not get instance of Excel, so create a new one
        Err.Clear
        On Error GoTo Error_Handler
        Set oExcel = CreateObject("Excel.Application")
        bExcelOpened = False
    Else    'Excel was already running
        bExcelOpened = True
    End If
    On Error GoTo Error_Handler

    oExcel.ScreenUpdating = True
    oExcel.Visible = True   'Keep Excel hidden until we are done with our manipulation
    Set oExcelWrkBk = oExcel.Workbooks.Add()    'Start a new workbook
    Set oExcelWrSht = oExcelWrkBk.Sheets(1)

    'Bring it to the Front
    Call AppActivate(oExcel.Caption)

Error_Handler_Exit:
    On Error Resume Next
    Set oExcelWrSht = Nothing
    Set oExcelWrkBk = Nothing
    oExcel.ScreenUpdating = True
    Set oExcel = Nothing
    Exit Sub

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

Outlook

For Outlook, in the case of an e-mail, we use the subject to bring it to the forefornt.

So if we were using my SendHTMLEmail function it becomes as simple as:

'Generate the e-mail
Call SendHTMLEmail("someone@somewhere.com", "Test E-mail", "Hello World From Microsoft Access", True)
'Bring it to the Front
Call AppActivate("Test E-mail")

PowerPoint

Similarily to Excel, with PowerPoint we use the Caption as well, giving us something like:

Function LaunchPowerPoint()
    Dim oPPT                  As Object
    Dim oPPTPres              As Object
    Dim bPPTOpened            As Boolean

    'Start PowerPoint
    On Error Resume Next
    Set oPPT = GetObject("PowerPoint.Application")
    If Err.Number <> 0 Then
        Err.Clear
        On Error GoTo Error_Handler
        Set oPPT = CreateObject("PowerPoint.Application")
        bPPTOpened = False
    Else    'PowerPoint was already running
        bPPTOpened = True
    End If
    On Error GoTo Error_Handler

    oPPT.Visible = True
    Set oPPTPres = oPPT.Presentations.Add
    
    'Bring it to the Front
    Call AppActivate(oPPT.Caption)

Error_Handler_Exit:
    On Error Resume Next
    Set oPPTPres = Nothing
    Set oPPT = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: LaunchPowerPoint" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

Word

With Word, we need only pass the document name to the AppActivate statement, something along the lines of:

Function LaunchWord()
    Dim oWord                 As Object
    Dim oWordDoc              As Object
    Dim bWordOpened           As Boolean
    '    Const wdOrientPortrait = 0
    Const wdOrientLandscape = 1

    'Start Word
    On Error Resume Next
    Set oWord = GetObject("Word.Application")    'Bind to existing instance of Word
    If Err.Number <> 0 Then    'Could not get instance of Word, so create a new one
        Err.Clear
        On Error GoTo Error_Handler
        Set oWord = CreateObject("Word.application")
        bWordOpened = False
    Else    'Word was already running
        bWordOpened = True
    End If
    On Error GoTo Error_Handler
    oWord.Visible = True   'Keep Word hidden until we are done with our manipulation
    Set oWordDoc = oWord.Documents.Add   'Start a new document
    oWordDoc.PageSetup.Orientation = wdOrientLandscape
    
    'Bring it to the Front
    Call AppActivate(oWord.ActiveDocument.Name)

Error_Handler_Exit:
    On Error Resume Next
    Set oWordDoc = Nothing
    Set oWord = Nothing
    Exit Function

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

so on and so forth.
 
 
So as you can see, there are numerous ways to bring a given window to the forefront to ensure it is visible by your users.

2 responses on “VBA – Find A Window By Its Title and Bring It To The Front

    1. Daniel Pineault Post author

      I can’t say, I don’t have a MAC, nor do any of my clients run Office on their MACs.

      My gut would think the API approach wouldn’t work (I could be wrong though), but I’d suspect the UIAutomation or AppActivate would work.

      Only way to know for sure is to test.