【テクニカル・上級編】リソースの割り当て解除を安全に行うためのエラーハンドリング – Project VBA解析バイブル

スポンサーリンク

Project VBAの深淵:リソース割り当て解除における「整合性の死守」とメモリ管理の極意

Project VBA(Microsoft Project Object Model)を操る際、最も忌むべきは「中途半端な状態」でのリソース剥離だ。単に `Assignment.Delete` を叩けば済むと考えるのは、アーキテクトとしては三流と言わざるを得ない。

実績工数(Actual Work)が記録されたタスクに対し、不用意なリソース解除を行えば、Projectの計算エンジンは即座にエラーを吐くか、最悪の場合、プロジェクトファイルそのものの整合性を破壊する。本稿では、レガシーなVBA環境において、いかにして「安全に」「高速に」リソースを解放し、メモリリークを皆無にするかを論じる。

—

1. 割り当て解除が失敗する「真因」を見極める

`Assignment` オブジェクトを削除する際、以下のいずれかが存在する場合、VBAは例外を投げる。

  • 実績工数の発生: `ActualWork > 0` の場合、Projectは削除を拒絶する。
  • 依存関係(リンク): 外部参照や複雑な制約がある場合、計算エンジンがロックをかける。
  • メモリの断片化: 大規模プロジェクトでループ処理中にオブジェクトを放置すると、COMの参照カウンタが積み上がり、スタックオーバーフローや予期せぬクラッシュを招く。

2. 極限のコード設計:安全な解除プロセス

以下のコードは、単なる削除ではなく、プロジェクトファイルの整合性を担保しつつ、明示的なメモリ解放を行うためのテンプレートである。

‘ プロジェクトの整合性を保ったリソース解除の実装例
Public Sub SafeRemoveResource(ByRef targetTask As Task, ByVal resourceName As String)
Dim asn As Assignment
Dim proj As Project
Set proj = ActiveProject

‘ 1. エラーハンドリングの要塞化
On Error GoTo Cleanup

‘ 2. 対象のアサインメントを特定
For Each asn In targetTask.Assignments
If asn.ResourceName = resourceName Then

‘ 実績工数が存在する場合のフォールバック
‘ 削除ではなく「稼働率0%」への変更を検討すべきケース
If asn.ActualWork > 0 Then
Debug.Print “Warning: 実績工数が存在するため削除をスキップ: ” & asn.Name
‘ ここでフラグを立てて通知するロジックへ移行
Exit Sub
End If

‘ 3. 削除実行
asn.Delete

‘ 4. 即時のオブジェクト解放(重要)
Set asn = Nothing
End If
Next asn

Cleanup:
‘ 5. コンテキストのクリーンアップ
If Err.Number <> 0 Then
‘ Windows API等を用いた詳細なログ出力処理をここに実装
Debug.Print “Critical Error: ” & Err.Description
End If

Set proj = Nothing
End Sub

3. パフォーマンスとメモリ最適化の知見

VBAにおけるメモリリークの9割は、`Set Object = Nothing` を怠ったことによる「COM参照の残留」だ。特に数千行を超えるプロジェクトで `For Each` ループを回す際、オブジェクト変数がスコープを抜けるまで残留し続けると、メモリフットプリントは指数関数的に増大する。

  • 明示的な解放: ループ内では必ず `Set asn = Nothing` を実行し、参照カウンタを即座にデクリメントすること。
  • 画面更新の制御: `Application.ScreenUpdating = False` を利用するのは基本だが、さらに `Application.Calculation = pjManual` に切り替えることで、削除毎の再計算を抑制し、処理時間を劇的に短縮できる。

4. システム間連携における「ロック」の回避

外部システム(ExcelやSQL Server)と連携してリソースを割り当てる際、最も恐ろしいのは「Project側が計算中のロック」だ。

システム間で同期をとる際は、以下の手順を鉄則とする。

1. 計算モードを「手動」へ強制移行。
2. バルク処理(一括削除)を実行。
3. 最後に `Project.Calculate` を一回だけ呼び出す。

このアーキテクチャを採用することで、計算エンジンが都度走ることによる不整合エラーを回避し、かつ処理速度を最大化することが可能となる。

最後に:伝説的エンジニアの嗜み

VBAは、一見すると古い技術だが、その背後にあるCOMアーキテクチャを深く理解すれば、現代の高度なシステム構築にも十分に耐えうる堅牢な基盤となる。

重要なのは、コードが「何をしたいか」ではなく、「Projectエンジンがどのような挙動を嫌うか」を先回りして察知する能力だ。エラーを回避するのではない、エラーを発生させない環境を作る。それが、現場を任されるシニアエンジニアの矜持である。

貴殿のプロジェクトに、無駄なクラッシュがないことを願う。

タイトルとURLをコピーしました