Project VBAを掌握せよ:FSOによるプロジェクトファイル一括制御の極意
プロジェクト管理の現場において、数十、数百の`.mpp`ファイルを個別に開いてステータスを確認・更新する……そんな「化石のような手作業」で消耗していないだろうか。
Project VBAを扱うエンジニアとして、私は断言する。「ファイル操作を自動化できないプロジェクト管理は、管理とは呼べない」と。
今日は、`FileSystemObject (FSO)`を用いた再帰的なファイル検索と、Project Applicationを制御する堅牢な一括処理の実装手法を授ける。単に動くだけのコードではない。本番環境で「例外を吐かずに確実に仕事を完遂する」ためのプロの設計論だ。
—
1. なぜ「Dir関数」ではなく「FSO」なのか
VBA初心者はよく`Dir`関数でファイルをループさせるが、これは拡張性が皆無だ。
- 再帰処理の限界: サブフォルダの階層が深くなるたびにロジックが破綻する。
- 状態管理: `Dir`は内部でポインタを保持するため、入れ子になったループ処理で容易に暴走する。
対して`FileSystemObject (FSO)`はオブジェクト指向的であり、ファイル操作を「オブジェクト」として扱う。これにより、堅牢で保守性の高い再帰処理が可能になる。
—
2. 堅牢な一括処理アーキテクチャ
本番環境で運用するツールには、以下の3原則が必須だ。
1. 疎結合な設計: ファイル検索ロジックと、個別のプロジェクト処理(開く・保存・ベースライン設定等)を分離する。
2. エラーハンドリングの徹底: 1つのファイルが破損していても、処理を止めない。
3. リソースの解放: `Project.Application`を起動しっぱなしにするのはメモリリークの温床。処理単位で確実に閉じる。
—
3. 実装:再帰的検索とプロジェクト制御のプロダクションコード
以下のコードは、指定ディレクトリ以下の全`.mpp`ファイルを再帰的に検索し、処理を行うテンプレートだ。
Option Explicit
‘ 必要な参照設定: Microsoft Scripting Runtime
Public Sub ProcessAllProjects()
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 処理対象のルートディレクトリ
Dim targetPath As String
targetPath = “C:\Projects\TargetFolder”
‘ 再帰処理の開始
Call RecursiveSearch(fso.GetFolder(targetPath), fso)
MsgBox “全プロジェクトの処理が完了しました。”, vbInformation
End Sub
Private Sub RecursiveSearch(folder As Object, fso As Object)
Dim subFolder As Object
Dim file As Object
‘ 現在のフォルダ内のファイルを処理
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Path)) = “mpp” Then
Call ProcessProject(file.Path)
End If
Next
‘ サブフォルダを再帰的に探索
For Each subFolder In folder.SubFolders
Call RecursiveSearch(subFolder, fso)
Next
End Sub
Private Sub ProcessProject(filePath As String)
Dim projApp As MSProject.Application
Dim proj As MSProject.Project
On Error GoTo ErrorHandler
‘ Projectアプリケーションを個別に制御(非表示で高速化)
Set projApp = New MSProject.Application
projApp.Visible = False
‘ ファイルを開く(ReadOnlyモード等、要件に合わせて変更)
If projApp.FileOpen(filePath, ReadOnly:=False) Then
Set proj = projApp.ActiveProject
‘ — ここに業務ロジックを記述 —
‘ 例: ベースラインの保存
‘ proj.SaveBaseline BaselineNumber:=pjBaseline
‘ ——————————-
proj.Close SaveChanges:=pjSave
End If
Set proj = Nothing
projApp.Quit
Set projApp = Nothing
Exit Sub
ErrorHandler:
‘ エラーログをテキストファイル等に出力するのがプロの作法
Debug.Print “エラー発生: ” & filePath & ” – ” & Err.Description
If Not projApp Is Nothing Then projApp.Quit
End Sub
—
4. プロフェッショナルへのアドバイス
ファイルロックとパフォーマンス
大量のファイルを処理する場合、`projApp.Visible = False`は必須だ。しかし、これを行うと「ファイルが読み取り専用で開かれています」というダイアログが背後で停滞し、プログラムがハングアップすることがある。`projApp.DisplayAlerts = False`を併用し、ダイアログを強制的に閉じる設定を忘れるな。
データベース連携の罠
もし、この処理の結果をExcelやSQL Serverに書き出すなら、「1ファイル処理するごとに接続を切る」な。DBへのコネクションは重い。処理の冒頭でコネクションを張り、最後で閉じる。そして、ファイル処理中のデータはコレクションや配列に保持し、最後に一括でコミットする。これがパフォーマンスを最大化する鍵だ。
最後に
コードを書くことは、単なる作業ではない。そのコードが将来の自分、あるいはチームメンバーの時間をどれだけ節約するかを想像することだ。「動いた」で満足するな。「誰が保守しても壊れない」設計こそが、我々エンジニアの誇りであるべきだ。
さあ、このコードを武器に、プロジェクト管理という名の迷宮を攻略してほしい。健闘を祈る。
