MS Project自動化の深淵:メモリリークを撲滅する「プロジェクト・ライフサイクル管理」の極意
多くのVBAエンジニアが、MS Projectの自動化において「なぜか動作が重くなる」「突然Projectが応答なしになる」という壁にぶつかる。その原因の9割は、オブジェクトのゾンビ化にある。
Projectアプリケーションは、ExcelやWordとは比較にならないほどメモリを貪る。特に複数プロジェクトを逐次処理する際、`.Close`メソッドを呼んだだけでは、裏でインスタンスが生き残り、メモリを圧迫し続ける。
今日は、プロフェッショナルとして守るべき「Projectオブジェクトのライフサイクル管理」の真髄を伝授する。
—
1. なぜ「Closeだけ」では足りないのか
VBAにおける `Set prj = Nothing` は、参照カウントを減らすだけの儀式ではない。しかし、MS ProjectはCOMの複雑なラッパーの上に成り立っているため、明示的にオブジェクトの階層を解体しなければ、参照が残存し、バックグラウンドでプロセスが積み重なる。
特に、`Application.Projects.Open` で開いた各プロジェクトオブジェクトは、明示的なクローズ処理と参照破棄をセットで行わない限り、メモリ上に残骸を撒き散らす。これが長時間のバッチ処理でPCをフリーズさせる真犯人だ。
—
2. 堅牢な自動化を実現する「クリーン・プロセッサ」設計
以下のコードは、複数プロジェクトを安全に処理するためのテンプレートだ。ポイントは「エラーハンドリングによる強制解放」と「明示的なクローズ」の二段構えにある。
‘ ——————————————————————
‘ 複数プロジェクト処理用:メモリ安全性を担保するプロトタイプ
‘ ——————————————————————
Public Sub ProcessMultipleProjects(filePaths As Collection)
Dim projApp As MSProject.Application
Dim prj As MSProject.Project
Dim filePath As Variant
‘ プロジェクトアプリの初期化(既に開いていればそれを使う)
Set projApp = New MSProject.Application
projApp.Visible = False ‘ バックグラウンド処理で高速化
On Error GoTo Cleanup
For Each filePath In filePaths
‘ ファイルを開く(読み取り専用推奨:ロック回避のため)
Set prj = projApp.Projects.Open(filePath, ReadOnly:=True)
‘ — ここにビジネスロジックを記述 —
Debug.Print “処理中: ” & prj.Name
‘ ———————————-
‘ 処理が終わったら即座に閉じる
‘ SaveChanges:=pjDoNotSave を明示するのが事故を防ぐコツ
prj.Close SaveChanges:=pjDoNotSave
‘ オブジェクトの参照を強制的に破棄
Set prj = Nothing
Next filePath
Cleanup:
‘ エラーが発生しても確実にアプリを終了・解放する
If Not prj Is Nothing Then prj.Close SaveChanges:=pjDoNotSave
If Not projApp Is Nothing Then
projApp.Quit
Set projApp = Nothing
End If
If Err.Number <> 0 Then
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical
End If
End Sub
—
3. 実務で「詰む」ポイント:3つの鉄則
① `Visible = False` の罠
バックグラウンドで隠れて動くプロセスは非常に強力だが、処理中にエラーで止まると、`Task Manager` に「Microsoft Project」が幽霊のように残る。`On Error` ハンドラ内で必ず `Quit` を呼び出す設計を忘れてはならない。
② データベース連携時の注意点
プロジェクトをデータベース(Project Server/Online)から開く場合、`Projects.Open` の引数には接続文字列やパスが必要となる。このとき、ネットワーク断絶等による「ダイアログの表示」が自動化の敵となる。
必ず `Application.DisplayAlerts = False` を冒頭で宣言し、対話的処理を完全に封じ込めること。
③ ベースライン設定の非同期リスク
ベースラインをプログラムから設定する際、MS Projectは内部的に計算処理を行う。大規模プロジェクトで `BaselineSave` を繰り返すと、完了を待たずに次のコードが走り、データ不整合を起こすことがある。
極めて巨大なファイルの場合、処理後に `CalculateAll` を明示的に呼び出し、オブジェクトの更新を確定させるのが賢明だ。
—
結びに:コードは「生き物」である
今回紹介した設計パターンは、単なる「動くコード」ではなく、「運用に耐えうるコード」だ。
自動化エンジニアの価値は、コードを書くことそのものではなく、「そのコードがどれだけ長期間、無人でエラーを吐かずに走り続けられるか」という安定性に宿る。プロジェクトファイルのライフサイクルを制御できるようになった時、君の自動化ツールは「単なるスクリプト」から「堅牢な業務基盤」へと進化するはずだ。
次は、プロジェクト間の依存関係を保持したままのデータ抽出について深掘りしよう。準備はいいか?
