TL;DR —
Application.FileDialogは Windows 標準のピッカーを開き、パスをハードコーディングする代わりに ユーザーにファイルやフォルダーを選ばせます。種類を選びます —msoFileDialogFilePicker、msoFileDialogFolderPicker、msoFileDialogSaveAs、msoFileDialogOpenのいずれかです。.Showを呼ぶと、ユーザーが何かを選べば-1、 キャンセルすれば0を返します — パスではありません。パスは 1 始まり のコレクション.SelectedItems(1)の中にあります。FileDialogが渡すのはパスで、開くのも保存するのも自分でやることに変わりはありません。
Sub PickAFile()
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.Title = "Choose a workbook"
.AllowMultiSelect = False
.Filters.Clear
.Filters.Add "Excel Files", "*.xlsx;*.xlsm"
If .Show <> -1 Then Exit Sub ' -1 = 選択あり、0 = キャンセル
MsgBox "You picked: " & .SelectedItems(1) ' 1 始まりのコレクション
End With
End Sub
"C:\Users\Me\Reports\Jan.xlsx" をマクロにハードコーディングするのは、他の誰かが実行した瞬間に壊れるようにする
一番の近道です。プロの習慣は たずねる ことです。VBA はそのための道具を三つ用意していて、そのすべてに共通する
ひとつの考え方を、まずはっきりさせておく価値があります。これらの道具が返すのはパスの文字列であって、ファイル
を開いたり、保存したり、触れたりはしません。 パスを手に入れることと、パスに対して動くことは、二つの別々のステ
ップです。FileDialog が三つのうちで最も高機能なのは、フォルダー もたずねられる唯一の道具だからです。
この記事で学べること
FileDialog・GetOpenFilename・GetSaveAsFilenameを結びつける考え方- 四つのダイアログの種類と、それぞれがどの仕事のためのものか
.ShowがTrue/Falseではなく-1と0を返す理由と、その確かめ方- 1 始まりのコレクション
.SelectedItemsから結果を読む方法 FolderPickerでフォルダーを選ぶ方法 — より単純な関数にはできないこと- 複数選択を許可する方法、フィルターを追加する方法、そして共有オブジェクトのリセットの落とし穴
考え方の軸:あとから読み取る、設定できるピッカー
Application.FileDialog は、パスを返す関数ではありません。設定し、表示し、そして読み取る オブジェクト です。
流れはいつも同じ三拍子です。
Set fd = Application.FileDialog(msoFileDialogFilePicker) ' 1. 種類(TYPE)を選ぶ
' ... .Title、.Filters、.AllowMultiSelect を設定 ... ' 2. 設定する
If fd.Show = -1 Then answer = fd.SelectedItems(1) ' 3. 表示してから、選択を読む
.Show はユーザーがボタンをクリックするまで処理を止め、パスではなく 状態(ステータス) を返します。パス —
あるいは複数のパス — は .SelectedItems に収まります。この二つの考えを分けておけば、オブジェクト全体の筋が通り
ます。ダイアログを表示することと、選択を読むことは、別々の行なのです。このページの残りはすべて、どの種類を選ぶ
か、そして結果をどう読むか、という話です。
四つのダイアログの種類
ダイアログの仕事は、Application.FileDialog(...) に渡す定数で選びます。
Application.FileDialog(msoFileDialogFilePicker) ' 既存のファイルを一つ以上選ぶ
Application.FileDialog(msoFileDialogFolderPicker) ' フォルダーを選ぶ(ファイルではなく)
Application.FileDialog(msoFileDialogOpen) ' FilePicker と同じで、開く .Execute が付く
Application.FileDialog(msoFileDialogSaveAs) ' 保存先のパスと名前を選ぶ
マクロの 90% では、msoFileDialogFilePicker(読み込むファイルを取得)か msoFileDialogFolderPicker(ループする
フォルダーを取得)を使いたいはずです。Open と SaveAs の種類には、実際に開く/保存する .Execute メソッドが
余分に付いていますが、それが必要になることはめったにありません — パスを読んで自分で
Workbooks.Open や SaveAs を呼ぶほうが分かりやすく、
次に何が起きるかを自分で制御できます。
なぜ .Show は -1 と 0 を返すのか
これは、.Show が選ばれたパスを返すと思っている人がつまずく細部です。返すのは 整数の状態(ステータス) です。
If fd.Show = -1 Then
' user clicked OK / Open / Save - 選択が存在する
Else
' user clicked Cancel - .SelectedItems は空、読んではいけない
End If
-1 は選択がなされたこと、0 はユーザーがキャンセルしたことを意味します。たまたま -1 は VBA が True と呼ぶ
値なので、If fd.Show = -1 も If fd.Show もどちらも動きます — でも = -1 と書きましょう。その数字が 何を意味
するか を語ってくれるからです。大事なのは後半の Else です。ユーザーがキャンセルすると .SelectedItems は空に
なり、SelectedItems(1) は実行時エラーを起こします。読む前に、必ずキャンセルをガードしましょう。
結果を読む:SelectedItems は 1 始まり
ユーザーの選択は コレクション である .SelectedItems で、すべての VBA コレクションと同じく 0 ではなく 1 から
数えます。
If fd.Show = -1 Then
Dim i As Long
For i = 1 To fd.SelectedItems.Count ' コレクションは 1 始まり
Debug.Print fd.SelectedItems(i) ' 各項目はフルパスの文字列
Next i
End If
ファイルを一つだけ選ぶなら、.SelectedItems(1) がすべてです。For i = 1 To .Count のループが意味を持つのは、
複数選択をオンにしたときだけで — そのループを 0 から始めるのは、「インデックスが有効範囲にありません」を起こす
典型的な 1 ずれです。各項目は、Workbooks.Open・Dir・あるいは
FileSystemObject にそのまま渡せる完全なパスです。
フォルダーを選ぶ — FileDialog だけができること
より単純な関数の隣に FileDialog が居場所を得る理由がこれです。GetOpenFilename
が返せるのは ファイル だけです。フォルダー が必要なとき — たとえばその中のすべてのブックをループするために —
使う道具が FolderPicker です。
Sub PickAFolder()
Dim fd As FileDialog, folderPath As String
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
If fd.Show <> -1 Then Exit Sub
folderPath = fd.SelectedItems(1)
If Right(folderPath, 1) <> "\" Then folderPath = folderPath & "\" ' 正規化する
MsgBox "Chosen folder: " & folderPath
End Sub
フォルダーは末尾のバックスラッシュ なし で返ってきます。ですからファイル名を続けて付ける
(folderPath & "Report.xlsx")つもりなら、\ は自分で足しましょう — これを忘れるのが、フォルダーをループする
マクロで一番多いバグです。ここから先は、Dir(folderPath & "*.xlsx") がフォルダー内のすべてのブックをたどります。
複数選択、フィルター、そしてリセットの落とし穴
残りのほとんどは、二つの設定でカバーできます。AllowMultiSelect = True はユーザーに複数のファイルを選ばせるもの
で、まさに先ほどの For i = 1 To .Count ループが活きる場面です。フィルターは、ダイアログが表示するものを絞り込み
ます。
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = True
.Filters.Clear ' まずリセット - 下記参照
.Filters.Add "Spreadsheets", "*.xlsx;*.xlsm;*.xls"
.Filters.Add "All Files", "*.*"
If .Show = -1 Then MsgBox .SelectedItems.Count & " file(s) chosen"
End With
名前を付けておく価値のある落とし穴はこれです。Application.FileDialog は 単一の共有オブジェクト です。前回の
呼び出しのフィルターや設定が、まだそこに残っていることがあります。自分のフィルターを追加する前には必ず
.Filters.Clear を呼び、.AllowMultiSelect も毎回明示的に設定しましょう。さもないと、セッションの前のほうで紛れ
込んだ設定が、あなたのダイアログに漏れ出します。実際には共有されているオブジェクトを、まっさらなものとして扱うの
は、静かで再現しにくいバグです。
FileDialog か GetOpenFilename か:何を返してほしいかで選ぶ
フォルダー が必要なとき、あるいは最も豪華なダイアログ(複数選択に加えて細かいフィルター)が欲しいときは、
FileDialog が答えです。読み込むファイルのパスを一つ 手に入れたいだけなら、
GetOpenFilename は一行で、パスを直接返します — オブジェクトも .SelectedItems も
いりません。保存先 のパスが必要なら、それは GetSaveAsFilename です。三つとも
同じ規則に従います。渡すのはパスで、それを開くのも保存するのも、やはり次の行はあなたの仕事です。
ExcelMaster の活用
このページの二つの間違いは、静かなものです。ユーザーがキャンセルしたあとに .SelectedItems を読むこと(実行時エ
ラー)、そして選んだフォルダーからパスを組み立てるときに末尾のバックスラッシュを忘れること(間違った場所に書き出
されるファイル)。どちらも書きやすく、追いかけるのが厄介です。
ExcelMaster には、手順を普通の言葉で伝えら
れます — 「フォルダーを選ばせて、その中のすべてのブックを開いて」 — すると、キャンセルをガードし、パスを正規化し、
ファイルを正しくループする FileDialog のコードを書いてくれます。ブックとコードはあなたの手元に残り、1 ずれのバグ
も避けられます。
よくある質問
Excel VBA でファイルダイアログを開くには?
Set fd = Application.FileDialog(msoFileDialogFilePicker) でオブジェクトを作り、設定してから(.Title、
.Filters、.AllowMultiSelect)、fd.Show を呼びます。.Show は、ユーザーが何かを選べば -1、キャンセルすれば
0 を返します。選ばれたパスは fd.SelectedItems(1) から読みます。これが返すのはパスだけで、開くにはやはり
Workbooks.Open を呼ぶことに注意してください。
VBA でユーザーにフォルダーを選ばせるには?
Application.FileDialog(msoFileDialogFolderPicker) を使います。これは、ファイルではなくフォルダーを返す唯一のファ
イルダイアログで — GetOpenFilename にはできません。If fd.Show = -1 Then のあと、
fd.SelectedItems(1) でフォルダーのパスを読み、ファイル名を足す前にバックスラッシュを付け加えます。フォルダーは末
尾の \ なしで返ってくるからです。
FileDialog.Show がファイルのパスではなく -1 を返すのはなぜですか?
.Show が返すのはパスではなく状態だからです。-1 はユーザーが選択したこと、0 はキャンセルしたことを意味します。
選ばれたパス(複数のこともある)は .SelectedItems コレクションの中にあります。まず If fd.Show = -1 Then を確か
め、-1 のときだけ .SelectedItems(1) を読みます。キャンセルのあとはそのコレクションが空で、インデックスを付ける
とエラーになるからです。
FileDialog で複数のファイルを選ぶには?
.Show を呼ぶ前に .AllowMultiSelect = True を設定します。ユーザーが複数のファイルを選んだら、
For i = 1 To fd.SelectedItems.Count をループして、各パスを fd.SelectedItems(i) で読みます。コレクションは 1 始
まりなので、ループは 0 ではなく 1 から始めます — 0 から始めると「インデックスが有効範囲にありません」が起きま
す。
FileDialog と GetOpenFilename の違いは何ですか?
GetOpenFilename は、ファイルのパスの文字列(キャンセル時は False)を返す一行の
関数で — 読み込むファイルが一つ必要なだけなら一番手軽です。FileDialog は設定できるオブジェクトで、フォルダーも選
べ、より豊かな複数選択ができ、(.Execute を通じて)直接開いたり保存したりもできます。よくある場面では
GetOpenFilename、フォルダーや追加の制御が必要なときは FileDialog を使いましょう。
検証環境
検証環境: Excel 365 (Windows 11)、VBA 7.1 — 最終確認 2026-09-26。
関連ガイド: VBA GetOpenFilename · VBA GetSaveAsFilename · VBA Open Workbook · VBA Dir · VBA FileSystemObject · VBA For Each
