日々の業務において、「特定のフォルダに保存されている数十個のExcelファイルやCSVファイルを一つずつ開き、必要なデータをコピーして、別の集計用ファイルに貼り付けて閉じる」という作業を繰り返していませんか。月末の売上集計や、各部署から集まったアンケート結果の統合など、ファイル数が多くなるほどこの手作業は膨大な時間を奪い、コピー漏れや貼り付け位置のズレといったヒューマンエラーを引き起こす最大の原因となります。 Excel VBA(マクロ)を活用すれば、指定したフォルダ内にあるすべてのファイルを瞬時に自動取得し、ファイル名の一覧を作成したり、すべてのデータを1つのシートに統合(結合)したりする作業を、ボタン一つで、わずか数秒で完結させることができます。 この記事では、VBAを使ってフォルダ内の複数ファイル(ExcelおよびCSV)を自動取得・一覧化・結合するための具体的なコードと、その仕組みを初心者にも分かりやすく詳細に解説します。基本となる「Dir関数」の使い方から、サブフォルダまで検索できる「FileSystemObject(FSO)」の応用、そして実務で必ず直面する「見出し行の重複防止」や「画面のちらつき防止」といったプロのテクニックまで、そのままコピペして使える完成版コードとともに完全網羅しています。

目次

1. フォルダ内のファイルを取得する2つのアプローチ(Dir関数とFSO)

VBAでフォルダの中にあるファイルを探索・取得するためには、大きく分けて2つの手法が存在します。目的やフォルダの階層構造によって使い分けるのが一般的です。 ① Dir(ディル)関数を使用する方法 VBAに標準で組み込まれている関数です。コードの記述量が少なく、動作も非常に軽量です。「指定した1つのフォルダ内にあるファイル」だけを順番に取得したい場合は、このDir関数を使うのが最も簡単でオーソドックスな手法です。ただし、フォルダの中にある「さらにその下のフォルダ(サブフォルダ)」の中身まで自動で探りにいくことはできません。 ② FileSystemObject(FSO)を使用する方法 Windowsのファイルシステムを操作するための強力なオブジェクトです。Dir関数よりも高度な操作が可能で、ファイルの作成日時やサイズを取得したり、サブフォルダの中まで再帰的(次から次へと深い階層へ潜っていく)に検索したりすることができます。ファイル管理システムを作るような複雑な処理に向いています。 本記事では、まずはシンプルで分かりやすい「Dir関数」を使った方法を基本とし、より高度な要件向けに「FSO」も併せて解説します。

2. 【基本一覧化】Dir関数でファイル名一覧を自動作成するマクロ

特定のフォルダにどんなファイルが入っているか、目次(インデックス)としてExcelシートに一覧化したい場合に使えるマクロです。後述する「結合マクロ」の基礎となる「ファイルを順番に見つけるループ処理」を理解するのに最適です。 以下のコードは、ユーザーが指定したフォルダ内にあるすべてのファイルの「ファイル名」と「フルパス」を、現在開いているシートに書き出します。

Sub GetFileList_Dir()
    Dim folderPath As String
    Dim fileName As String
    Dim rowNum As Long

    ' 1. ユーザーにフォルダを選択させるダイアログを表示
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "ファイル一覧を取得するフォルダを選択してください"
        If .Show = -1 Then
            ' 選択されたフォルダパスの末尾に「\」を付与
            folderPath = .SelectedItems(1) & "\"
        Else
            MsgBox "キャンセルされました。", vbExclamation
            Exit Sub
        End If
    End With

    ' 2. シートの初期化と見出しの作成
    ActiveSheet.Cells.Clear
    Range("A1").Value = "ファイル名"
    Range("B1").Value = "ファイルパス"
    rowNum = 2 ' データ入力開始行

    ' 3. Dir関数でフォルダ内の最初のファイルを取得
    ' ("*.xlsx"のように指定するとExcelファイルだけを取得可能)
    fileName = Dir(folderPath & "*.*")

    ' 4. ファイルが見つからなくなる(空白になる)までループを繰り返す
    Do While fileName <> ""
        ' シートに書き出し
        Cells(rowNum, 1).Value = fileName
        Cells(rowNum, 2).Value = folderPath & fileName

        ' 次の行へ移動
        rowNum = rowNum + 1

        ' 次のファイルを取得(引数なしのDir()で次のファイルが呼ばれる)
        fileName = Dir()
    Loop

    ' 列幅の自動調整
    Columns("A:B").AutoFit

    MsgBox "ファイル一覧の取得が完了しました。", vbInformation
End Sub

【コードのポイント】Dir(folderPath & "*.*") によって最初のファイル名を掴み、その後ループの中で fileName = Dir() と引数を空にして呼び出すことで、フォルダ内の次のファイル、また次のファイル……と順番に名前を取得していくのがDir関数の特徴です。すべてのファイルを読み終えると空白(””)を返すため、ループが終了します。

3. 【応用一覧化】FSOでサブフォルダ内のファイルも含めて一覧化するマクロ

フォルダの中にさらに「2024年」「2025年」といったサブフォルダがあり、その奥底にあるファイルもすべて見つけ出して一覧化したい場合は、FSO(FileSystemObject)と「再帰呼び出し」というプログラミング手法を使用します。

' グローバル変数(再帰処理で行番号を保持するため)
Dim outputRow As Long

Sub GetFileList_FSO_Main()
    Dim fso As Object
    Dim folderPath As String

    ' フォルダ選択ダイアログ
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show = -1 Then
            folderPath = .SelectedItems(1)
        Else
            Exit Sub
        End If
    End With

    ' シート準備
    ActiveSheet.Cells.Clear
    Range("A1").Value = "ファイル名"
    Range("B1").Value = "ファイルパス"
    outputRow = 2

    ' FSOのインスタンス生成
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' サブフォルダも含めて検索するプロシージャを呼び出し
    Call SearchFolders(fso.GetFolder(folderPath))

    Set fso = Nothing
    Columns("A:B").AutoFit
    MsgBox "サブフォルダを含む一覧取得が完了しました。", vbInformation
End Sub

' 再帰呼び出し用の別プロシージャ
Sub SearchFolders(ByVal targetFolder As Object)
    Dim fileObj As Object
    Dim subFolder As Object

    ' 1. 現在のフォルダ内のファイルをシートに書き出す
    For Each fileObj In targetFolder.Files
        Cells(outputRow, 1).Value = fileObj.Name
        Cells(outputRow, 2).Value = fileObj.Path
        outputRow = outputRow + 1
    Next fileObj

    ' 2. 現在のフォルダ内にサブフォルダがあれば、このプロシージャ自身を再度呼び出す(再帰)
    For Each subFolder In targetFolder.SubFolders
        Call SearchFolders(subFolder)
    Next subFolder
End Sub

このマクロを実行すると、親フォルダを指定するだけで、その下に広がるツリー構造をすべて探索し、あらゆる階層に埋もれたファイルをリストアップしてくれます。

4. フォルダ内の複数Excelファイルを1つのシートに結合するマクロ

ここからが実務における本命です。各支店から送られてきた売上データなど、フォーマットが統一された複数のExcelファイル(.xlsxなど)を、1つのマスターシートに縦に結合(統合)していくマクロを作成します。

結合マクロの基本的なロジック

プログラムが行っている作業は、人間が行う手作業と全く同じです。 1. 結合先の「マスターファイル」を用意する。 2. Dir関数でフォルダ内のデータファイルを1つ見つける。 3. そのデータファイルを開く。 4. データの範囲をコピーする。 5. マスターファイルの「データが入っている一番下の行の、さらに1つ下の行」に貼り付ける。 6. データファイルを閉じる。 7. 次のファイルを探し、繰り返し処理を行う。

見出し(ヘッダー)行が重複しないようにする工夫

単純にすべてのファイルの「1行目から最終行まで」をコピーして貼り付けてしまうと、結合結果のシート内に「氏名」「売上金額」といった見出し行が何度も繰り返し登場してしまい、後からピボットテーブルなどで集計できなくなってしまいます。 これを防ぐため、コード内に「1つ目のファイルを貼り付ける時だけは1行目(見出し)からコピーし、2つ目以降のファイルは2行目(データ部分)からコピーする」というIf分岐のロジックを組み込むのがプロの鉄則です。

【完成版コード】Excelファイル結合マクロ

以下のコードをコピーして実行してください。処理を高速化するための設定も組み込んでいます。

Sub CombineExcelFiles()
    Dim folderPath As String
    Dim fileName As String
    Dim wsMaster As Worksheet
    Dim wbData As Workbook
    Dim wsData As Worksheet
    Dim lastRowData As Long
    Dim pasteRow As Long

    ' 1. ダイアログでデータが入っているフォルダを選択
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "結合するExcelファイルが入ったフォルダを選択してください"
        If .Show = -1 Then
            folderPath = .SelectedItems(1) & "\"
        Else
            Exit Sub
        End If
    End With

    ' 2. 結合先のシート(このマクロが書かれているファイルの1番目のシート)を設定
    Set wsMaster = ThisWorkbook.Worksheets(1)
    wsMaster.Cells.Clear ' 既存のデータをクリア
    pasteRow = 1 ' 最初の貼り付け先は1行目

    ' 3. 画面更新と警告をオフにして高速化
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Application.EnableEvents = False

    ' 4. Dir関数でフォルダ内のExcelファイル(.xls, .xlsxなど)を取得
    fileName = Dir(folderPath & "*.xls*")

    ' 5. ファイルが見つかる限りループ
    Do While fileName <> ""
        ' 自分自身(マクロファイル)を開こうとした場合はスキップ
        If fileName <> ThisWorkbook.Name Then

            ' データファイルを開く(読み取り専用で開くことで安全性を高める)
            Set wbData = Workbooks.Open(folderPath & fileName, ReadOnly:=True)
            Set wsData = wbData.Worksheets(1) ' 1番目のシートを対象

            ' データファイルの最終行を取得(A列を基準)
            lastRowData = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row

            ' データが存在する場合のみコピー処理を行う
            If lastRowData >= 1 Then
                If pasteRow = 1 Then
                    ' 最初のファイル:1行目(見出し)から最終行までコピー
                    wsData.Range("A1", wsData.Cells(lastRowData, wsData.Columns.Count).End(xlToLeft)).Copy
                    wsMaster.Cells(pasteRow, 1).PasteSpecial Paste:=xlPasteValues
                Else
                    ' 2つ目以降のファイル:2行目(データのみ)から最終行までコピー
                    If lastRowData >= 2 Then
                        wsData.Range("A2", wsData.Cells(lastRowData, wsData.Columns.Count).End(xlToLeft)).Copy
                        wsMaster.Cells(pasteRow, 1).PasteSpecial Paste:=xlPasteValues
                    End If
                End If

                ' 次の貼り付け先行を更新(マスターシートの最終行+1)
                pasteRow = wsMaster.Cells(wsMaster.Rows.Count, "A").End(xlUp).Row + 1
            End If

            ' データファイルを保存せずに閉じる
            wbData.Close SaveChanges:=False
        End If

        ' 次のファイルを取得
        fileName = Dir()
    Loop

    ' 6. 設定を元に戻す
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    Application.EnableEvents = True

    ' クリップボードをクリアし、A1セルを選択
    Application.CutCopyMode = False
    wsMaster.Range("A1").Select

    MsgBox "すべてのExcelファイルの結合が完了しました。", vbInformation
End Sub

このマクロは、結合先のシートに「値のみ貼り付け(PasteSpecial Paste:=xlPasteValues)」を行う仕様にしています。これにより、各ファイルに設定されていた罫線や背景色、計算式などが持ち込まれてファイルサイズが肥大化・エラーを起こすのを防ぎ、純粋なデータベースとして統合することができます。

5. 複数CSVファイルを高速に結合するマクロと注意点

システムからダウンロードした大量のデータなど、対象が「CSVファイル」である場合も結合のニーズは非常に高いです。

CSVを扱う際の「ゼロ落ち」「文字化け」問題

CSVファイルをVBAで単純に Workbooks.Open で開くと、Excelの自動変換機能が働き、「00123」という社員番号が「123」になってしまう(ゼロ落ち)、あるいは「1-1」という品番が「1月1日」という日付に変換されてしまうといった致命的なデータ破壊が起こる可能性があります。 これを完全に防ぐには、CSVを開く際に QueryTable というデータ取り込み機能を使うか、あるいはファイルそのものを開かずに「テキストストリーム」として読み込んで文字列処理を行う必要がありますが、コードが非常に複雑になります。 よりシンプルで高速な代替案として、コマンドプロンプトの機能(DOSコマンド)をVBAから呼び出して、文字データとしてガッチャンコと結合してしまうという裏ワザテクニックを紹介します。

【完成版コード】CSVファイル結合マクロ(コマンドプロンプト連携)

以下のコードは、フォルダ内にある複数のCSVファイルを、VBA経由でWindowsのコマンドを使って「1つの結合されたCSVファイル」として一瞬で生成します。ファイルを開かないため、数千ファイルあっても数秒で終わる爆速仕様です。

Sub CombineCSVFiles_Fast()
    Dim folderPath As String
    Dim outputFile As String
    Dim commandStr As String
    Dim wsh As Object

    ' ダイアログでCSVが入っているフォルダを選択
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "結合するCSVファイルが入ったフォルダを選択してください"
        If .Show = -1 Then
            folderPath = .SelectedItems(1) & "\"
        Else
            Exit Sub
        End If
    End With

    ' 結合後の出力ファイル名(同じフォルダに「結合結果.csv」として作成)
    outputFile = folderPath & "結合結果_" & Format(Now, "yyyymmdd_hhmmss") & ".csv"

    ' WScript.Shellオブジェクトの作成
    Set wsh = CreateObject("WScript.Shell")

    ' DOSコマンドの「copy」を使って、フォルダ内の全CSVを1つに結合する命令を作成
    ' 例: cmd.exe /c copy /Y "C:\Test\*.csv" "C:\Test\結合結果.csv"
    commandStr = "cmd.exe /c copy /Y """ & folderPath & "*.csv"" """ & outputFile & """"

    ' コマンドを実行(0は非表示で実行、Trueは処理完了まで待機)
    wsh.Run commandStr, 0, True

    Set wsh = Nothing

    MsgBox "CSVファイルの結合が完了しました。" & vbCrLf & _
           "出力先: " & outputFile, vbInformation
End Sub

※この手法の唯一の弱点は、前述の「2つ目以降のファイルの見出し行を消す」という高度な処理ができない点です。結合後に生成されたCSVを開き、Excelのフィルター機能などで不要な「見出し行」を一括削除する等の事後処理を行ってください。

6. 実務で役立つエラー回避と高速化の必須テクニック

紹介したコードにも組み込んでいますが、複数ファイルを扱うマクロを安定して稼働させるためのVBAの作法を解説します。

画面の更新と警告メッセージをオフにする

何十個ものファイルを開いて閉じてを繰り返すと、画面がチカチカと点滅し、処理に膨大な時間がかかります。さらに、ファイルにクリップボードの情報が残っていると、閉じる際に「クリップボードに大きな情報があります。保持しますか?」という警告ポップアップが出て、人間が「いいえ」を押すまでマクロがストップしてしまいます。 これらを防ぐ魔法のコードが以下の3行です。複数ファイルを処理するループの直前に書き、処理が終わったら必ず True に戻します。

Application.ScreenUpdating = False ' 画面の点滅を停止(超高速化)
Application.DisplayAlerts = False  ' 「保存しますか?」などの警告を無視して強制処理
Application.EnableEvents = False   ' 開いたファイルに仕込まれているマクロの自動実行を防止

ユーザーにフォルダをダイアログで選択させる

マクロのコード内に folderPath = "C:\Users\Yamada\Desktop\集計" のようにパスを直接書いてしまうと、担当者が変わったりフォルダ名が変わったりした途端にエラーになります。 Application.FileDialog(msoFileDialogFolderPicker) を使うことで、Windowsの一般的な「フォルダ選択画面」を呼び出すことができ、誰でも直感的に操作できるプロフェッショナルなツールに仕上がります。

7. まとめ

VBAを利用してフォルダ内の複数ファイルを自動取得し、結合するマクロは、Excel業務の自動化において「最も費用対効果が高い(時間を削減できる)」処理の一つです。 ファイルのリストアップだけなら「Dir関数」によるシンプルなループで完結し、サブフォルダまで深く潜りたい場合は「FSO(FileSystemObject)」の再帰処理を活用します。 そして、複数のExcelファイルを統合する場合は、単にコピペを繰り返すだけでなく、「マスターシートの最終行の次を常に計算して貼り付ける」「見出し行が重複しないように条件分岐する」「画面更新を止めて処理を高速化し、不要な警告でマクロを止めない」といったエラー回避の工夫を盛り込むことが成功の秘訣です。 CSVに関しては、データの性質(ゼロ落ちなど)に注意を払い、要件に応じてVBAで開くか、コマンド連携で一括結合するかを選択してください。 本記事で提供した完成版コードをあなたの実務環境に合わせて少しカスタマイズするだけで、これまで毎月数時間かかっていた面倒なコピペ作業が、コーヒーを一口飲む間に終わるようになります。ぜひ導入して、圧倒的な業務効率化を体感してください。