大量のファイルをフォルダごと再帰的に処理する必要が出てきたとき、Open文だけでは限界を感じてFileSystemObjectに手を伸ばしました。両者の使い分けが整理されないまま書いていた過去のコードを反省しつつまとめています。
Open文 vs FileSystemObject
図1: Open文 vs FileSystemObject の使い分け
| 項目 | Open文 | FileSystemObject |
|---|---|---|
| 参照設定 | 不要(組み込み) | 不要(CreateObjectで可) |
| テキスト読み書き | ◎ 高速・シンプル | ○ オブジェクト経由 |
| ファイル操作(コピー・移動・削除) | △ 別途 FileCopy等を使う | ◎ メソッドで一括 |
| フォルダ操作 | △ MkDir・RmDir のみ | ◎ SubFolders で再帰可能 |
| ファイル属性・プロパティ | △ GetAttr等 | ◎ FileオブジェクトのプロパティでOK |
Open文(テキスト読み書き)
Option Explicit
' ── テキスト書き込み ──
Sub WriteTextFile(ByVal path As String, ByVal content As String)
Dim fn As Integer
fn = FreeFile ' 空きファイル番号を取得
Open path For Output As #fn
Print #fn, content
Close #fn
End Sub
' ── テキスト読み込み(全行)──
Function ReadTextFile(ByVal path As String) As String
Dim fn As Integer
Dim line As String
Dim sb As String
fn = FreeFile
Open path For Input As #fn
Do While Not EOF(fn)
Line Input #fn, line
sb = sb & line & vbCrLf
Loop
Close #fn
ReadTextFile = sb
End Function
FileSystemObject の基本操作
Option Explicit
Sub FsoExample()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim srcPath As String: srcPath = "C:\data\report.xlsx"
Dim destPath As String: destPath = "C:\backup\report.xlsx"
' ── 存在確認 ──
If fso.FileExists(srcPath) Then
' ── コピー ──
fso.CopyFile srcPath, destPath
' ── 移動 ──
' fso.MoveFile srcPath, destPath
' ── 削除 ──
' fso.DeleteFile srcPath
End If
' ── フォルダ作成 ──
If Not fso.FolderExists("C:\backup") Then
fso.CreateFolder "C:\backup"
End If
' ── テキスト書き込み ──
Dim ts As Object
Set ts = fso.CreateTextFile("C:\data\log.txt", True, True) ' True=上書き, True=Unicode
ts.WriteLine "ログ記録: " & Now
ts.Close
Set ts = Nothing
Set fso = Nothing
End Sub
フォルダ再帰処理
Option Explicit
' 指定フォルダ以下の xlsx ファイルをすべて収集
Sub CollectXlsxFiles(ByVal folderPath As String, ByRef results As Collection)
Dim fso As Object
Dim folder As Object
Dim file As Object
Dim sub_ As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderPath)
' ── ファイルを処理 ──
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Path)) = "xlsx" Then
results.Add file.Path
End If
Next file
' ── サブフォルダを再帰処理 ──
For Each sub_ In folder.SubFolders
CollectXlsxFiles sub_.Path, results
Next sub_
Set fso = Nothing
End Sub
' 呼び出し元
Sub Main()
Dim results As New Collection
CollectXlsxFiles "C:\data", results
Dim item As Variant
For Each item In results
Debug.Print item
Next item
End Sub
まとめ
テキストの読み書きだけなら Open 文が簡潔です。ファイル・フォルダの操作全般(コピー・移動・削除・再帰)は FileSystemObject の方が直感的で強力です。
✅ 次の章では…
PART 11 では セル操作の高速化 を解説します。Range vs 配列の一括読み書きとCalculation制御で処理速度を劇的に改善します。
VBAファイル操作でよくある誤り
VBAのファイル操作はエラー処理を怠るとファイルロックやデータ損失につながります。代表的な落とし穴を整理します。
| 誤り/失敗パターン | 何が起きるか | 正しい対処/防止策 |
|---|---|---|
| Openステートメント後にCloseを呼ばない | ファイルがロックされたままになり、他のプロセスや次回処理でアクセスできなくなる | 必ずClose #ファイル番号で閉じる。エラーが起きても確実にCloseを呼ぶようOn Error Gotoでハンドラーを設ける |
| 存在チェックなしにファイルを削除・上書きする | 対象ファイルが存在しない場合にエラーが発生し、重要なファイルを誤って上書き・削除してしまう | Dir()関数でファイルの存在を確認し、上書きの場合はバックアップコピーを作成してから処理する |
| 相対パスを使用してパスが環境依存になる | 実行環境によってカレントディレクトリが異なり、別のPCでは動作しなくなる | ThisWorkbook.PathやEnviron("USERPROFILE")を使って絶対パスを動的に構築し、環境依存を排除する |