プロジェクト統計情報の「自動追記」:Project VBAとExcelの境界を越えるアーキテクチャ
プロジェクトマネジメントにおいて、MS Projectの統計情報(進捗率、コスト、工数)を「点」でしか見ていないならば、それはマネジメントではない。真の統制とは、それらの推移を「線」として捉えることにある。
本稿では、MS Projectの保存イベントをトリガーに、統計情報を外部Excel台帳へ非同期的に追記する堅牢なワークフローを構築する。単なるコードの羅列ではない。メモリリークを排除し、マルチユーザー環境でも破綻しない「極限の設計思想」を伝授する。
—
1. アーキテクチャの核心:イベントハンドラの分離とライフサイクル管理
Project VBAにおいて最も避けるべきは、`Project_BeforeSave` イベント内に直接重い処理を記述することだ。これは保存処理そのものを遅延させ、最悪の場合、プロジェクトファイルの破損を招く。
我々が採用すべきは、「状態の退避と別プロセス実行」である。
核心となる設計指針
- イベントの即時解放: `BeforeSave` はデータの抽出と一時保存に徹する。
- 早期バインディングの回避: 実行時の参照関係トラブルを避けるため、Excel操作は `Late Binding`(CreateObject)で行う。
- メモリの完全浄化: `Set obj = Nothing` は儀式ではない。COMオブジェクトの参照カウントを確実にゼロにするための必須手順である。
—
2. 実装:Project側(Event Handler)
まずは `ThisProject` モジュールに記述するイベントハンドラだ。ここでは、統計情報を構造体(または配列)として抽出し、Excelへ引き渡す準備を行う。
‘ ThisProject モジュールに記述
Private Sub Project_BeforeSave(ByVal pj As Project, ByVal SaveAsUi As Boolean, Cancel As Boolean)
On Error GoTo Err_Handler
‘ 統計データの抽出
Dim stats(1 To 4) As Variant
stats(1) = Now
stats(2) = pj.Name
stats(3) = pj.PercentComplete
stats(4) = pj.Cost
‘ Excelへの転記処理を呼び出し(分離設計)
Call ExportStatsToExcel(stats)
Exit Sub
Err_Handler:
MsgBox “統計情報の転記に失敗しました: ” & Err.Description, vbCritical
End Sub
—
3. 実装:Excel連携ロジック(Memory Management)
ここがエンジニアの腕の見せ所だ。Excelを起動し、追記し、即座に解放する。この際、`Workbook.Close` と `Application.Quit` を確実に行い、ゾンビプロセスを発生させてはならない。
Public Sub ExportStatsToExcel(data As Variant)
Dim xlApp As Object
Dim xlWb As Object
Dim xlWs As Object
Dim targetPath As String
targetPath = “C:\ProjectLogs\ProjectStatistics.xlsx”
‘ 外部プロセスの起動
Set xlApp = CreateObject(“Excel.Application”)
Set xlWb = xlApp.Workbooks.Open(targetPath)
Set xlWs = xlWb.Sheets(1)
‘ 最終行を取得して追記
Dim nextRow As Long
nextRow = xlWs.Cells(xlWs.Rows.Count, 1).End(-4162).Row + 1 ‘ xlUp = -4162
‘ データの書き込み
xlWs.Cells(nextRow, 1).Resize(1, 4).Value = data
‘ 保存と終了処理
xlWb.Close SaveChanges:=True
xlApp.Quit
‘ 参照の明示的解放(必須)
Set xlWs = Nothing
Set xlWb = Nothing
Set xlApp = Nothing
End Sub
—
4. シニアエンジニアが意識すべき「極限の最適化」
Windows APIによる二重起動防止
もし、複数のProjectファイルが同時に保存された場合、Excelのインスタンスが競合する可能性がある。このアーキテクチャを堅牢にするには、`FindWindow` APIを使用してExcelのプロセスロック状態を監視するか、あるいは「ファイルシステムへの書き込み」を経由するキューイング方式を推奨する。
なぜ `Late Binding` なのか
`Microsoft Excel XX.X Object Library` を参照設定に追加すると、環境差異(バージョン不一致)でコンパイルエラーを引き起こす。大規模開発において、参照設定の欠落は地雷そのものだ。`CreateObject` を用いることで、実行時の柔軟性を最大限に担保している。
パフォーマンスの重み
`Application.ScreenUpdating = False` を記述するのも一つの手だが、本来は「Excelを開かずにVBAから直接バイナリまたはCSVへ書き込む」のが最速だ。もし管理者が求めるのが「集計の自動化」であるならば、ExcelのGUI操作を介さず、`Scripting.FileSystemObject` を用いてCSVに追記し、Excel側でそれを読み込むアーキテクチャが最も低負荷であることは言うまでもない。
—
結びに:保守性を担保する「黒子の哲学」
システムは完成した瞬間から腐敗が始まる。
今回提供したコードは、あくまで「最小の構成」だ。実戦投入する際は、エラーログの出力先を統一し、`Resume` ステートメントを用いたリトライ処理を組み込むことを強く推奨する。
VBAはレガシーではない。使い手の知性次第で、Projectのポテンシャルを引き出す最強の「ハックツール」に化ける。諸君のプロジェクトが、この自動化によってより精緻な管理下におかれることを期待する。
何か疑問があれば、アーキテクチャの深層についていつでも議論しよう。
