VBAで特定フォルダ内のExcelファイルを一括読み込む方法|Dir関数・Workbooks.Open・データ転記の実装

VBAで特定フォルダ内のExcelファイルを一括読み込みするには、Dir 関数でファイルを順に取得し、Workbooks.Open で開いてデータを転記するループを作るだけです。毎月届く売上データや支店レポートなど、同じ形式のファイルを手作業で開いていた業務をワンクリックで自動化できます。

この記事では、次の内容を順番に解説します。

  • フォルダ内のExcelを一括で読み込む基本コード
  • フォルダをダイアログで選択できるようにする方法
  • 読み込んだデータに出所(ファイル名・シート名)を記録する方法
  • エラーが起きたファイルをスキップして続ける方法

フォルダ内のExcelを一括読み込みするには?

Dir(フォルダパス & "*.xls*") でフォルダ内のExcelファイルを1つずつ取得し、Do While〜Loop でループして処理します。

Sub ImportExcelFiles()

    Dim fPath    As String
    Dim fName    As String
    Dim wb       As Workbook
    Dim wsSrc    As Worksheet
    Dim wsDest   As Worksheet
    Dim lastRow  As Long
    Dim pasteRow As Long

    '集計先シートを指定
    Set wsDest = ThisWorkbook.Sheets("集計")
    pasteRow   = 2   '2行目から書き込む(1行目は見出し)

    '読み込み対象のフォルダパス(末尾は¥で終わる)
    fPath = "C:¥データ¥取込フォルダ¥"

    'フォルダ内の最初のExcelファイルを取得
    fName = Dir(fPath & "*.xls*")

    Do While fName <> ""

        '対象ファイルを開く
        Set wb    = Workbooks.Open(fPath & fName)
        Set wsSrc = wb.Sheets(1)   '1枚目のシートを対象にする

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

        'データ行(2行目以降)をA〜C列分コピーして貼り付け
        wsSrc.Range(wsSrc.Cells(2, 1), wsSrc.Cells(lastRow, 3)).Copy
        wsDest.Cells(pasteRow, 1).PasteSpecial Paste:=xlPasteValues

        Application.CutCopyMode = False

        '次の貼り付け開始行を更新
        pasteRow = wsDest.Cells(wsDest.Rows.Count, 1).End(xlUp).Row + 1

        '保存せずに閉じる
        wb.Close SaveChanges:=False

        '次のファイルへ
        fName = Dir

    Loop

    MsgBox "読み込みが完了しました。"

End Sub
コードの要素役割
Dir(fPath & "*.xls*")フォルダ内の.xls・.xlsx・.xlsmを最初の1件取得
Do While fName <> ""ファイルがなくなるまで繰り返す
Workbooks.Openファイルを開く
PasteSpecial Paste:=xlPasteValues値だけを貼り付け(書式・数式を持ち込まない)
fName = Dir次のファイル名を取得(引数なしでDir再呼び出し)

フォルダをダイアログで選択できるようにするには?

フォルダパスをコードに直書きするとパスが変わるたびにコードを修正する必要があります。実行時にダイアログでフォルダを選択させると柔軟に使えます。

Sub ImportWithFolderDialog()

    Dim fPath  As String
    Dim fName  As String
    Dim wb     As Workbook
    Dim wsDest As Worksheet

    'フォルダ選択ダイアログを表示
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "読み込むファイルのフォルダを選択してください"
        If .Show <> -1 Then
            MsgBox "フォルダが選択されませんでした。", vbExclamation
            Exit Sub
        End If
        fPath = .SelectedItems(1) & "¥"
    End With

    Set wsDest = ThisWorkbook.Sheets("集計")

    fName = Dir(fPath & "*.xls*")

    Do While fName <> ""
        Set wb = Workbooks.Open(fPath & fName)
        '処理内容…
        wb.Close SaveChanges:=False
        fName = Dir
    Loop

    MsgBox "完了しました。"

End Sub

読み込んだデータに出所を記録するには?

複数ファイルをまとめて集計したとき「このデータはどのファイルから来たか」を後から確認できるよう、ファイル名をD列などに記録しておくと管理しやすくなります。

'貼り付け後にD列にファイル名を記録する例
Dim recordStart As Long
Dim recordEnd   As Long

recordStart = pasteRow

wsSrc.Range(wsSrc.Cells(2, 1), wsSrc.Cells(lastRow, 3)).Copy
wsDest.Cells(pasteRow, 1).PasteSpecial Paste:=xlPasteValues

pasteRow = wsDest.Cells(wsDest.Rows.Count, 1).End(xlUp).Row + 1
recordEnd = pasteRow - 1

'読み込んだ行全体にファイル名を記録
wsDest.Range("D" & recordStart & ":D" & recordEnd).Value = fName

エラーが起きたファイルをスキップして続けるには?

パスワードがかかっているファイルや破損ファイルが混ざっているとOpenでエラーになり処理が止まります。エラーが起きたファイルをスキップして次に進むようにすると安全です。

Do While fName <> ""

    On Error Resume Next
    Set wb = Workbooks.Open(fPath & fName)
    On Error GoTo 0

    If wb Is Nothing Then
        Debug.Print "スキップ:" & fName & "(開けませんでした)"
    Else
        '正常に開けた場合の処理
        wb.Close SaveChanges:=False
        Set wb = Nothing
    End If

    fName = Dir

Loop

まとめ

  • Dir(フォルダパス & "*.xls*") でフォルダ内のExcelファイルを順に取得できる
  • Do While fName <> "" 〜 fName = Dir のループでフォルダ内のファイルを全件処理できる
  • フォルダパスは ダイアログ(FileDialog) で選択させるとコードの変更が不要になる
  • 集計先に ファイル名・シート名を記録しておくと後からデータの出所を追跡できる
  • エラーが起きるファイルは On Error Resume Next でスキップして処理を続けられる

よくある質問

サブフォルダ内のファイルも対象にできますか?

Dir関数はサブフォルダを自動では見ません。FileSystemObjectの folder.SubFolders を使って再帰的にサブフォルダを処理する方法か、対象ファイルを一度フラットなフォルダにまとめてから処理する方法があります。

開いているファイルと同名のファイルが対象フォルダにある場合はどうなりますか?

同名のブックが既に開いている場合、Workbooks.Openを実行すると既に開いているブックが返されることがあります。フォルダ内のファイル名と現在開いているブック名が重複しないよう確認するか、処理前に既存ブックを確認するチェックを入れると安全です。

処理速度を上げるにはどうすればいいですか?

Application.ScreenUpdating = FalseApplication.Calculation = xlCalculationManual をループ前に設定し、処理後にTrueと xlCalculationAutomatic に戻すと大幅に速くなります。

対象ファイルのシート名が毎回違う場合はどう対応しますか?

wb.Sheets(1) のようにシート番号(インデックス)で指定すると、シート名に関わらず常に1枚目のシートを対象にできます。特定のシート名を探す場合は wb.Sheets("売上") のように名前指定しますが、存在しない場合はエラーになるためOn Error Resume Nextで確認する処理を加えてください。

読み込み対象から自分自身(集計ファイル)を除外するにはどうすればいいですか?

If fName = ThisWorkbook.Name Then fName = Dir : GoTo SkipFile のように自分のファイル名と一致する場合はスキップする処理を追加します。集計ファイルと読み込み対象ファイルを別のフォルダに分けておく方がより安全です。


動画で学びたい方へ

「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。

VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。

動画で学ぶExcelマクロ|JIMOVEオンラインスクール

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール