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.

Does this work on a MAC as well as WIndows?
‘
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.