To bring a modeless Excel VBA UserForm forward on Windows, show it with vbModeless, then use the Windows API SetWindowPos to move its window to the front. If the form should block interaction with Excel, use the default modal display instead: UserForm1.Show vbModal. A modeless form can be covered by other windows, and VBA has no simple, built-in UserForm method that reliably keeps it above them.
Choose modal or modeless display first
The right solution depends on what “bring to front” means for the workbook. A modal form is displayed in front of its owning Excel window and prevents the user from working in that workbook until the form is hidden or unloaded. This is usually appropriate for a required choice, confirmation, or short data-entry step. Calling UserForm1.Show without an argument is modal by default; writing UserForm1.Show vbModal makes that choice explicit.
A modeless form lets the user continue working in Excel while the form remains open. Use UserForm1.Show vbModeless for a persistent tool such as a search panel or a small command window. Because the user can switch between Excel and other applications, the modeless form may lose its position in the Windows stacking order. A modal form is not globally pinned above every other application, either: modal means that it blocks its owner, not that it is always on top of the desktop.
These modes solve different problems. If users should not interact with the sheet until the form is complete, prefer modal display rather than trying to force a modeless form forward. If they need to use the sheet and the form together, modeless display is more suitable, with a separate fronting step when needed.
Use a Windows API call for a modeless form
Excel VBA does not offer a dependable UserForm.ZOrder method for placing the whole form window above other windows. The ZOrder method often encountered in VBA examples applies to certain controls, not as a general way to position a UserForm window. On Windows, a common approach is to find the form’s window handle and call the Windows API function SetWindowPos.
The example below temporarily marks the form as topmost and then removes that topmost status. This raises it without deliberately leaving it pinned above other applications. The window handle is found using the form’s caption and the class name commonly used by VBA UserForms. Windows API calls depend on Windows and on host implementation details, so this technique is not a cross-platform VBA feature.
Add the API declarations and helper procedure
Place this code in a standard VBA module, not in a worksheet module. It is written for VBA7, used by Microsoft 365 Excel for Windows, and uses LongPtr so the window handle has the appropriate size in 32-bit or 64-bit Office. The API declarations must be at the top of the module, before its procedures.
Option Explicit
' Windows API declarations for VBA7 in Excel for Windows.
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function SetWindowPos Lib "user32" ( _
ByVal hWnd As LongPtr, ByVal hWndInsertAfter As LongPtr, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal uFlags As Long) As Long
Private Const SWP_NOSIZE As Long = &H1
Private Const SWP_NOMOVE As Long = &H2
Private Const SWP_SHOWWINDOW As Long = &H40
Public Sub BringUserFormToFront(ByVal formCaption As String)
Dim formHandle As LongPtr
Dim positionFlags As Long
' Find the form by its standard VBA UserForm window class and caption.
formHandle = FindWindow("ThunderDFrame", formCaption)
If formHandle = 0 Then Exit Sub
positionFlags = SWP_NOMOVE Or SWP_NOSIZE Or SWP_SHOWWINDOW
' Raise the window, then remove its temporary topmost status.
Call SetWindowPos(formHandle, CLngPtr(-1), 0, 0, 0, 0, positionFlags)
Call SetWindowPos(formHandle, CLngPtr(-2), 0, 0, 0, 0, positionFlags)
End Sub
FindWindow returns zero when it cannot find a window matching both the class name and caption; the helper then exits without attempting to reposition anything. The commonly used class name is ThunderDFrame, but it is an implementation detail rather than a promise that applies to every host or future version. If the handle is not found, check the form caption and consider whether the host uses a different class name before changing the code.
Call the helper after showing the form
For a modeless form, call the helper after the Show statement has returned. At that point the form window should exist and can be found. For example, put this procedure in the same standard module:
Public Sub OpenSearchPanel()
' Show the form without blocking work in Excel.
UserForm1.Show vbModeless
' Raise it after Windows has created the form window.
BringUserFormToFront UserForm1.Caption
End Sub
Replace UserForm1 with the form’s actual VBA name. The caption passed to the helper must match the form’s Caption property, not necessarily its VBA name. If two open windows share the same caption and class, FindWindow may find the wrong one; use unique captions when practical. The example’s API declarations use the ANSI FindWindowA entry point, so captions with unusual characters can also be a reason to adapt the lookup method.
Save a copy of the workbook before running a macro. VBA macros cannot be undone with Ctrl+Z, and API-based code can behave differently from ordinary worksheet operations. Save the workbook as a macro-enabled Excel workbook (.xlsm) if it needs to retain VBA code.
Understand what “front” and “focus” mean
Window order and keyboard focus are related but distinct. Bringing a form forward changes where it sits in the window stacking order. Focus determines which window or control receives keystrokes. The example raises the form and requests normal window activation through SetWindowPos; it does not select a particular text box or guarantee that a particular control is ready for typing.
If the form appears but typing still goes somewhere unexpected, set the desired control’s focus after the form is shown. For example, if TextBox1 is a control on the form, a procedure in the form’s code module can call TextBox1.SetFocus once the form is active. The control must be enabled and visible, and the form must be active; otherwise focus may not move as expected. This is different from raising the form window itself.
Windows also manages which application is allowed to take foreground focus. Applications cannot always force themselves in front of a user’s current work. Therefore, an API call should be treated as a request to change the window order, not a guarantee that Excel will steal attention from another application in every circumstance.
Common problems and practical fixes
- The form is not found: Confirm that it has already been shown, that the caption is exact, and that the lookup class matches the form window. A zero handle means the API did not find a match; it is not a signal to pass a zero handle to another Windows API.
- The form goes behind Excel again: Another window activation or a later call to show a different form can change the stacking order. Call the helper at the point where the form needs raising, rather than assuming one call pins it permanently.
- The form appears but does not accept typing: Check which control has focus and whether it is enabled and visible. Raising the form is not the same as focusing a text box.
- The form stays above other applications: The code makes two API calls to avoid leaving it topmost. If the second call fails or is removed, the form could remain in the topmost group. Do not omit the reset simply to make the form more persistent unless that behavior is intentional.
- A different form is raised:
FindWindowsearches by caption and class, not by a VBA object reference. Give simultaneously open forms distinct captions or use a more specific handle-retrieval approach. - The code will not compile: Confirm that the declarations are in a standard module and that the Office installation uses VBA7. The declarations shown are for Windows, not for Excel on Mac.
Mac and Excel for the web limitations
The user32 library and the declarations above are Windows-specific. They will not work in Excel for Mac, which does not provide this Windows API. On Mac, use the normal UserForm display methods and design the workflow around modal or modeless behavior; there is no equivalent Windows SetWindowPos call to copy into Mac VBA. Avoid compiling Windows API declarations as though they were portable across both platforms.
Excel for the web does not run VBA macros or display VBA UserForms. Users opening the workbook in a browser cannot use this macro-driven approach; they would need to open it in desktop Excel for Windows, or use a different web-compatible workflow. For a workbook shared across Windows, Mac, and browser users, document the platform requirement clearly and consider whether a UserForm is essential.
Alternatives when an API is not appropriate
Start with the simplest option that meets the requirement. A modal form is the cleanest choice when users must finish a task before returning to Excel. A modeless form is right when sheet interaction must continue, but it may need to be brought forward again after the user switches windows. If an always-visible interface is a core requirement across platforms, consider whether worksheet controls, a dedicated worksheet panel, or an Office add-in would fit better than a Windows-only API call.
Another useful design choice is to make the form easy to recover rather than trying to keep it permanently on top. Provide a worksheet button or ribbon command that shows the form again, and avoid opening duplicate copies of the same form. This is often less disruptive than repeatedly forcing a window to the foreground, especially when the user is working in another application.
Frequently Asked Questions
How do I show an Excel VBA UserForm on top?
For a modal form, use UserForm1.Show vbModal; it stays in front of its owning Excel window while it blocks interaction with that workbook. For a modeless form, use Show vbModeless and, on Windows, call a window-positioning API after showing it if it needs to be raised.
Does a UserForm have a ZOrder method?
Do not rely on ZOrder as a built-in way to position the whole UserForm window. The method associated with many VBA examples applies to controls. Raising the form window itself on Windows requires a window-level approach, such as the API example above.
Can I keep a UserForm always on top?
Windows can mark a window topmost, but that places it above ordinary windows from other applications too and can interfere with the user’s work. The example briefly uses topmost status and then removes it. It raises the form without intending to keep it permanently pinned.
Why does my modeless form appear behind Excel?
A modeless form does not block Excel, and switching windows or activating another form can change which window is in front. Raise it after displaying it, or offer a command that brings it back when needed. A modal form may be more suitable if users should not switch back to the workbook during the task.
Will this VBA code work on Mac or in a browser?
No. The user32 API is for Windows, and Excel for the web does not run VBA. Mac users need a design that uses supported UserForm behavior without this Windows call, while browser users need a non-VBA alternative.
Related
- Excel Page Break Reset: How to Restore Defaults
- Excel Page Break Preview Without Page Numbers: What to Know
- Excel Page Break Preview: Add and Move Page Breaks
Try it: the Column Letter to Number: aA is 27, XFD is 16,384. Converts both ways.
More in VBA & macros
- Excel VBA: Find the First Row Above a Value ThresholdTo find the first row where a cell’s value is greater than a threshold, loop through the relevant…
- Access VBA Error Handling: Trapping and Fixing ErrorsAccess VBA error handling lets a procedure respond when a runtime error occurs instead of stopping unexpectedly. Use…
- How to Find VBA Code in Excel: Open and Search MacrosTo find VBA code in Excel for Microsoft 365 on Windows, open the workbook in the desktop app,…
- Excel VBA: Loop Through All Open Workbooks in a MacroTo loop through every workbook currently open in desktop Excel, use a For Each loop over Application.Workbooks. Declare…
- VBA Range Object: How to Work with CellsThe Excel VBA Range object represents one or more cells on a worksheet, letting code read or change…
- Excel VBA Freeze Panes at a Specific CellYes. Activate the worksheet, select the cell that marks the top-left corner of the scrolling area, then set…
Sources: Function behaviour and menu paths: Microsoft Support documentation for Excel. Method & sources
Spotted an error in this guide? Let us know.