TL;DR —
Application.GetOpenFilenameshows 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 callWorkbooks.Open. When the user clicks Cancel it returns the BooleanFalse, so declare the variableAs Variant(neverAs String) and testIf fname = False Then Exit Subbefore 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,GetSaveAsFilenameandFileDialogtogether - 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 beAs Variant - The
FileFiltersyntax, with multiple extensions and multiple filter groups - Returning many paths at once with
MultiSelect:=True(a 1-based array) - When
GetOpenFilenameis enough and when to step up toFileDialog
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
