VBAでフォルダ内ファイル一括処理・リネーム・アーカイブ

💡 本編(VBAなし)との位置づけ

「複数ファイルの中身のデータを結合する」だけであればVBAは不要です。代替手法は → パワークエリ「データ取り込みパターン集」 を使用してください。本記事は、ファイル自体の「移動」「名前変更」を行うための手法です。

1. パワークエリの限界とFileSystemObject (FSO)

パワークエリの「フォルダーから」取り込みは、大量のCSVやExcelファイルのデータを一気に結合する際に強力ですが、「ファイル自体をリネームする」「処理が終わったファイルを別フォルダに移動(アーカイブ)する」といったファイルシステムへの干渉はできません。
業務フローとして「処理済みファイルは別フォルダへ退避する」ルールがある場合、VBAの FileSystemObject (FSO) が最も確実で安全な選択肢となります。標準の Name ステートメントや Dir 関数は古い仕様であり、Unicode文字の扱いや別ドライブへの移動でエラーを起こしやすいため、現代の実務ではFSO一択です。

2. 実践:Excelリストに基づく一括リネーム(FSO版)

A列に「現在のファイル名」、B列に「新しいファイル名」を入力したリスト(シート名:リネームリスト)を用意し、一気にリネームする堅牢なコードです。上書きエラーやファイル欠損を事前に検知します。

Sub FSO_ファイル一括リネーム() Dim ws As Worksheet Dim i As Long, lastRow As Long Dim folderPath As String Dim oldPath As String, newPath As String Dim fso As Object Dim successCount As Long, errorCount As Long Set ws = ThisWorkbook.Sheets("リネームリスト") Set fso = CreateObject("Scripting.FileSystemObject") folderPath = ThisWorkbook.Path & "\TargetFolder\" ' 処理対象フォルダ lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To lastRow oldPath = fso.BuildPath(folderPath, ws.Cells(i, 1).Value) newPath = fso.BuildPath(folderPath, ws.Cells(i, 2).Value) ' リネームの安全性チェック If Not fso.FileExists(oldPath) Then ws.Cells(i, 3).Value = "エラー:元ファイルなし" errorCount = errorCount + 1 ElseIf fso.FileExists(newPath) Then ws.Cells(i, 3).Value = "エラー:同名ファイルが存在" errorCount = errorCount + 1 Else ' FSOによるリネーム(ファイルのNameプロパティを利用) On Error Resume Next fso.GetFile(oldPath).Name = ws.Cells(i, 2).Value If Err.Number = 0 Then ws.Cells(i, 3).Value = "完了" successCount = successCount + 1 Else ws.Cells(i, 3).Value = "エラー:ファイル使用中など" End If On Error GoTo 0 End If Next i Set fso = Nothing MsgBox "処理完了" & vbCrLf & "成功: " & successCount & "件" & vbCrLf & "失敗: " & errorCount & "件", vbInformation End Sub

3. 処理済みファイルのアーカイブ(日付別フォルダへ移動)

パワークエリでデータを読み込んだ後、使用したCSVファイルを「YYYYMM」形式のアーカイブフォルダに自動で移動させるルーチンです。

Sub 処理済ファイル_アーカイブ() Dim fso As Object Dim sourceFolder As String, archiveRoot As String, targetFolder As String Dim f As Object, folderObj As Object Dim yyyymm As String Set fso = CreateObject("Scripting.FileSystemObject") sourceFolder = ThisWorkbook.Path & "\ImportData\" archiveRoot = ThisWorkbook.Path & "\Archive\" ' 今月のフォルダ名を生成(例:202604) yyyymm = Format(Date, "yyyymm") targetFolder = fso.BuildPath(archiveRoot, yyyymm) ' アーカイブのルート、および月別フォルダが存在しなければ作成 If Not fso.FolderExists(archiveRoot) Then fso.CreateFolder archiveRoot If Not fso.FolderExists(targetFolder) Then fso.CreateFolder targetFolder Set folderObj = fso.GetFolder(sourceFolder) ' フォルダ内の全CSVを移動 For Each f In folderObj.Files If LCase(fso.GetExtensionName(f.Name)) = "csv" Then ' 移動先に同名ファイルがある場合は上書き(True指定)できる Copy を使い、その後削除 ' ※ MoveFile は上書きできないため安全ですが、業務要件により選択してください fso.CopyFile f.Path, fso.BuildPath(targetFolder, f.Name), True f.Delete End If Next f Set fso = Nothing MsgBox "CSVファイルのアーカイブが完了しました。", vbInformation End Sub
実務でのポイント: MoveFile は移動先に同名ファイルが存在するとエラーになります。日次処理で再実行の可能性がある場合、CopyFile (Overwrite:=True) してから Delete する手法がトラブルになりにくい運用方法です。

4. サブフォルダも含む再帰処理

対象フォルダの中にさらにサブフォルダがある場合、再帰的に全てのファイルを処理するパターンです。月別フォルダの中にあるCSVを一括でリネームしたい場合などに使います。

Sub 再帰的ファイル一覧取得(folderPath As String, result As Collection) Dim fso As Object, folder As Object, subFolder As Object, f As Object Set fso = CreateObject("Scripting.FileSystemObject") Set folder = fso.GetFolder(folderPath) ' 現在のフォルダ内のファイルを収集 For Each f In folder.Files result.Add f.Path Next f ' サブフォルダに対して再帰呼び出し For Each subFolder In folder.SubFolders 再帰的ファイル一覧取得 subFolder.Path, result Next subFolder End Sub ' --- 使用例 --- Sub テスト_再帰取得() Dim files As New Collection 再帰的ファイル一覧取得 ThisWorkbook.Path & "\TargetFolder", files Dim i As Long For i = 1 To files.Count Debug.Print files(i) Next i MsgBox files.Count & "件のファイルが見つかりました。", vbInformation End Sub

5. パワークエリとの使い分けまとめ

やりたいこと パワークエリ(本編) VBA FSO(この記事)
複数CSVのデータを結合 ✅ フォルダー取込で一発 不要(PQを使うべき)
ファイルのリネーム ❌ 不可能 ✅ FSO.GetFile.Name
処理済ファイルを別フォルダに移動 ❌ 不可能 ✅ FSO.MoveFile / CopyFile
サブフォルダの再帰的探索 △ フォルダー取込のみ ✅ 再帰関数で自在に

6. 関連記事