VBA FileSystemObjectの使い方|フォルダ作成・ファイル一覧取得・存在確認を自動化

スポンサーリンク

「毎月、報告書を年月フォルダに手で振り分けている」「フォルダがあるか目視で確認してからコピーしている」

ファイル整理は地味ですが、毎月くり返すと意外と時間を取られますよね。フォルダを作り、ファイルを探し、コピーして、また確認して。この一連の作業こそ、VBAで自動化したいポイントです。

そこで活躍するのが FileSystemObject(FSO) です。この記事では、FSOの準備から、フォルダの自動作成・ファイルの存在確認・一覧取得・コピーまでを解説します。月次フォルダの自動仕分けなど、コピペで使える実務コードも紹介していきますね。

VBA FileSystemObject(FSO)とは?

FileSystemObjectは、Windowsのファイル操作をVBAから命令できるオブジェクトです。「FSO」と略されます。

イメージは「ファイル係の司令塔」です。普段あなたがエクスプローラーで手動でやっている操作を、コードで指示できます。

具体的には、次のような操作ができます。

  • フォルダを作る・あるか調べる
  • ファイルがあるか調べる
  • フォルダの中のファイル一覧を取り出す
  • ファイルをコピー・移動・削除する
  • ファイル名や拡張子、更新日時を取り出す

FSOは Microsoft Scripting Runtime という部品に含まれています。Windowsに標準で入っているので、特別なインストールは不要です。

NOTE

VBE(Visual Basic Editor)は Alt + F11 で起動します。リボンから開く場合は「開発」タブ →「Visual Basic」を選びます。「開発」タブが表示されていないときは、「ファイル」→「オプション」→「リボンのユーザー設定」で「開発」にチェックを入れてください。VBEが開いたら「挿入」→「標準モジュール」でコードを書く場所を作ります。画面構成がわからない方は、VBE画面の見方の記事も参考にしてみてください。

FileSystemObjectを使う準備(参照設定とCreateObject)

FSOを使うには、最初にオブジェクトを生成する必要があります。生成方法は2通りあります。

方法1: 参照設定する(事前バインディング)

VBEのメニューから「ツール」→「参照設定」を開きます。一覧から Microsoft Scripting Runtime にチェックを入れます。これで準備完了です。

Sub UseEarlyBinding()
    Dim fso As Scripting.FileSystemObject 'ファイル操作オブジェクト
    Set fso = New Scripting.FileSystemObject

    MsgBox fso.FolderExists("C:Temp") 'C:Tempがあるか判定
End Sub

参照設定すると、入力中に候補が出る入力補完(IntelliSense)が効きます。コードが書きやすくなるので、自分のPCで使う場合はこちらがおすすめです。

方法2: CreateObjectで生成する(実行時バインディング)

参照設定をせずに、コード内でオブジェクトを直接生成する方法です。

Sub UseLateBinding()
    Dim fso As Object 'ファイル操作オブジェクト
    Set fso = CreateObject("Scripting.FileSystemObject")

    MsgBox fso.FolderExists("C:Temp") 'C:Tempがあるか判定
End Sub

CreateObjectは参照設定が不要です。そのため、ファイルを他の人に配布する場合に向いています。環境による設定の違いを気にしなくて済むからです。

TIP

迷ったら CreateObject を選んでおくと安全です。参照設定はファイルごとに必要で、配布先で外れていると動かなくなります。本記事のコードはすべてCreateObjectで統一しています。

FileSystemObjectの基本メソッド一覧(フォルダ・ファイル操作)

FSOでよく使うメソッドとプロパティを、まず一覧で見ておきましょう。後のセクションで1つずつコード付きで解説します。

フォルダ操作

要素役割
CreateFolder(パス)フォルダを新規作成(既存だとエラー・1階層のみ)
FolderExists(パス)フォルダの有無を True / False で返す
GetFolder(パス)Folderオブジェクトを取得(存在しないとエラー)
DeleteFolder(パス)フォルダを削除
Folder.SubFoldersサブフォルダのコレクション

ファイル操作

要素役割
FileExists(パス)ファイルの有無を True / False で返す
GetFile(パス)Fileオブジェクトを取得(存在しないとエラー)
Folder.Filesフォルダ内ファイルのコレクション
CopyFile(元, 先)ファイルをコピー(既定で上書き)
MoveFile(元, 先)ファイルを移動
DeleteFile(パス)ファイルを削除

パス・名前の操作

要素役割
GetFileName(パス)パスからファイル名を取り出す
GetBaseName(パス)拡張子を除いたファイル名
GetExtensionName(パス)拡張子を取り出す(例: xlsx)
GetParentFolderName(パス)親フォルダのパス
BuildPath(パス, 名前)パスと名前を区切り文字込みで連結

Fileオブジェクトの主なプロパティ

プロパティ取得できる情報
Nameファイル名
Pathフルパス
Sizeサイズ(バイト)
DateLastModified最終更新日時
Typeファイルの種類

フォルダの存在確認と自動作成(FolderExists / CreateFolder)

まずはフォルダ操作からです。実務でいちばん多いのが「フォルダがなければ作る」という処理です。

FolderExists:フォルダがあるか調べる

FolderExists は、指定したフォルダがあるかを True / False で返します。

Dim fso As Object 'ファイル操作オブジェクト
Set fso = CreateObject("Scripting.FileSystemObject")

If fso.FolderExists("C:Temp2026") Then
    MsgBox "フォルダがあります"
Else
    MsgBox "フォルダがありません"
End If

CreateFolder:フォルダを作る

CreateFolder は、新しいフォルダを作ります。

fso.CreateFolder "C:Temp2026" 'フォルダを新規作成

ここで注意点が2つあります。まず、既に同じフォルダがあるとエラーになります。次に、作れるのは1階層だけです。たとえば C:Temp がないのに C:Temp2026 を一度に作ろうとするとエラーになります。

そこで実務では、FolderExists で確認してから CreateFolder する形が定番です。

Dim fso As Object 'ファイル操作オブジェクト
Dim targetPath As String '作りたいフォルダのパス
Set fso = CreateObject("Scripting.FileSystemObject")
targetPath = "C:Temp2026"

'--- フォルダがなければ作る ---
If Not fso.FolderExists(targetPath) Then
    fso.CreateFolder targetPath
    MsgBox "フォルダを作成しました"
Else
    MsgBox "フォルダは既にあります"
End If

If Not fso.FolderExists(...) で「なければ」を判定しています。これでエラーを防ぎながら安全にフォルダを用意できます。条件分岐の書き方はIf文の使い方をご覧ください。

NOTE

多階層のフォルダ(例: C:Temp20264)を一度に作りたい場合は、親から順に作る必要があります。C:TempC:Temp2026C:Temp20264 の順です。後ほどの実務パターン1で、この処理を関数にまとめた例を紹介します。

ファイルの存在確認・一覧取得・コピー削除(FileExists / GetFolder / CopyFile)

続いてファイル操作です。「ファイルがあるか確認する」「フォルダ内の一覧を取る」「コピーする」の3つを押さえれば、実務はほぼカバーできます。

FileExists:ファイルがあるか調べる

FileExists は、指定したファイルがあるかを True / False で返します。

If fso.FileExists("C:Tempreport.xlsx") Then
    MsgBox "ファイルがあります"
Else
    MsgBox "ファイルがありません"
End If

上書き保存の前や、コピーの前に「すでにあるか」を確認するときに使います。

GetFolderとFiles:フォルダ内のファイル一覧を取る

フォルダ内のファイルを1つずつ処理したいとします。このときは GetFolder でフォルダを取得し、Files コレクションを For Each で回します。

Sub ListFiles()
    Dim fso As Object 'ファイル操作オブジェクト
    Dim fol As Object '対象フォルダ
    Dim f As Object '取り出す1ファイル
    Dim msg As String '一覧の文字列

    Set fso = CreateObject("Scripting.FileSystemObject")
    Set fol = fso.GetFolder("C:Temp") '対象フォルダを取得

    '--- フォルダ内のファイル名を1つずつ集める ---
    For Each f In fol.Files
        msg = msg & f.Name & vbCrLf
    Next f

    MsgBox msg
End Sub

For Each f In fol.Files で、フォルダの中のファイルを1つずつ取り出しています。f.Name でファイル名が取れます。ループの基本はFor Eachの使い方も参考にしてください。

拡張子で絞り込む

一覧の中から「Excelファイルだけ」を選びたいときは、GetExtensionName で拡張子を調べます。

For Each f In fol.Files
    If fso.GetExtensionName(f.Name) = "xlsx" Then
        msg = msg & f.Name & vbCrLf '拡張子がxlsxのものだけ集める
    End If
Next f

GetExtensionName は拡張子だけを返します。ドット(.)は含まないので、"xlsx" のように比較します。

CopyFile・MoveFile・DeleteFile:コピー・移動・削除

ファイルのコピー・移動・削除は、それぞれ1行で書けます。

fso.CopyFile "C:Tempreport.xlsx", "C:Backupreport.xlsx" 'コピー
fso.MoveFile "C:Tempold.xlsx", "C:Archiveold.xlsx" '移動
fso.DeleteFile "C:Tempunused.xlsx" '削除

NOTE

CopyFile は、コピー先に同じ名前のファイルがあると既定で上書きします。上書きしたくない場合は、第3引数に False を指定します(fso.CopyFile 元, 先, False)。この場合、同名ファイルがあるとエラーになります。コピー前に FileExists で確認すると、より安全です。

【実務】FileSystemObjectの活用コード3選

ここからは、実務でそのまま使えるパターンを3つ紹介します。どれもコピペして動かせるコードです。

パターン1: 月次報告書を年月フォルダに自動仕分け

C:報告書2026-04_営業報告.xlsx のようなファイルがあるとします。ファイル名の先頭から年月フォルダ(C:報告書2026-04)を作り、そこへ移動するコードです。

Sub SortReportsByMonth()
    Dim fso As Object 'ファイル操作オブジェクト
    Dim fol As Object '元フォルダ
    Dim f As Object '処理するファイル
    Dim baseFol As String '振り分け元のパス
    Dim ym As String '年月(フォルダ名)
    Dim destFol As String '移動先フォルダのパス

    Set fso = CreateObject("Scripting.FileSystemObject")
    baseFol = "C:報告書"
    Set fol = fso.GetFolder(baseFol)

    '--- ファイルを1つずつ確認して年月フォルダに移動する ---
    For Each f In fol.Files
        ym = Left(f.Name, 7) 'ファイル名先頭の"2026-04"を取り出す
        destFol = baseFol & "" & ym

        '--- 年月フォルダがなければ作る ---
        If Not fso.FolderExists(destFol) Then
            fso.CreateFolder destFol
        End If

        fso.MoveFile f.Path, destFol & "" & f.Name '移動
    Next f

    MsgBox "仕分けが完了しました"
End Sub

ポイントは2つです。Left(f.Name, 7) でファイル名の先頭7文字(2026-04)を取り出してフォルダ名にしています。そして移動前に FolderExists で確認し、なければ CreateFolder で作っています。これで「フォルダがない」エラーを防げます。

TIP

ファイル名のルールに合わせて Left(f.Name, 7) の文字数を変えてください。2026年04月 のような形式なら、文字数を調整するか、Mid 関数で必要な部分を切り出します。

パターン2: 指定フォルダ内のExcelファイルを一括処理

C:データ フォルダのExcelファイルを順番に開くコードです。A1セルにファイル名を書き込み、保存して閉じます。複数ファイルへの定型処理の土台になります。

Sub ProcessAllExcelFiles()
    Dim fso As Object 'ファイル操作オブジェクト
    Dim fol As Object '対象フォルダ
    Dim f As Object '処理するファイル
    Dim wb As Workbook '開いたブック

    Set fso = CreateObject("Scripting.FileSystemObject")
    Set fol = fso.GetFolder("C:データ")

    Application.ScreenUpdating = False '画面更新を止めて高速化

    '--- フォルダ内のxlsxファイルを順に開いて処理する ---
    For Each f In fol.Files
        If fso.GetExtensionName(f.Name) = "xlsx" Then
            Set wb = Workbooks.Open(f.Path) 'ファイルを開く
            wb.Worksheets(1).Range("A1").Value = f.Name 'A1に処理を書き込む
            wb.Close SaveChanges:=True '保存して閉じる
        End If
    Next f

    Application.ScreenUpdating = True '画面更新を戻す
    MsgBox "一括処理が完了しました"
End Sub

fso.GetExtensionName(f.Name) = "xlsx" でExcelファイルだけに絞っています。Workbooks.Open で開いたブックは、処理後に必ず Close で閉じます。セルの操作はRangeの使い方も参考にしてください。

NOTE

一括処理では、自分自身(マクロを書いたブック)を開きにいかないよう注意してください。マクロブックを処理対象フォルダの外に置くのが安全です。同じフォルダに置く場合は、If f.Name <> ThisWorkbook.Name Then で自分を除外します。

パターン3: 存在確認してから安全にバックアップする

ファイルをバックアップフォルダにコピーするコードです。元ファイルの有無とバックアップ先フォルダの有無を両方確認してから実行します。

Sub SafeBackup()
    Dim fso As Object 'ファイル操作オブジェクト
    Dim srcFile As String 'コピー元ファイル
    Dim destFol As String 'バックアップ先フォルダ

    Set fso = CreateObject("Scripting.FileSystemObject")
    srcFile = "C:Tempreport.xlsx"
    destFol = "C:Backup"

    '--- 元ファイルがなければ中止する ---
    If Not fso.FileExists(srcFile) Then
        MsgBox "コピー元のファイルがありません"
        Exit Sub
    End If

    '--- バックアップ先フォルダがなければ作る ---
    If Not fso.FolderExists(destFol) Then
        fso.CreateFolder destFol
    End If

    fso.CopyFile srcFile, destFol & "" & fso.GetFileName(srcFile) 'コピー実行
    MsgBox "バックアップが完了しました"
End Sub

fso.GetFileName(srcFile) で元ファイルの名前だけを取り出し、コピー先のパスを組み立てています。先に FileExistsFolderExists でチェックしているので、途中でエラーが出ません。Exit Sub で安全に中断する書き方も覚えておくと便利です。

FileSystemObjectでよくあるエラーと対処法

エラー原因対処法
実行時エラー ’58’:既に存在します既存フォルダを CreateFolder したFolderExists で事前チェックしてから作る
実行時エラー ’76’:パスが見つかりません親フォルダがない、パスのタイプミス親フォルダから順に作る。パスを見直す
実行時エラー ’53’:ファイルが見つかりませんGetFile / CopyFile で元ファイルがないFileExists で事前チェックする
実行時エラー ’70’:書き込みできませんファイルが他で開かれている、読み取り専用ファイルを閉じる。DeleteFile は第2引数に True
ユーザー定義型は定義されていません参照設定なしで As Scripting.FileSystemObject参照設定する。または CreateObjectAs Object に変える
パスがつながらない末尾の を付け忘れた(C:datafile.xlsxパスとファイル名を でつなぐ。BuildPath を使う

NOTE

FSOを使うマクロは、必ず マクロ有効ブック(.xlsm) で保存してください。通常の .xlsx で保存すると、マクロが消えてしまいます。ファイル形式の違いは.xlsxと.xlsmの違いで解説しています。

Dir関数との使い分け

ファイル操作には、FSO以外に Dir関数 という方法もあります。VBA組み込みの関数で、参照設定なしで使えます。

両者の違いを整理しておきましょう。

比較項目Dir関数FileSystemObject
準備不要(組み込み)参照設定 or CreateObject
速度速い・軽いやや重い
存在確認できる(戻り値が空かで判定)FileExists / FolderExists で明快
一覧取得できる(書き方にクセあり)Files / SubFolders で直感的
サブフォルダ再帰書きにくい(状態が壊れやすい)書きやすい
ファイル情報取れないサイズ・更新日時などが取れる
可読性やや低い高い

使い分けの目安

  • 単純な存在確認・1フォルダの列挙だけ → Dir関数でも十分
  • サブフォルダまで再帰的に探す・ファイル情報を取る・読みやすさ重視 → FSO

TIP

Dir関数は、ループの途中で別のDir呼び出しを挟むと検索状態が壊れます。一方FSOは Files コレクションを For Each で回すだけなので、こうした落とし穴がありません。複雑な処理ほどFSOが安全です。

まとめ

VBA FileSystemObjectは「Windowsのファイル操作をVBAから命令できる」オブジェクトです。

  • 準備は CreateObject(“Scripting.FileSystemObject”) が配布向きで安全
  • フォルダは FolderExists で確認してから CreateFolder で作る(既存だとエラー・1階層のみ)
  • ファイルは FileExists で確認、GetFolder + Files で一覧取得、CopyFile / MoveFile / DeleteFile で操作
  • 拡張子の絞り込みは GetExtensionName が便利
  • 単純な処理は Dir関数、複雑な処理や再帰探索は FSO と使い分ける

まずは「フォルダがなければ作る」のコードをVBEに貼り付けて、動きを確かめてみてください。月次の手作業がボタン1つに変わると、ファイル整理がぐっと楽になりますよ。

ファイル操作を覚えたら、次はVBA学習ロードマップで全体の学習ステップを確認してみましょう。

関連記事

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