🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA GetOpenFilename in Excel — Get a File Path, Then Open It Yourself

|

VBA GetOpenFilename in Excel — Get a File Path, Then Open It Yourself

TL;DR — Application.GetOpenFilename shows the Open dialog and returns the path the user picked as a string — it does not open the file. To actually open it you still call Workbooks.Open. When the user clicks Cancel it returns the Boolean False, so declare the variable As Variant (never As String) and test If fname = False Then Exit Sub before you use it.

Sub AskThenOpen()
    Dim fname As Variant                       ' Variant, so cancel can return False
    fname = Application.GetOpenFilename( _
            "Excel Files (*.xlsx;*.xlsm), *.xlsx;*.xlsm", , "Choose a workbook")
    If fname = False Then Exit Sub             ' user cancelled
    Workbooks.Open fname                        ' GetOpenFilename only gave the path
End Sub

GetOpenFilename is the shortest way to stop hardcoding paths. It shows the familiar Open dialog, lets the user browse, and hands you back what they chose. But two facts about it cause most of the questions online, and both come from the same misunderstanding: this function returns a path — it does not open the file, and it does not fail loudly when the user cancels. Get those two straight and it is a one-liner you will reach for constantly.

What you'll learn

  • The mental model that ties GetOpenFilename, GetSaveAsFilename and FileDialog together
  • Why it returns a path, not an open workbook — and the one line you still owe
  • The cancel trap: it returns False, so the variable must be As Variant
  • The FileFilter syntax, with multiple extensions and multiple filter groups
  • Returning many paths at once with MultiSelect:=True (a 1-based array)
  • When GetOpenFilename is enough and when to step up to FileDialog

The mental model: a sticky note that asks which file

Think of GetOpenFilename as handing the user a sticky note that asks "which file?" — they write down a path and give it back. That is all it does. It does not walk to the filing cabinet and pull the file out:

fname = Application.GetOpenFilename(...)   ' returns a PATH string, e.g. "C:\Data\Jan.xlsx"
Workbooks.Open fname                        ' YOU do the opening

The single most common "GetOpenFilename doesn't work" report is really "I called it and my file did not open." Of course it did not — you got the path; opening it is a separate line. Once you internalise that asking for a path and acting on the path are two steps, the function becomes simple and predictable.

The cancel trap: return False, so Dim As Variant

This is the one that bites hardest. When the user clicks Cancel, GetOpenFilename returns the Boolean value False. That forces a choice on you when you declare the variable:

Dim fname As Variant     ' CORRECT - can hold a path String OR the Boolean False
' Dim fname As String    ' WRONG - False gets coerced to the text "False"

If you declare fname As String, VBA quietly coerces the returned False into the string "False", so If fname = False never triggers and your code marches on with a garbage "path" called False. Declaring it As Variant keeps the Boolean a Boolean, so If fname = False Then Exit Sub actually catches the cancel. This is the exact same trap as reading a cancelled InputBox — the fix is the same: hold the result in a Variant and test the type of answer you got before you trust it.

The FileFilter: description, comma, pattern

The first argument controls which files the dialog shows. Its shape is a description, a comma, then the pattern — and you can chain several groups:

' One group: label, then the pattern(s)
fname = Application.GetOpenFilename("Text Files (*.txt), *.txt")

' Several extensions in one group: separate patterns with a semicolon
fname = Application.GetOpenFilename("Excel Files (*.xlsx;*.xlsm), *.xlsx;*.xlsm")

' Several groups the user can switch between: comma-separate the label/pattern pairs
fname = Application.GetOpenFilename( _
        "Excel Files, *.xlsx;*.xlsm, CSV Files, *.csv, All Files, *.*")

Inside one filter, multiple extensions are joined with semicolons (*.xlsx;*.xlsm). To offer several filters the user can flip between in the dropdown, comma-separate the label/pattern pairs. The optional second argument, FilterIndex, chooses which group is selected by default; the third, Title, sets the dialog caption. Getting the comma-versus-semicolon rule right is what separates a filter that works from one that shows nothing.

Multiple files: MultiSelect returns a 1-based array

Pass MultiSelect:=True and the return type changes: instead of one path string you get an array of paths — or still False if the user cancelled:

Sub OpenSeveral()
    Dim files As Variant, i As Long
    files = Application.GetOpenFilename( _
            "Excel Files, *.xlsx;*.xlsm", , , , True)   ' last arg = MultiSelect
    If Not IsArray(files) Then Exit Sub                 ' False (cancel) is not an array
    For i = LBound(files) To UBound(files)              ' the array is 1-based
        Workbooks.Open files(i)
    Next i
End Sub

Two details matter. Test IsArray(files) rather than = False, because on success you now hold an array, not a string. And loop with LBound to UBound — the array GetOpenFilename returns starts at 1, and hardcoding For i = 1 To ... happens to work here, but LBound/UBound is the habit that never breaks. Each element is a full path ready for Workbooks.Open.

GetOpenFilename or FileDialog? Pick by what you need

For the everyday job — ask for one file to read — GetOpenFilename wins on simplicity: one line, the path comes straight back, no object to configure. Step up to FileDialog when you need a folder (GetOpenFilename cannot pick one), when you want the dialog object's richer control, or when you prefer reading from .SelectedItems. To ask where to save rather than what to open, the mirror function is GetSaveAsFilename. All three share the rule: they return a path, and the open or save is your next line.

How ExcelMaster helps

The two mistakes here are the quiet kind: declaring the result As String (so the cancel slips through as the text "False"), and expecting the file to open when all you received was a path. Both compile fine and fail at run time on someone else's machine.

ExcelMaster lets you say what you want — "ask me for a CSV, then import it into a new sheet" — and it writes the GetOpenFilename call with the right filter, the Variant cancel guard, and the Workbooks.Open (or import) that actually acts on the path. You keep the workbook and the code.

Frequently asked questions

How do I use GetOpenFilename in Excel VBA?

Call fname = Application.GetOpenFilename(fileFilter, filterIndex, title). Declare fname As Variant, and test If fname = False Then Exit Sub to catch a cancel. On success fname holds the chosen path as a string — pass it to Workbooks.Open to open it. GetOpenFilename itself only returns the path; it does not open anything.

Why does GetOpenFilename not open the file?

Because it is not supposed to — it returns the path the user selected and stops there. Opening the file is a separate step: Workbooks.Open fname for a workbook, or a FileSystemObject / Dir for other files. The dialog is only asking "which file?"; acting on the answer is your code.

How do I check if the user clicked Cancel in GetOpenFilename?

Declare the variable As Variant and test If fname = False Then Exit Sub. On cancel the function returns the Boolean False; on success it returns a path string. If you declare the variable As String instead, False is coerced to the text "False", the check never fires, and the macro continues with an invalid path.

How do I select multiple files with GetOpenFilename?

Pass MultiSelect:=True (the fifth argument). The return value becomes an array of path strings, or False if cancelled. Test IsArray(result) first, then loop For i = LBound(result) To UBound(result) and open each result(i). Because the return type changes to an array, do not test = False for the cancel — use IsArray.

What is the FileFilter syntax in GetOpenFilename?

Each filter is a description followed by a comma and a pattern: "Excel Files (*.xlsx), *.xlsx". Join several extensions in one filter with semicolons: "*.xlsx;*.xlsm". Offer several filters by comma-separating the label/pattern pairs: "Excel, *.xlsx, CSV, *.csv, All, *.*". The optional FilterIndex argument sets which one is selected by default.

Tested in

Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-09-26.

Related guides: VBA FileDialog · VBA GetSaveAsFilename · VBA Open Workbook · VBA InputBox · VBA Dir · VBA UBound