【テクニカル・上級編】複数プロジェクト間でのリソース競合を可視化するダッシュボード作成 – Project VBA解析バイブル

スポンサーリンク

プロジェクトの境界を越えろ:Project VBAによるリソース競合可視化の極致

諸君。Project VBAの海を渡り歩いていると、避けて通れない絶望がある。それは「複数のmppファイルに散らばったリソースの、全体像が見えない」という不毛な状況だ。

PMOやリソースマネージャーがExcelで「誰がどこでパンクしているか」を必死に手作業で集計している光景は、もはや喜劇ですらない。今日は、複数のプロジェクトファイルを横断し、メモリを極限まで節約しながらリソース競合を可視化する、アーキテクト級のソリューションを提示する。

1. なぜ「そのまま」では死ぬのか:メモリ管理の鉄則

Project VBAで複数の`Project`オブジェクトを同時に開く際、最も恐れるべきはメモリリークだ。`Application.Projects`を舐めるようにループする際、`Set`したオブジェクトを適宜解放しなければ、MS ProjectのCOMプロセスは肥大化し、やがて応答不能に陥る。

我々が目指すべきは、「必要な時に呼び出し、即座にメモリの海へ還す」というストイックなライフサイクル管理だ。

2. 横断集計エンジンの実装アーキテクチャ

以下のコードは、指定したフォルダ内のすべてのmppファイルからリソース情報を吸い出し、メモリ上でマッピングした後にExcelへ出力する最小構成のロジックだ。

‘ 必要な参照設定: Microsoft Project x.x Object Library
Option Explicit

Public Sub ExportResourceUtilization()
Dim projApp As MSProject.Application
Dim proj As MSProject.Project
Dim res As MSProject.Resource
Dim fso As Object, folder As Object, file As Object
Dim targetFolder As String

targetFolder = “C:\Projects\Data\”
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set projApp = New MSProject.Application

‘ バックグラウンドで処理し、描画負荷を低減
projApp.Visible = False

For Each file In fso.GetFolder(targetFolder).Files
If LCase(fso.GetExtensionName(file.Name)) = “mpp” Then
‘ プロジェクトを開く(読み取り専用推奨)
Set proj = projApp.Projects.Add(file.Path, ReadOnly:=True)

‘ リソースの集計処理(この関数の詳細は後述)
Call ExtractResourceData(proj)

‘ メモリの即時解放: 明示的なCloseとNothingの代入
proj.Close SaveChanges:=pjDoNotSave
Set proj = Nothing
End If
Next file

‘ クリーンアップ
projApp.Quit
Set projApp = Nothing
Set fso = Nothing
End Sub

Private Sub ExtractResourceData(ByRef proj As MSProject.Project)
Dim res As MSProject.Resource
‘ ここでExcelのRange等にデータを転送する
‘ 重要なのは、Projectオブジェクトを直接参照し続けず、
‘ 必要な属性だけを抽出してコレクションに保持する点だ
For Each res In proj.Resources
If Not res Is Nothing Then
If res.PercentAllocation > 100 Then
Debug.Print res.Name & ” が競合: ” & res.PercentAllocation & “%”
End If
End If
Next res
End Sub

3. チーフアーキテクトの視点:パフォーマンスの要諦

上記のコードを単に動かすだけでは、プロとは呼べない。実運用では以下の調整が不可欠だ。

  • 遅延バインディングの検討:

配布先環境のMS Projectのバージョンが混在している場合、`New MSProject.Application`ではなく、`CreateObject(“MSProject.Application”)`による遅延バインディングを採用せよ。これにより、参照設定の不一致によるランタイムエラーを一掃できる。

  • Windows APIによるプロセス監視:

もしプロジェクトファイルが巨大で、開くたびにメモリが解放されない現象(ゾンビプロセス)が発生する場合、`GetWindowThreadProcessId` APIを使用して、特定のPIDを明示的にKillする実装を追加する勇気を持て。

  • イベントの抑制:

`Application.DisplayAlerts = False` を必ず設定せよ。外部参照リンクの更新確認ダイアログひとつで、自動化プロセスは凍結する。

4. 結論:泥臭い自動化を「洗練」に変える

リソースの競合は、単なる数値のオーバーフローではない。組織の生産性という「血流」の停滞だ。

Excelへのレポート出力においては、`Application.ScreenUpdating = False`を徹底し、書き込みは`Range`の配列一括転送(`Range.Value = Array`)を行うこと。セル単位の書き込みは、巨大なデータセットにおいては犯罪的なパフォーマンス低下を招く。

このコードは、君たちが直面している混沌を整理するための、最初の楔(くさび)に過ぎない。あとは、このアーキテクチャの上に、各社の独自ルールを肉付けしていけばいい。

システムは、書いたコードの通りにしか動かない。そして、そのコードの品質は、設計者の矜持そのものだ。健闘を祈る。

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