【テクニカル・上級編】リソースの「稼働率」をヒートマップ化するExcelアドイン連携VBA – Project VBA解析バイブル

スポンサーリンク

Project VBAの深淵:リソース稼働率ヒートマップの極限実装

多くのVBAエンジニアは、`Project.Application`オブジェクトを安易に叩き、`For Each`ループでリソースを舐めるような稚拙なコードでシステムを破綻させる。プロジェクトの規模が数千タスクを超えた瞬間、彼らのアプリケーションは「応答なし」の墓標を立てる。

真のアーキテクトは、Projectのデータモデルを「メモリ上の多次元配列」として抽象化し、Excelの再描画コストを極限まで排除する。今日は、Projectリソースの稼働負荷をヒートマップとしてExcelに展開する、エンジニアリングの真髄を説く。

—

1. アーキテクチャの鉄則:オブジェクト・オーバーヘッドの撲滅

Projectの`Resource.Assignments`を直接走査するのは自殺行為だ。COM経由のプロパティアクセスは、その一回一回が重厚なIPC(プロセス間通信)を伴う。

極意: 必要なデータは、一度のバッチ処理でVariant配列に吸い上げ、メモリ空間内で完結させる。

‘ メモリ空間への一括転送用構造体
Private Type ResourceLoad
Name As String
Workload As Double
Dates As Variant ‘ 日次負荷配列
End Type

‘ 伝説的なチーフの設計:COM呼び出しを最小化するイテレータ
Public Sub ExtractResourceData(ByRef projApp As Object)
Dim res As Object
Dim rCount As Long

‘ プロセス間通信回数を減らすため、あらかじめ範囲を絞る
With projApp.ActiveProject
rCount = .Resources.Count
‘ ここでメモリを確保する。ReDim Preserveの乱用はメモリの断片化を招くため禁忌
Dim dataMap() As ResourceLoad
ReDim dataMap(1 To rCount)

‘ 処理の詳細は割愛するが、ここで一気に配列へ格納し、
‘ ループ内での.Rangeや.Cellsアクセスは一切行わない
End With
End Sub

—

2. ヒートマップ描画の最適化:計算と描画の分離

Excelでヒートマップを描画する際、`Range.Interior.Color`を一つずつ変更する愚行は今すぐやめるべきだ。1000セルあれば1000回の再描画イベントが発生し、UIスレッドを殺す。

戦術: Excelの「条件付き書式」を数式で適用せよ。VBAの役割は、値をセルに流し込み、条件付き書式のルールを一度だけ書き換えることだ。

‘ 条件付き書式の動的適用(パフォーマンスの極致)
Sub ApplyHeatMap(targetRange As Range)
With targetRange.FormatConditions.AddColorScale(ColorScaleType:=3)
‘ 低負荷(緑)から高負荷(赤)へのグラデーションを定義
.ColorScaleCriteria(1).FormatColor.Color = RGB(0, 255, 0)
.ColorScaleCriteria(2).FormatColor.Color = RGB(255, 255, 0)
.ColorScaleCriteria(3).FormatColor.Color = RGB(255, 0, 0)
End With
End Sub

—

3. Windows APIによる「応答なし」の回避

VBAの実行中、特にProjectからのデータ抽出が重い場合、Windowsはアプリがフリーズしたと判断する。これを防ぐには、`DoEvents`という安易な魔法に頼らず、`User32.dll`の`PeekMessage`を叩き、イベントキューを適切に処理するのがプロの流儀だ。

‘ メッセージポンプの制御(高度なUI制御)
Private Declare PtrSafe Function PeekMessage Lib “user32” Alias “PeekMessageA” _
(lpMsg As Any, ByVal hwnd As LongPtr, ByVal wMsgFilterMin As Long, _
ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long

Sub SafeWait()
‘ DoEventsの副作用(再帰呼び出しによるスタックオーバーフロー)を回避し、
‘ UIスレッドの最低限の息継ぎを強制する
Dim msg As Any
If PeekMessage(msg, 0, 0, 0, 1) Then
‘ イベント処理をハンドリング
End If
End Sub

—

4. ライフサイクル管理:メモリリークを許すな

VBAにおいて、`Set obj = Nothing`を書き忘れるのは素人だ。しかし、真のアーキテクトは「エラーハンドリングのスコープ内での確実な解放」を徹底する。`On Error GoTo Cleanup`は、プロジェクトの安定性を担保する最後の砦である。

Public Sub MasterProcess()
Dim projApp As Object
On Error GoTo Cleanup

Set projApp = GetObject(, “MSProject.Application”)
‘ … 処理本体 …

Cleanup:
‘ 予期せぬエラー発生時も、メモリリークを許さない
If Not projApp Is Nothing Then Set projApp = Nothing
‘ オブジェクトの完全な破棄を確実にする
End Sub

—

結び:エンジニアリングは「制約」との対話である

Project VBAというレガシーな枠組みは、現代の技術スタックから見れば不自由極まりない。しかし、その制約こそが、エンジニアの腕を磨く砥石となる。

ヒートマップがExcel上で軽快に描き出されるとき、それは単なる可視化ではない。君の書いたロジックが、プロジェクトの複雑性を完全に掌握したという証拠だ。

次回の講義では、このデータをJSON化し、Web APIを介してダッシュボードへリアルタイム同期するアーキテクチャについて深掘りする。それまでに、今日のコードを自らのシステムに移植し、ボトルネックを徹底的に排除しておけ。

「動く」ことは最低条件だ。「速く、美しく、壊れない」ことこそが、伝説への入り口である。

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