「毎月、報告書を年月フォルダに手で振り分けている」「フォルダがあるか目視で確認してからコピーしている」
ファイル整理は地味ですが、毎月くり返すと意外と時間を取られますよね。フォルダを作り、ファイルを探し、コピーして、また確認して。この一連の作業こそ、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:Temp2026 4)を一度に作りたい場合は、親から順に作る必要があります。C:Temp→C:Temp2026→C:Temp2026 4の順です。後ほどの実務パターン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) で元ファイルの名前だけを取り出し、コピー先のパスを組み立てています。先に FileExists と FolderExists でチェックしているので、途中でエラーが出ません。Exit Sub で安全に中断する書き方も覚えておくと便利です。
FileSystemObjectでよくあるエラーと対処法
| エラー | 原因 | 対処法 |
|---|---|---|
| 実行時エラー ’58’:既に存在します | 既存フォルダを CreateFolder した | FolderExists で事前チェックしてから作る |
| 実行時エラー ’76’:パスが見つかりません | 親フォルダがない、パスのタイプミス | 親フォルダから順に作る。パスを見直す |
| 実行時エラー ’53’:ファイルが見つかりません | GetFile / CopyFile で元ファイルがない | FileExists で事前チェックする |
| 実行時エラー ’70’:書き込みできません | ファイルが他で開かれている、読み取り専用 | ファイルを閉じる。DeleteFile は第2引数に True |
| ユーザー定義型は定義されていません | 参照設定なしで As Scripting.FileSystemObject | 参照設定する。または CreateObject と As 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学習ロードマップで全体の学習ステップを確認してみましょう。
