【テクニカル・上級編】大規模WBSの分割:VBAで特定の階層を別ファイルに切り出し、依存関係を維持する – Project VBA解析バイブル

スポンサーリンク

巨大WBSの解体新書:Project VBAによる階層分割と依存関係の動的再構築

巨大なProjectファイル(.mpp)は、いずれ「モンスター」と化す。数千行を超えるWBS、複雑に絡み合う依存関係、そして度重なる更新で肥大化したバイナリデータ。これらを単一のファイルで管理するのは、技術的負債への最短ルートだ。

今日は、プロジェクト管理の現場において「分割」と「連結」を自動化し、堅牢なモジュール型アーキテクチャを構築する極限の手法を伝授する。

1. なぜ「分割」が必要なのか:メモリと整合性の限界

Projectのオブジェクトモデルは強力だが、同時にメモリリークの温床でもある。特に`Task`オブジェクトの`Predecessors`(先行タスク)は、ファイル分割時に参照が切れるという致命的な問題を孕んでいる。

私が推奨するのは、「マスター・スレーブ・ゲートウェイ」アーキテクチャだ。

  • マスターファイル: 全体工程のサマリとマイルストーンを保持。
  • スレーブファイル: 特定階層以下の詳細WBSを保持。
  • ゲートウェイ: VBAにより、外部ファイル間の依存関係(外部リンク)を動的に再定義し、同期をとる。

2. 依存関係維持のためのキーポイント:`ExternalTask`の制御

ファイルを分割する際、最も重要なのは「外部タスク(External Task)」の扱いだ。VBAからこれを操作するには、`Task.ExternalTask`プロパティを理解し、正しいパスを注入する必要がある。

実装コード:外部依存の再構築

以下のコードは、スレーブファイルのタスクをマスターファイルにリンクさせ、依存関係を維持するエンジンの一部である。

‘ 依存関係を維持したまま、外部タスクをリンクする核心ロジック
Public Sub LinkExternalTask(targetTask As Task, sourceMppPath As String, sourceTaskID As Long)
Dim linkString As String

‘ プロジェクトの外部参照形式: <パス>\
‘ Windows APIによるパス正規化を推奨するが、まずはProjectの流儀に従う
linkString = “‘” & sourceMppPath & “‘\” & sourceTaskID

On Error Resume Next
‘ 前提条件の追加
targetTask.Predecessors = linkString

If Err.Number <> 0 Then
‘ エラーハンドリング:ファイルパスが不正、またはタスクIDが存在しない場合
Debug.Print “Link Error: ” & targetTask.Name & ” -> ” & linkString
End If
On Error GoTo 0
End Sub

3. パフォーマンスの極致:オブジェクトの解放とメモリ管理

VBAにおいて、`Application.Projects`や`Task`オブジェクトを不必要に保持することは、メモリ枯渇の主因となる。大規模処理を行う際は、必ず「スコープを最小化し、即座に解放する」原則を徹底せよ。

メモリ最適化の定石

Sub SafeCleanup()
Dim prj As Project
‘ 巨大な処理を行う前には、強制的な再計算をオフにする
Application.Calculation = pjManual

‘ 処理終了時には必ずオブジェクト変数をNothingに
‘ Set prj = Nothing だけでは不十分な場合、ガベージコレクションを意識したコードを書く
Set prj = Nothing

‘ 最後に再計算を実行し、Windows APIでメモリを解放する(必要であれば)
Application.Calculation = pjAutomatic
Application.CalculateAll
End Sub

4. Windows APIを活用したファイルハンドリングの堅牢化

Project VBA標準のファイルパス操作は、ネットワークドライブや長いパス名で不安定になることが多い。`Kernel32`を呼び出し、絶対パスの取得と存在確認を厳密に行うのが「プロの仕事」だ。

If VBA7 Then
Private Declare PtrSafe Function GetFullPathName Lib “kernel32” Alias “GetFullPathNameA” _
(ByVal lpFileName As String, ByVal nBufferLength As Long, ByVal lpBuffer As String, ByVal lpFilePart As String) As Long
End If

‘ パスの正規化関数
Public Function GetNormalizedPath(ByVal path As String) As String
Dim buffer As String 260
GetFullPathName path, 260, buffer, vbNullString
GetNormalizedPath = Left$(buffer, InStr(buffer, vbNullChar) – 1)
End Function

5. アーキテクトからの提言:運用を止めないために

モジュール化したWBSを運用する際、最も恐ろしいのは「パスの変更」だ。

  • 絶対パスをコードに埋め込まない: 設定ファイルやレジストリ、またはマスターファイル内の隠しプロパティに、各スレーブファイルの格納場所を動的に記録させること。
  • 階層構造のハッシュ管理: 分割したファイルが正しく更新されているか、タスクの最終更新日時をハッシュ値としてマスターで管理し、同期の必要性を判定するアルゴリズムを導入せよ。

まとめ:技術は「管理」のためにある

システム管理者が目指すべきは、ツールを複雑にすることではなく、「誰でも安全に大規模プロジェクトを運用できるエコシステム」を作ることだ。

VBAはレガシーと言われるが、Projectの深淵を制御する唯一無二の手段であることに変わりはない。今日公開したコードとアーキテクチャの指針が、君のプロジェクトを「崩壊」から救う一助となることを願っている。

妥協のないコードを書け。それが、真のエンジニアだ。

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