【エクセルVBA入門】For Each~Next文でフォルダ内のブック全てを開く方法

CDコレクション

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

今回はエクセルVBAを使ってバラバラの経費精算書のデータをデータベースに集約するシリーズです。

前回の記事はこちら。

【エクセルVBA入門】フォルダやファイルを操作するFileSystemオブジェクトとその使い方
エクセルVBAでバラバラの経費精算書をデータベースに集めるマクロの作り方をお伝えしています。今回はエクセルVBAでフォルダやファイルを操作するFileSystemオブジェクトとその使い方についてです。

フォルダやファイルの操作をすることができるFileSystemオブジェクトについて紹介しました。

今回はその続き。フォルダ内のすべてのブックについて開いて経費データを収集していきますよ。

ということで、エクセルVBAでFor Each~Next文を使ってフォルダ内のブック全てを開く方法についてお伝えします。

では、行ってみましょう!

スポンサーリンク

前回のおさらい

まず、今回の目標について確認しておきましょう。

以下のような経費精算書があります。

経費精算書ひな形

これは、社内のスタッフごとに別ファイルで作成されて、「data」というフォルダに集められているとします。

その「data」フォルダと同じ階層にあるブックに、以下のような「経費データ」というシートがあり、そこに経費データを収集していくというのが目標です。

経費データフォーマット

そして、スタート地点となるプログラムはこちらです。

Sub 経費精算データ取り込み()

With Workbooks.Open(ThisWorkbook.Path & "\data\" & "201807経費精算書_経費_3001.xlsx")
    With .Worksheets(1)
    
        Dim month As Date: month = .Range("G4").Value
        Dim departmentName As String: departmentName = .Range("G6").Value
        Dim staffId As Long: staffId = .Range("G8").Value
        Dim staffName As String: staffName = .Range("G7").Value
        
        Dim i As Long: i = 12
        Dim di As Long: di = 2
        Do While .Cells(i, 1).Value <> ""
            wsData.Cells(di, 1).Value = month '1 対象月
            wsData.Cells(di, 2).Value = .Cells(i, 1).Value '2 日付
            wsData.Cells(di, 3).Value = ""  '3 部署No
            wsData.Cells(di, 4).Value = departmentName '4 部署
            wsData.Cells(di, 5).Value = staffId '5 社員No
            wsData.Cells(di, 6).Value = staffName '6 氏名
            wsData.Cells(di, 7).Value = .Cells(i, 2).Value '7 科目
            wsData.Cells(di, 8).Value = .Cells(i, 5).Value '8 摘要
            wsData.Cells(di, 9).Value = .Cells(i, 6).Value '9 金額
            wsData.Cells(di, 10).Value = .Cells(i, 7).Value '10 備考
            i = i + 1: di = di + 1
        Loop
    End With
    .Close
End With

End Sub

3行目にある通り、フォルダ内の唯一のブックだけに対応しているプログラムになっていますので、これを「data」フォルダ内のすべてのブックについて繰り返し処理をするように修正していく必要があります。

For Each~Next文とは

繰り返しの構文にFor Each~Next文というものがあります。

これがエクセルVBAにおいて、半端なく便利なシロモノなのです。

記述方法としては、以下のように書きます。

For Each オブジェクト変数 In コレクション
 ’処理
Next オブジェクト変数

と書きます。

コレクションというのは同種のオブジェクトの集合です。

For Each~Next文の意味としては、コレクション内の全てのオブジェクトてについて、一つずつ順番にオブジェクト変数にセットしながらプログラムを繰り返してね、という意味になります。

Worksheetsコレクションの例

わかりやすい例えを使って説明をしますね。

例えば、反復の対象とするオブジェクトをWorksheetオブジェクトとして以下のプログラムを実行してみましょう。

Sub 現在のマクロブックのすべてのワークシート名()

Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
    Debug.Print ws.Name
Next ws

End Sub

wsはFor Each~Next文用に用意したWorksheet型のオブジェクト変数です。命名にルールはありませんので、好きなオブジェクト変数名でOKです。

このオブジェクト変数wsにはFor Each~Nextを繰り返すたびにコレクション内にあるオブジェクトが順番にセットされます。

コレクションとしてはThisWorkbook.Worksheetsが指定されています。つまりThisWorkbookに含まれている全てのワークシートが設定されています。

  • オブジェクト変数:ws
  • コレクション:ThisWorkbook.Worksheets

このFor Each~Nextは、ThisWorkbookに含まれる全てのワークシートについて、一つずつ順番にFor Each~Nextの中を繰り返してね、という意味になります。

例えば「Sheet1」「Sheet2」「Sheet3」の3つのワークシートが存在しているのであれば、このプログラムの実行により、それらのシート名が順番にイミディエイトウィンドウに表示されることになります。

イメージ湧きましたよね?

フォルダ内のすべてのファイルについて繰り返す

今回の目的としては、フォルダ「data」内にあるファイル全てについて処理したいということになります。

Folderオブジェクト内のFilesコレクションを取得する

前回の記事でお伝えした通り、フォルダを取得するにはFileSystemオブジェクトのgetFolederメソッドを使えば良いですね。

FileSystemオブジェクト.getFolder(フォルダのパス)

そして、そのフォルダ内のファイルのコレクション、つまりFilesコレクションをFilesプロパティで取得することができます。

Folderオブジェクト.Files

これをFor Each~Next文のコレクションの位置に指定してあげればよいですよね。

フォルダ内のファイルについてのFor Each~Next文

以上をもとに、以下のようにFor Each~Next文を作ることができます。

Dim f As File
For Each f In fso.GetFolder(ThisWorkbook.Path & "\data").Files
 '処理
Next f

オブジェクト変数とコレクションについて整理しますと、以下のようになります。

  • オブジェクト変数:f
  • コレクション:fso.GetFolder(ThisWorkbook.Path & “\data”).Files

FileSystemオブジェクトとFor Each文でFilesコレクションの全ての要素に処理をすることについては、以下の記事も参考になると思います。

429 Too Many Requests

Fileオブジェクトのフルパスを取得して開く

それで、それぞれのファイルについて、Workbookオブジェクトとして開く必要がありますね。

どうするかというと、繰り返しの対象となっているFileオブジェクトfについて、そのフルパスがわかれば、Openできますよね。

FileオブジェクトはPathプロパティで、そのフルパスを取得できます。

Fileオブジェクト.Path

フォルダ内のブックを開いてデータを収集するプログラム

これを元に、フォルダ「data」内のすべての経費精算書を開いてデータを収集するプログラムを作成すると、こちらになります。

Sub 経費精算データ取り込み()

Dim fso As FileSystemObject
Set fso = New FileSystemObject

Dim di As Long: di = 2
Dim f As File
For Each f In fso.GetFolder(ThisWorkbook.Path & "\data").Files
    Debug.Print f.Path
    With Workbooks.Open(f.Path)
        With .Worksheets(1)
        
            Dim month As Date: month = .Range("G4").Value
            Dim departmentName As String: departmentName = .Range("G6").Value
            Dim staffId As Long: staffId = .Range("G8").Value
            Dim staffName As String: staffName = .Range("G7").Value
            
            Dim i As Long: i = 12
            Do While .Cells(i, 1).Value <> ""
                wsData.Cells(di, 1).Value = month '1 対象月
                wsData.Cells(di, 2).Value = .Cells(i, 1).Value '2 日付
                wsData.Cells(di, 3).Value = ""  '3 部署No
                wsData.Cells(di, 4).Value = departmentName '4 部署
                wsData.Cells(di, 5).Value = staffId '5 社員No
                wsData.Cells(di, 6).Value = staffName '6 氏名
                wsData.Cells(di, 7).Value = .Cells(i, 2).Value '7 科目
                wsData.Cells(di, 8).Value = .Cells(i, 5).Value '8 摘要
                wsData.Cells(di, 9).Value = .Cells(i, 6).Value '9 金額
                wsData.Cells(di, 10).Value = .Cells(i, 7).Value '10 備考
                i = i + 1: di = di + 1
            Loop
        End With
        .Close
    End With
Next f

End Sub

実行すると、以下のように太郎さんだけでなく花子さんのデータも収集することができました。

経費精算データ収集プログラムの結果

まとめ

以上、エクセルVBAでフォルダ内の複数のワークブック全てを開いてデータを取り込むプログラムについて解説をしました。

この状態であればひとまずお仕事には使えるレベルにはなったかなと思います。

ちなみに、フォルダ内のファイルを参照するテクニックはお仕事の現場でかなりの活躍を見せてくれます。

経費精算書だけでなく、出勤管理表でも申込書でもフォーマットさえ統一されていれば活用をすることができますので、ぜひ一度作業の検討をしてみてくださいね。

次回は、シートのデータがある最終行数を求めるステートメントを紹介します。

【エクセルVBA入門】シートのデータがある最終行番号を求めるステートメントを徹底解説
エクセルVBAを使ってバラバラの経費精算書データを集約するシリーズです。今回は、実行のたびにデータをシートに追加できるようにします。また、最終行番号を求めるステートメントについて徹底的に解説をしていきます。

どうぞお楽しみに!

連載目次:エクセルVBAで経費データをデータベースに集約する

請求書シリーズと逆のパターンですが、バラバラの帳票からデータ一覧つまりデータベースに情報を集めて蓄積していく、というお仕事も多いと思います。ここでは各担当者から提出された経費精算書をデータベースに蓄積するプログラムを目標にして進めていきます。
  1. 【エクセルVBA入門】バラバラの経費精算書をデータにまとめる
  2. 【エクセルVBA入門】Do While~Loop文で条件を満たす間繰り返し
  3. 【エクセルVBA入門】繰り返しを使ってデータの転記をするときの2つのポイント
  4. 【エクセルVBA入門】With文でプログラムをスッキリわかりやすく書く
  5. 【エクセルVBA入門】他のワークブックをWithで開く&保存せずに閉じる
  6. 【エクセルVBA入門】フォルダやファイルを操作するFileSystemオブジェクトとその使い方
  7. 【エクセルVBA入門】For Each~Next文でフォルダ内のブック全てを開く方法
  8. 【エクセルVBA入門】シートのデータがある最終行番号を求めるステートメントを徹底解説
  9. 【エクセルVBA入門】開いたブック名から文字列を抽出して人為的なミスを回避する方法
  10. 【エクセルVBA入門】マクロを作るときに知っておきたいマスタデータのこと
  11. 【エクセルVBA入門】開いたブックのファイル名から番号を取り出して数値に変換する
  12. 【エクセルVBA入門】マクロでVlookupを使ってデータを検索する方法
  13. 【エクセルVBA入門】Vlookupメソッドを使ったときに発生するエラーを回避する方法
  14. 【エクセルVBA入門】エラーが発生したときに分岐処理を追加する方法
  15. 【エクセルVBA入門】オートフィルタや行の非表示で隠れている行を全て表示する
タイトルとURLをコピーしました