【VBA】ファイル選択ダイアログでユーザーにファイルを選ばせる方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク

この記事でできること

  • VBAのApplication.FileDialogでファイル選択ダイアログを表示し、ユーザーにファイルを選ばせる
  • .Filters.Addで拡張子フィルタを設定し、Excelファイルだけを表示させる
  • .AllowMultiSelectで複数ファイルの同時選択ができる
  • .InitialFileNameで初期フォルダを指定できる
  • .Showの戻り値でキャンセル判定を正しく書ける
  • 実務版: ダイアログでExcelファイルを選択→開いて集計→結果をシートに書き出す

対象: Excel 2016以降 / Microsoft 365、Windows 10/11


完成イメージ(Before / After)

Before(パス直書き):

  1. マクロの対象ファイルを変えたい
  2. VBEを開いてコード内のファイルパスを書き換える
  3. マクロを実行
  4. 別のファイルに変えたいとき → またVBEを開いて書き換え
  5. 毎回この作業を繰り返す

After(ファイル選択ダイアログ):

  1. マクロを実行
  2. ファイル選択ダイアログが表示される → 対象ファイルをクリックして「開く」
  3. 選択したファイルのデータが集計される
  4. 別のファイルにしたいとき → もう一度実行してファイルを選ぶだけ

フォルダ内のExcelファイルを集計するマクロを作ったが、ファイルパスをコードに直書きしていた。対象ファイルが変わるたびにVBEを開いてパスを修正するのが正直めんどくさかった。ファイル選択ダイアログを組み込んだら、コードを触らず誰でも対象ファイルを選べるマクロになった。同じ面倒を感じている人がこの記事でサクッと解消できればうれしい。

UserFormは複数の入力項目をまとめた本格的なフォーム向き。FileDialogはファイルやフォルダの選択に特化している。用途に応じて使い分けるとよい。UserFormの使い方は 入力フォームで手入力ミスを防ぐ方法 を参照。

ファイル選択ダイアログを使えば、対象ファイルをコード変更なしでユーザーが自由に選べる。


実行前の準備

バックアップを取る

実務版ではファイルを開いてデータを集計するため、マクロ実行前にExcelファイルのコピーを別フォルダに保存しておく。

Excelをマクロ有効ブック(.xlsm)で保存する

拡張子が .xlsx のままだとマクロが保存できない。

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. Alt + F8 → マクロ名を選んで「実行」

ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。


コード(最小版)– ファイル選択ダイアログでファイルパスを取得

まずはFileDialogの基本。ファイル選択ダイアログを表示して、選択されたファイルのパスをMsgBoxで表示するだけの最小コード。キャンセル判定も入れている。


'============================================================
' ■ ファイル選択ダイアログでパスを取得(最小版)
'   → ダイアログを表示し、選択したファイルのパスをMsgBoxで確認
'============================================================
Sub ファイル選択ダイアログを表示する()
    Dim fd As FileDialog
    Dim selectedFile As String

    '--- FileDialogオブジェクトを取得(ファイル選択モード)
    Set fd = Application.FileDialog(msoFileDialogFilePicker)

    '--- ダイアログの設定
    With fd
        .Title = "対象ファイルを選択してください"   ' タイトル
        .AllowMultiSelect = False                     ' 単一選択
        .InitialFileName = "C:\"                      ' 初期フォルダ

        '--- フィルタの設定(Excelファイルのみ表示)
        .Filters.Clear
        .Filters.Add "Excelファイル", "*.xlsx; *.xlsm; *.xls"
        .Filters.Add "すべてのファイル", "*.*"
    End With

    '--- ダイアログを表示(-1: OK、0: キャンセル)
    If fd.Show = -1 Then
        selectedFile = fd.SelectedItems(1)
        MsgBox "選択されたファイル: " & selectedFile, vbInformation
    Else
        MsgBox "キャンセルされました。", vbExclamation
    End If
End Sub

書き換えポイント

変数・箇所 説明 初期値
"対象ファイルを選択してください" ダイアログのタイトルバーに表示する文字 「対象ファイルを選択してください」
"C:\" ダイアログを開いたときの初期フォルダ。ThisWorkbook.Path にすれば自ブックと同じフォルダになる C:\
"*.xlsx; *.xlsm; *.xls" 表示するファイルの拡張子。; で区切って複数指定可 Excel系ファイル
.AllowMultiSelect = False True にすると複数ファイルを選択可能 False(単一選択)

コードの流れ

  1. Application.FileDialog(msoFileDialogFilePicker) でファイル選択ダイアログのオブジェクトを取得
  2. .Title でタイトル、.InitialFileName で初期フォルダ、.Filters.Add でフィルタを設定
  3. .Filters.Clear で既存のフィルタをクリアしてから .Filters.Add で追加(クリアしないと前回の設定が残る)
  4. .Show でダイアログを表示。ユーザーがファイルを選んで「開く」→ 戻り値 -1。「キャンセル」→ 戻り値 0
  5. .SelectedItems(1) で選択されたファイルのフルパスを取得(インデックスは1始まり)
  6. MsgBoxでパスを表示

.Show の戻り値は -1(True相当)と 0(False相当)。If fd.Show = -1 Then または If fd.Show <> 0 Then で判定する。If fd.Show Then と書くと -1True と評価されるため動作するが、明示的に -1 と比較するほうが可読性が高い。


コード(実務版)– ダイアログでExcelファイルを選択→開いて集計→結果を書き出す

実務では「ダイアログでファイルを選ばせて、そのファイルを開いて処理する」パターンが多い。この実務版では、ファイル選択ダイアログでExcelファイルを選択し、開いてA列のデータ合計を集計して結果をシートに書き出す。

自分はこのコードを月次の売上報告集計に使っている。毎月届くExcelファイルをダイアログで選ぶだけで、A列の売上合計が集計シートに書き出される。ファイル名が毎月変わっても、コードを触る必要がない。

ファイルを開いて処理する詳細は Excelファイルを自動で開いて処理して閉じる方法 を参照。ファイルの存在チェックは ファイルやフォルダの存在を確認してから処理する方法 を参照。エラー処理の詳細は エラー処理の基本 を参照。


'============================================================
' ■ ダイアログでExcelファイルを選択→開いて集計→結果を書き出す(実務版)
'   → ファイル選択ダイアログでExcelファイルを選択
'   → 選択したファイルを読み取り専用で開く
'   → A列(2行目以降)の合計を計算
'   → 集計結果を「Sheet1」に書き出す
'============================================================
Sub ダイアログで選んだファイルを集計する()
    Dim fd As FileDialog
    Dim selectedFile As String
    Dim wb As Workbook
    Dim wsSrc As Worksheet
    Dim wsResult As Worksheet
    Dim lastRow As Long
    Dim total As Double

    '--- FileDialogオブジェクトを取得(ファイル選択モード)
    Set fd = Application.FileDialog(msoFileDialogFilePicker)

    '--- ダイアログの設定
    With fd
        .Title = "集計対象のExcelファイルを選択してください"
        .AllowMultiSelect = False
        .InitialFileName = ThisWorkbook.Path & "\"

        '--- フィルタの設定(Excelファイルのみ)
        .Filters.Clear
        .Filters.Add "Excelファイル", "*.xlsx; *.xlsm; *.xls"
    End With

    '--- ダイアログを表示
    If fd.Show <> -1 Then
        MsgBox "キャンセルされました。", vbExclamation
        Exit Sub
    End If

    '--- 選択されたファイルパスを取得
    selectedFile = fd.SelectedItems(1)

    '--- 画面更新を停止(高速化)
    Application.ScreenUpdating = False

    '--- エラー発生時もScreenUpdatingを復帰させる
    On Error GoTo ErrHandler

    '--- 選択したファイルを読み取り専用で開く
    Set wb = Workbooks.Open(selectedFile, ReadOnly:=True, UpdateLinks:=0)
    Set wsSrc = wb.Sheets(1)

    '--- A列の最終行を取得
    lastRow = wsSrc.Cells(wsSrc.Rows.Count, 1).End(xlUp).Row

    '--- データがない場合は終了
    If lastRow < 2 Then
        wb.Close SaveChanges:=False
        Application.ScreenUpdating = True
        MsgBox "データがありません。", vbExclamation
        Exit Sub
    End If

    '--- A列(2行目以降)の合計を計算
    '    ※ 文字列が混在していてもエラーにならないよう安全に処理
    On Error Resume Next
    total = Application.WorksheetFunction.Sum(wsSrc.Range("A2:A" & lastRow))
    If Err.Number <> 0 Then
        total = 0
        Err.Clear
    End If
    On Error GoTo ErrHandler

    '--- ファイルを閉じる(保存しない)
    wb.Close SaveChanges:=False
    Set wb = Nothing

    '--- 集計結果をSheet1に書き出す
    Set wsResult = ThisWorkbook.Sheets("Sheet1")
    Dim writeRow As Long
    writeRow = wsResult.Cells(wsResult.Rows.Count, 1).End(xlUp).Row + 1

    wsResult.Cells(writeRow, 1).Value = Dir(selectedFile)   ' ファイル名
    wsResult.Cells(writeRow, 2).Value = total                ' 合計値
    wsResult.Cells(writeRow, 3).Value = Now                  ' 集計日時

    '--- 列幅を自動調整
    wsResult.Columns("A:C").AutoFit

    '--- 画面更新を再開
    Application.ScreenUpdating = True

    '--- 完了メッセージ
    MsgBox "集計が完了しました。" & vbCrLf & _
           "ファイル: " & Dir(selectedFile) & vbCrLf & _
           "A列合計: " & Format(total, "#,##0"), vbInformation
    Exit Sub

ErrHandler:
    '--- エラー発生時も画面更新を必ず復帰
    Application.ScreenUpdating = True
    If Not wb Is Nothing Then
        wb.Close SaveChanges:=False
        Set wb = Nothing
    End If
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

書き換えポイント

変数・箇所 説明 初期値
"集計対象のExcelファイルを選択してください" ダイアログのタイトル 集計対象の選択を促す文
ThisWorkbook.Path & "\" 初期フォルダ。自ブックと同じフォルダを起点にする 自ブックのフォルダ
"*.xlsx; *.xlsm; *.xls" 表示するファイルの拡張子 Excel系ファイル
wsSrc.Range("A2:A" & lastRow) 合計を計算する範囲。列や開始行に応じて変更 A列の2行目以降
Sheets("Sheet1") 集計結果を書き出すシート名 Sheet1

コードの流れ

  1. ダイアログ表示: FileDialogでExcelファイルのみ表示するフィルタを設定し、ダイアログを表示
  2. キャンセル判定: .Show <> -1 ならキャンセルで終了
  3. ファイルを開く: 選択したファイルを ReadOnly:=True で読み取り専用で開く
  4. データ存在チェック: A列の最終行が2未満ならデータなしで終了
  5. 合計計算: WorksheetFunction.Sum でA列の2行目以降の合計を計算。文字列が混在していてもエラーにならないよう On Error Resume Next で保護
  6. ファイルを閉じる: SaveChanges:=False で保存せず閉じる
  7. 結果書き出し: Sheet1にファイル名・合計値・集計日時を書き出す
  8. 完了メッセージ: ファイル名と合計値を表示

Dir(selectedFile) はフルパスからファイル名だけを取得する。"C:\Data\売上.xlsx""売上.xlsx" になる。


応用:フォルダ選択ダイアログ / 複数ファイル選択 / GetOpenFilenameとの違い

フォルダ選択ダイアログ(msoFileDialogFolderPicker)

ファイルではなくフォルダを選択させたい場合は msoFileDialogFolderPicker を使う。フォルダ内のファイルを一括処理するときに便利。複数ファイルの統合については 複数Excelファイルを1つに統合する方法 を参照。


'============================================================
' ■ フォルダ選択ダイアログ
'   → ユーザーにフォルダを選択させてパスを取得
'============================================================
Sub フォルダ選択ダイアログを表示する()
    Dim fd As FileDialog
    Dim folderPath As String

    '--- FileDialogオブジェクトを取得(フォルダ選択モード)
    Set fd = Application.FileDialog(msoFileDialogFolderPicker)

    With fd
        .Title = "対象フォルダを選択してください"
        .InitialFileName = "C:\"
    End With

    '--- ダイアログを表示
    If fd.Show = -1 Then
        '--- 戻り値には末尾に \ が付かないため、手動で付ける
        folderPath = fd.SelectedItems(1) & "\"
        MsgBox "選択されたフォルダ: " & folderPath, vbInformation
    Else
        MsgBox "キャンセルされました。", vbExclamation
    End If
End Sub

msoFileDialogFolderPicker の戻り値(SelectedItems(1))には末尾に \ が付かない。Dir でファイルを列挙するときは folderPath & "*.xlsx" のように \ が必要なので、取得直後に & "\" を付けておくのが確実。

複数ファイル選択(AllowMultiSelect = True)


'============================================================
' ■ 複数ファイル選択ダイアログ
'   → 複数ファイルを選択してパスを一覧表示
'============================================================
Sub 複数ファイルを選択する()
    Dim fd As FileDialog
    Dim i As Long
    Dim msg As String

    Set fd = Application.FileDialog(msoFileDialogFilePicker)

    With fd
        .Title = "処理対象のファイルを選択してください(複数選択可)"
        .AllowMultiSelect = True
        .InitialFileName = ThisWorkbook.Path & "\"
        .Filters.Clear
        .Filters.Add "Excelファイル", "*.xlsx; *.xlsm"
    End With

    If fd.Show <> -1 Then
        MsgBox "キャンセルされました。", vbExclamation
        Exit Sub
    End If

    '--- 選択されたファイルを順に処理
    msg = "選択されたファイル(" & fd.SelectedItems.Count & "件):" & vbCrLf
    For i = 1 To fd.SelectedItems.Count
        msg = msg & i & ". " & fd.SelectedItems(i) & vbCrLf
    Next i

    MsgBox msg, vbInformation
End Sub

.AllowMultiSelect = True にすると、CtrlキーやShiftキーで複数ファイルを選択できる。.SelectedItems.Count で選択数を取得し、For i = 1 To .SelectedItems.Count でループ処理する。インデックスは 1始まり なので注意。

Application.GetOpenFilename との使い分け

項目 FileDialog GetOpenFilename
フィルタ設定 .Filters.Add で柔軟に設定 引数で文字列指定
初期フォルダ .InitialFileName で指定可能 直接指定不可(ChDir で間接的に変更は可能だが、FileDialogのほうが直感的)
フォルダ選択 FolderPickerで可能 不可
ダイアログタイトル .Title で設定 Title 引数で設定
戻り値 SelectedItemsコレクション ファイルパス文字列(Variant)
コードの簡潔さ やや長い シンプル

GetOpenFilenameのほうがコードが短いが、初期フォルダの指定やフォルダ選択ができない。実務で細かく制御したい場合はFileDialogを使う。


' --- GetOpenFilenameのシンプルな例 ---
Sub GetOpenFilenameの例()
    Dim filePath As Variant
    filePath = Application.GetOpenFilename("Excelファイル,*.xlsx")
    If filePath = False Then
        MsgBox "キャンセルされました。", vbExclamation
        Exit Sub
    End If
    MsgBox "選択されたファイル: " & filePath, vbInformation
End Sub

よくある落とし穴5選

# 落とし穴 原因 対策
1 キャンセルしたら「実行時エラー5」が出る .Show の戻り値を確認せずに .SelectedItems(1) を参照している .Show = -1 を必ず確認してからSelectedItemsを参照する
2 前回のフィルタ設定が残っている .Filters.Clear を呼ばずに .Filters.Add だけ実行した .Filters.Add の前に必ず .Filters.Clear を入れる
3 ダイアログが毎回違うフォルダで開く .InitialFileName を設定していない。直前に開いたフォルダが使われる .InitialFileName = ThisWorkbook.Path & "\" で初期フォルダを明示的に指定する
4 複数選択でSelectedItems(0)を参照してエラーになる VBAのSelectedItemsコレクションはインデックスが1始まり。0を指定するとエラー For i = 1 To fd.SelectedItems.Count で1から開始する
5 InitialFileNameにフォルダを指定したのにファイル名入力欄に文字が入る フォルダパスの末尾に \ を付けていない。"C:\Data" だとDataがファイル名として扱われる フォルダパスの末尾に必ず \ を付ける(例: "C:\Data\"

自分も .Show の戻り値チェックを入れずにSelectedItems(1)を参照したことがある。キャンセルを押した瞬間に「実行時エラー5」で落ちて、そのたびにVBEのデバッグ画面が開いた。それ以来、.Showの直後に必ずキャンセル判定を入れるようにしている。


FAQ

Q1: ダイアログの初期フォルダを指定したい

.InitialFileName にフォルダパスを指定する。末尾に \ を付けるのがポイント。付けないとフォルダ名がファイル名入力欄に入ってしまう。


fd.InitialFileName = "C:\Data\売上報告\"
' 自ブックと同じフォルダにしたい場合
fd.InitialFileName = ThisWorkbook.Path & "\"

Q2: Excelファイルだけ表示するようにフィルタしたい

.Filters.Clear でクリアしてから .Filters.Add で追加する。複数の拡張子はセミコロン ; で区切る。


With fd
    .Filters.Clear
    .Filters.Add "Excelファイル", "*.xlsx; *.xlsm; *.xls"
    .Filters.Add "CSVファイル", "*.csv"
    .Filters.Add "すべてのファイル", "*.*"
End With

Q3: 複数ファイルをまとめて選択して順に処理したい

.AllowMultiSelect = True にして、SelectedItems をForループで回す。


fd.AllowMultiSelect = True
If fd.Show = -1 Then
    Dim i As Long
    For i = 1 To fd.SelectedItems.Count
        Debug.Print fd.SelectedItems(i)   ' 各ファイルのパス
    Next i
End If

Q4: FileDialogとGetOpenFilenameのどちらを使うべきか

シンプルにファイルパスだけ取得したい場合: Application.GetOpenFilename が手軽。コードが短くて済む。

フィルタ・初期フォルダ・複数選択を細かく制御したい場合: Application.FileDialog のほうが柔軟。実務で使うならFileDialogを推奨。

Q5: フォルダを選択させてフォルダ内のファイルを一括処理したい

Application.FileDialog(msoFileDialogFolderPicker) でフォルダを選択させ、Dir でファイルを列挙する。


Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
If fd.Show = -1 Then
    Dim folderPath As String
    '--- 戻り値に末尾 \ が付かないため手動で付ける
    folderPath = fd.SelectedItems(1) & "\"
    Dim f As String
    f = Dir(folderPath & "*.xlsx")
    Do While f <> ""
        Debug.Print folderPath & f
        f = Dir()
    Loop
End If

まとめ

  • Application.FileDialog(msoFileDialogFilePicker) でファイル選択ダイアログを表示できる
  • .Filters.Clear.Filters.Add で拡張子フィルタを設定する(Clearを忘れない)
  • .AllowMultiSelect = True で複数ファイルの同時選択が可能
  • .InitialFileName で初期フォルダを指定する(末尾に \ を付ける)
  • .Show の戻り値で必ずキャンセル判定を行う(-1: OK、0: キャンセル)
  • フォルダ選択は msoFileDialogFolderPicker を使う

関連記事


次にやりたくなること


もっとカスタマイズしたい場合

「ダイアログで選んだ複数ファイルを順番に集計したい」「フォルダを選んでサブフォルダも含めて一括処理したい」「選択したファイルの内容に応じて処理を分岐させたい」など、業務に合わせたカスタマイズが必要な場合は、ココナラで相談できる。

相談時に伝えると話が早い情報:

  • Excel のバージョン / OS
  • 選択するファイルの種類(Excel、CSV、PDFなど)
  • 選択後にやりたい処理(集計、転記、PDF変換など)
  • 複数ファイルを処理するか、1ファイルずつか

コメント

タイトルとURLをコピーしました