【VBA】ファイルやフォルダの存在を確認してから処理する方法(コピペOK)

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

この記事でできること

VBAでファイルを開こうとしたら「ファイルが見つかりません」のエラーで止まった経験はないだろうか。Dir関数やFileSystemObjectを使えば、処理の前にファイルやフォルダの存在を確認し、なければ作成してから続行できる。コピペで動くコードで、エラー知らずのマクロを作ろう。

  • 対象:VBAでファイル操作をしていてエラーに困っている人
  • 所要時間:コピペ → 実行まで約5分(目安)
  • 成果物:存在チェック→なければ作成してからファイルコピーするマクロ

ファイル一覧を取得する方法は[記事001(フォルダ内ファイル一覧を自動取得)]で紹介している。一覧取得の前に「フォルダが存在するか?」を確認する場面で、この記事の内容が使える。

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


完成イメージ(Before / After)

Before(存在チェックなし)


マクロ実行
→ 「実行時エラー '53': ファイルが見つかりません」で停止
→ 残りの処理は実行されない

After(存在チェックあり)


マクロ実行
→ ファイルの存在を確認
→ 存在する場合:そのままコピー処理を実行
→ 存在しない場合:「ファイルが見つかりません」とメッセージを表示して安全に終了

実務版の動作イメージ


マクロ実行
→ コピー先フォルダの存在を確認
→ フォルダがない場合:自動で作成
→ コピー元ファイルの存在を確認
→ ファイルがある場合:コピー先フォルダにコピー
→ 「処理が完了しました」とメッセージ表示

実行前の準備

バックアップを取る

ファイルのコピーやフォルダの作成を伴う処理です。意図しない場所にファイルが作成されないよう、コード内のパスを必ず確認してください。重要なファイルを扱う場合は、先にバックアップを取ってください。

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

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

.xlsx のままだとマクロが保存されない。必ず .xlsm にすること。


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

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

Alt + F11 キーを押すとVBE(Visual Basic Editor)が開く。

一般的にはAlt + F11で開けるが、企業のセキュリティ設定でVBAが無効化されている場合は、IT部門に確認すること。

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

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

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

  1. 下の「コード(最小版)」をコピーして、コードウィンドウに貼り付ける
  2. コード内のファイルパス・フォルダパスを自分の環境に書き換える
  3. Alt + F8 を押す(または VBE上で F5
  4. マクロ名を選択して「実行」

コード(最小版)— Dir関数でファイル・フォルダの存在チェック

まずはこれだけで動く。Dir関数を使って、ファイルとフォルダの存在を確認する最小限のコード。

ファイルの存在チェック


Sub CheckFileExists()

    Dim filePath As String

    ' ★ ここを自分のファイルパスに書き換える
    filePath = "C:\Users\(ユーザー名)\Desktop\テストファイル.xlsx"

    ' 空パスのガード
    If filePath = "" Then
        MsgBox "ファイルパスが指定されていません。", vbExclamation
        Exit Sub
    End If

    ' --- ファイルの存在チェック ---
    ' Dir関数はファイルが存在すればファイル名を返し、存在しなければ空文字""を返す
    If Dir(filePath) <> "" Then
        MsgBox "ファイルが存在します:" & vbCrLf & filePath, vbInformation
    Else
        MsgBox "ファイルが見つかりません:" & vbCrLf & filePath, vbExclamation
    End If

End Sub

フォルダの存在チェック


Sub CheckFolderExists()

    Dim folderPath As String

    ' ★ ここを自分のフォルダパスに書き換える
    folderPath = "C:\Users\(ユーザー名)\Desktop\テストフォルダ"

    ' 空パスのガード
    If folderPath = "" Then
        MsgBox "フォルダパスが指定されていません。", vbExclamation
        Exit Sub
    End If

    ' --- フォルダの存在チェック(vbDirectoryが必須) ---
    ' vbDirectory を指定しないとフォルダを検出できない
    If Dir(folderPath, vbDirectory) <> "" Then
        MsgBox "フォルダが存在します:" & vbCrLf & folderPath, vbInformation
    Else
        MsgBox "フォルダが見つかりません:" & vbCrLf & folderPath, vbExclamation
    End If

End Sub

ポイント:

  • ファイルの存在チェック:Dir(filePath) <> "" — ファイルが存在すればファイル名が返り、存在しなければ空文字 "" が返る
  • フォルダの存在チェック:Dir(folderPath, vbDirectory) <> ""vbDirectory を指定しないとフォルダを検出できないので注意
  • vbDirectoryの注意:Dir(path, vbDirectory) は、同名のファイルが存在する場合もヒットする。フォルダであることを厳密に確認したい場合は、FSOの FolderExists を使うのが確実
  • フォルダパスの末尾に \ は付けても付けなくてもどちらでも動作する(Dir関数の場合)

応用:存在チェック→処理を分岐する基本パターン

実際の業務では、存在チェックの結果に応じて処理を分岐させることが多い。以下は「ファイルが存在すれば開く、存在しなければ新規作成する」パターン。


Sub OpenOrCreateFile()

    Dim filePath As String
    Dim wb As Workbook

    ' ★ ここを自分のファイルパスに書き換える
    filePath = "C:\Users\(ユーザー名)\Desktop\売上報告.xlsx"

    If Dir(filePath) <> "" Then
        ' --- ファイルが存在する → 開く ---
        Set wb = Workbooks.Open(filePath)
        MsgBox "既存ファイルを開きました。", vbInformation
    Else
        ' --- ファイルが存在しない → 新規作成して保存 ---
        Set wb = Workbooks.Add
        wb.SaveAs filePath
        MsgBox "新規ファイルを作成しました:" & vbCrLf & filePath, vbInformation
    End If

End Sub

このように If Dir(path) <> "" Then ... Else ... End If で分岐させるのが基本パターン。この考え方はファイルを開いて処理する場面([記事073(Excelファイルを自動で開いて処理して閉じる方法)])でも使える。


コード(実務版)— フォルダ確認→作成→ファイルコピー

実務では「コピー先フォルダがなければ作成し、ファイルをコピーする」というパターンが多い。以下はFSO(FileSystemObject)を使った実務版。


Sub CopyFileWithCheck()

    Dim fso As Object
    Dim srcFile As String    ' コピー元ファイル
    Dim dstFolder As String  ' コピー先フォルダ
    Dim dstFile As String    ' コピー先ファイルパス
    Dim ans As VbMsgBoxResult  ' 上書き確認の回答

    ' ★ ここを自分の環境に書き換える
    srcFile = "C:\Users\(ユーザー名)\Desktop\元データ\売上報告.xlsx"
    dstFolder = "C:\Users\(ユーザー名)\Desktop\バックアップ\202603"

    ' FileSystemObject を作成(参照設定不要)
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' --- 1. コピー元ファイルの存在チェック ---
    If Not fso.FileExists(srcFile) Then
        MsgBox "コピー元ファイルが見つかりません:" & vbCrLf & srcFile, vbExclamation
        ' エラーや中断時もCleanupに飛んでオブジェクトを解放する
        GoTo Cleanup
    End If

    ' --- 2. コピー先フォルダの存在チェック → なければ作成 ---
    '    ※ CreateFolder は1階層のみ作成可能。
    '      親フォルダが存在しない場合はエラーになる。
    '      深い階層の一括作成は記事029を参照。
    If Not fso.FolderExists(dstFolder) Then
        fso.CreateFolder dstFolder
        MsgBox "フォルダを新規作成しました:" & vbCrLf & dstFolder, vbInformation
    End If

    ' --- 3. コピー先ファイルパスを組み立て ---
    dstFile = dstFolder & "\" & fso.GetFileName(srcFile)

    ' --- 4. コピー先に同名ファイルがあるか確認 ---
    If fso.FileExists(dstFile) Then
        ans = MsgBox("コピー先に同名ファイルが既に存在します。上書きしますか?" & vbCrLf & _
                      dstFile, vbYesNo + vbQuestion)
        If ans = vbNo Then
            MsgBox "処理を中断しました。", vbInformation
            GoTo Cleanup
        End If
    End If

    ' --- 5. ファイルをコピー ---
    '    第3引数 True = 上書き許可(直前の確認でYesの場合のみここに到達)
    fso.CopyFile srcFile, dstFile, True

    MsgBox "ファイルをコピーしました。" & vbCrLf & _
           "コピー元:" & srcFile & vbCrLf & _
           "コピー先:" & dstFile, vbInformation

Cleanup:
    Set fso = Nothing

End Sub

ポイント:

  • fso.FileExists(path) / fso.FolderExists(path) で直感的に存在チェックできる
  • fso.CreateFolder でフォルダを作成。ただし 1階層のみ作成可能。親フォルダが存在しない場合はエラーになるので注意(深い階層の一括作成は[記事029(フォルダを自動作成して振り分ける方法)]を参照)
  • fso.CopyFile でファイルコピー(詳しくは[記事003(ファイルを別フォルダにコピー・移動)]を参照)
  • 同名ファイルの上書き確認を入れることで、意図しないデータ消失を防ぐ
  • CreateObject を使っているため、参照設定は不要。そのままコピペで動く

エラー処理(On Error)と組み合わせると、ネットワーク切断などの予期しないエラーにも対応できる。詳しくは[記事022(エラー処理で止まらないマクロを作る方法)]を参照。


Dir関数 vs FSO の使い分け

比較項目 Dir関数 FSO (FileSystemObject)
参照設定 不要(VBA標準) 不要(CreateObjectで使える)
ファイル存在チェック Dir(path) <> "" fso.FileExists(path)
フォルダ存在チェック Dir(path, vbDirectory) <> "" fso.FolderExists(path)
可読性 やや分かりにくい メソッド名が直感的
注意点 ループ中に別のDirを呼ぶと状態がリセットされる 特になし
推奨場面 単発のチェック、軽量な処理 複数のファイル操作を組み合わせる場合

迷ったらこの基準:

  • 「1つのファイルが存在するか確認するだけ」→ Dir関数で十分
  • 「存在チェック + コピー + フォルダ作成など複数操作」→ FSOがおすすめ

よくある落とし穴5選

# 症状 原因 対策
1 ファイルが存在するのに「存在しない」と判定される パスにタイプミスがある、または拡張子が違う(.xlsx と .xls など) エクスプローラーでパスをコピーして貼り付ける。拡張子まで含めたフルパスを指定する
2 フォルダの存在チェックでDir関数が常にTrueを返す Dir(path, vbDirectory) は同名のファイルもヒットする場合がある FSOの FolderExists を使うか、GetAttr で属性を追加確認する
3 「実行時エラー ’75’: パス名が無効です」が出る MkDirやCreateFolderで既に存在するフォルダを作成しようとした 作成前に必ず存在チェックを入れる。If Not fso.FolderExists(path) Then fso.CreateFolder path
4 「実行時エラー ’70’: 書き込みできません」が出る コピー先に読み取り専用の同名ファイルが既に存在する コピー前に存在チェック+上書き確認メッセージを表示する
5 Dir関数をループ中に入れ子で使うと結果がおかしくなる Dir関数は内部状態を保持するため、ループ内で別のDirを呼ぶと最初のDirの列挙がリセットされる ファイル一覧のループ中に別のDir呼び出しを避ける。または全面的にFSOを使う

FAQ

Q1: Dir関数とFSOのFileExistsはどちらを使うべき?

単純なチェック1回ならDir関数で十分。複数のファイル操作(コピー・移動・削除)を組み合わせるならFSOが便利。特にDir関数はループ中の入れ子呼び出しに注意が必要(落とし穴5参照)。

Q2: ネットワーク上の共有フォルダでも存在チェックできる?

一般的にはUNCパス(\\サーバー名\共有名\ファイル名)でも動作する。ただしアクセス権限がない場合やネットワーク切断時はエラーになる。[記事022(エラー処理で止まらないマクロを作る方法)]のOn Errorと組み合わせると安全。

Q3: ワイルドカード(*.xlsx)でDir関数を使うとどうなる?

Dir("C:\Data\*.xlsx") のように書くと、条件に合うファイルが1つでもあれば空文字以外が返る。「特定のファイルが存在するか」を確認したいときはワイルドカードを使わず、ファイル名をフルパスで指定すること。

Q4: 存在チェックとエラー処理(On Error)はどちらを使うべき?

基本は存在チェックで事前確認するのが推奨。On Errorは「ネットワーク切断」「権限不足」など予期しないエラーの保険として併用する。両方を組み合わせるのがベスト。詳しくは[記事022(エラー処理で止まらないマクロを作る方法)]を参照。

Q5: 深い階層のフォルダ(親フォルダも存在しない)を一括で作りたい

MkDirやFSO.CreateFolderは1階層ずつしか作成できない。深い階層を一括作成するには、パスを分割して上位フォルダから順に作成するか、[記事029(フォルダを自動作成して振り分ける方法)]を参照。


まとめ

この記事で、VBAでファイルやフォルダの存在を確認してから処理を分岐させる方法を学んだ。

  • 最小版:Dir関数で存在チェック。Dir(path) <> "" だけで判定できる
  • 実務版:FSOで存在チェック→フォルダ作成→ファイルコピーの一連の流れを自動化

存在チェックは、あらゆるファイル操作の「最初の一手」。[記事001(フォルダ内ファイル一覧を自動取得)]や[記事029(フォルダを自動作成して振り分ける方法)]と組み合わせれば、より実践的なマクロが作れる。

次にやりたくなること:

  • フォルダを自動作成してファイルを振り分けたい → [記事029(フォルダを自動作成して振り分ける方法)]
  • Excelファイルを自動で開いて処理したい → [記事073(Excelファイルを自動で開いて処理して閉じる方法)]
  • データの最終行を正確に取得したい → [記事032(データの最終行・最終列を正確に取得する方法)]

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

「複数フォルダの存在を一括チェックしたい」「存在しないファイルのリストをログに出力したい」「チェック結果をメールで通知したい」など、業務に合わせたカスタマイズが必要な場合は、ココナラで相談できます。

相談時に以下の情報があるとスムーズです:

  • Excel のバージョン / OS
  • チェック対象のファイル・フォルダの数(目安)
  • 存在しなかった場合にどう処理したいか(作成/スキップ/通知)
  • ネットワークドライブの有無

関連記事

コメント

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