【上級者向け】Projectの「ガントチャート」描画制御:バーのスタイルを依存関係のタイプで自動変更する
レガシーな巨大WBSの海原を航海するとき、管理者を最も絶望させるのは「情報の不可視性」だ。
MS Projectのデフォルトのガントチャートは、すべてのタスクバーを同一の単調な青い矩形として描き出す。そこにFS(Finish-to-Start)が隠されていようが、SS(Start-To-Start)のクリティカルな制約が潜っていようが、画面上からは一切判別がつかない。進捗会議のたびに、担当者がリンク線を一つずつ手動で辿って確認するような前近代的なオペレーションを強いられている現場も少なくないはずだ。
プロジェクトの規模が数千タスクを超えた瞬間、UIの視覚的情報はそのままプロジェクトの生存確率に直結する。
今回は、MS ProjectのVBAオブジェクトモデルの深淵に潜り込み、タスク間の依存関係(Task Dependencies / Predecessors)のタイプを動的に解析し、ガントチャート上のバーのスタイル(色、形状、パターン)をリアルタイムで自動書き換えする極限のUI自動化手法を解説する。
—
1. Project VBAにおける描画制御のパラダイムと罠
MS ProjectのVBAにおいて、画面描画やスタイル変更を扱う際の最大の障壁は、「オブジェクトのライフサイクルとビューの更新コスト」である。
甘いコードを書けば、数千行のWBSをループさせた瞬間にメモリリークを引き起こし、最悪の場合はCOMコンポーネントの応答停止(フリーズ)を招く。特に `Task.TaskLinks` コレクションの走査と、ガントチャートの書式設定(`BarStyles` や個別タスクの `Bar` プロパティ)の操作は、VBAの裏側でCOMマーシャリングのオーバーヘッドを大量に発生させる。
パフォーマンスを極限まで高める鉄則
1. 画面描画の完全な抑制 (`ScreenUpdating`): 処理中はプロジェクトの再計算と画面描画を停止する。
2. オブジェクトの明示的解放: ループ内で生成されるRangeやCollectionなどのCOMオブジェクトは、スコープを厳格に管理し、不要になったら即座に `Nothing` を代入してメモリ解放を促す。
3. リンクタイプのビット演算的解析: `TaskLink.LinkType` プロパティが返す列挙型 (`PjTaskLinkType`) を正確に捉え、単一のタスクが複数の先行タスクを持つ場合の「優先順位」をアルゴリズムに組み込む。
—
2. 実装コード:依存関係に基づくバー自動スタイリング・エンジン
以下のコードは、アクティブなプロジェクト内の全タスクを走査し、その先行タスクの依存関係(FS, SS, FF, SF)を判定した上で、あらかじめ定義されたカスタムバーースタイルを動的に適用する実用モジュールである。
‘ ==============================================================================
‘ módulo名: modGanttVisualizer
‘ 概要: 依存関係のタイプに応じてガントチャートのバーのスタイルを動的に制御する
‘ 著作権: 伝説的チーフアーキテクト直伝コード
‘ ==============================================================================
Option Explicit
‘ 依存関係タイプのカスタム定義(Project内部定数に依存しない堅牢なマッピング)
Public Enum CustomLinkStyle
Style_Default = 0
Style_FS = 1 ‘ Finish-to-Start (通常: 青系)
Style_SS = 2 ‘ Start-to-Start (並行開始: 緑系)
Style_FF = 3 ‘ Finish-to-Finish (同時完了: オレンジ系)
Style_Complex = 4 ‘ 複合リンク (赤系警告)
End Enum
Sub ApplyDynamicGanttStyles()
Dim tsk As Task
Dim tLink As TaskLink
Dim linkTypeCount As Long
Dim primaryType As Long
Dim hasFS As Boolean, hasSS As Boolean, hasFF As Boolean, hasSF As Boolean
‘ 1. パフォーマンス最適化:画面更新と自動計算の停止
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Application.Calculation = pjManual
‘ 2. アクティブプロジェクトの存在確認
If ActiveProject Is Nothing Then
MsgBox “アクティブなプロジェクトが存在しません。”, vbCritical, “致命的エラー”
GoTo Cleanup
End If
‘ 3. タスクコレクションの走査
For Each tsk In ActiveProject.Tasks
‘ サマリータスクやマイルストーンを除外する場合はここでガードを入れる
If Not tsk Is Nothing Then
If Not tsk.Summary And tsk.Milestone = False Then
hasFS = False: hasSS = False: hasFF = False: hasSF = False
linkTypeCount = 0
‘ 先行タスク(Predecessors)のリンクを解析
For Each tLink In tsk.TaskLinks
‘ tLink.To === tsk の関係性を検証
If tLink.To.ID = tsk.ID Then
linkTypeCount = linkTypeCount + 1
Select Case tLink.LinkType
Case pjLinkFinishToStart
hasFS = True
Case pjLinkStartToStart
hasSS = True
Case pjLinkFinishToFinish
hasFF = True
Case pjLinkStartToFinish
hasSF = True
End Select
End If
Next tLink
‘ リンクの組み合わせに応じたスタイル決定ロジック
If linkTypeCount > 1 Then
‘ 複数の先行タスクを持つ場合は「複雑」と判定
Call SetTaskBarCustomStyle(tsk, Style_Complex)
ElseIf linkTypeCount = 1 Then
If hasSS Then
Call SetTaskBarCustomStyle(tsk, Style_SS)
ElseIf hasFF Then
Call SetTaskBarCustomStyle(tsk, Style_FF)
ElseIf hasSF Then
Call SetTaskBarCustomStyle(tsk, Style_SF)
Else
Call SetTaskBarCustomStyle(tsk, Style_FS)
End If
Else
‘ 先行タスクなし(独立タスク)
Call SetTaskBarCustomStyle(tsk, Style_Default)
End If
End If
End If
Next tsk
Cleanup:
‘ 4. 状態の復元とメモリ解放
Application.ScreenUpdating = True
Application.Calculation = pjAutomatic
Application.CalculateAll
MsgBox “ガントチャートの視覚的再構築が完了しました。”, vbInformation, “完了”
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “異常終了”
Resume Cleanup
End Sub
Private Sub SetTaskBarCustomStyle(ByRef tsk As Task, ByVal styleID As CustomLinkStyle)
‘ 注意: MS Projectの個別タスクバーのオーバーライド(Barプロパティ)は
C_BAR_SHAPE_RECTANGLE = 3 等の定数を使用するか、
‘ あらかじめ定義されたガントバーのスタイル番号(BarStyles)を割り当てる。
‘ ここでは実務上最も確実な「個別タスクのバー書式プロパティ」を操作する。
On Error Resume Next
Dim barShape As Long
Dim barColor As Long
Select Case styleID
Case Style_SS
barColor = 65280 ‘ 緑 (RGB: 0, 255, 0)
barShape = 3 ‘ 矩形
Case Style_FF
barColor = 423423 ‘ オレンジ系
barShape = 3
Case Style_Complex
barColor = 255 ‘ 赤 (警告色)
barShape = 3
Case Style_FS
barColor = 16711680 ‘ 青 (デフォルト系)
barShape = 3
Case Else
barColor = 8421504 ‘ グレー (独立タスク)
barShape = 3
End Select
‘ 個別タスクのガントバー書式を設定
‘ ※Projectのバージョンやビューの構成によりBarオブジェクトの仕様が異なるため
‘ エラーハンドリングを包含させて堅牢性を担保する。
Dim tBar As Bar
Set tBar = tsk.Bar
If Not tBar Is Nothing Then
tBar.MiddleColor = barColor
tBar.MiddleShape = barShape
End If
Set tBar = Nothing
On Error GoTo 0
End Sub
—
3. レガシー環境・外部システム連携におけるアーキテクチャ上の注意点
この自動化スクリプトを、企業内の基幹系システム(SAPやP6など)からエクスポートされた数万行規模のMppファイル群に対して適用する場合、以下のアーキテクチャ上の設計思想が必要になる。
A. イベント駆動型連携への昇華
ボタンクリックによる手動実行にとどめず、「外部からXML/MSPDI形式でプロジェクトファイルがインポートされた瞬間」や、「スケジュール再計算バッチの完了直後」にこのVBAプロシージャ(またはCOM経由の外部VB.NETラッパー)を走らせるパイプラインを構築すべきだ。これにより、PMOが朝出社した時点で、すべての依存関係の矛盾や特性が視覚化された状態を自動担保できる。
B. MS Projectのバージョン差異(2010〜2016〜Subscription)の吸収
MS Projectはデスクトップ版のバージョンによって、COMオブジェクトのプロパティ(特に `Bar` や `BarStyles` 周り)の内部実装が微妙に異なる。レガシーなProject 2010からモダンなMicrosoft Project(デスクトップクライアント)までを単一のコードベースで保守するためには、`On Error Resume Next` による優雅なフォールバックを実装し、プロパティが存在しない古い環境でもクラッシュしない「防御的プログラミング」が必須となる。
—
結言
VBAは単なる「マクロの記録ツール」ではない。それは、巨大なデスクトップアプリケーションの神経系に直接アクセスし、人間の認知限界を拡張するためのハイエンドなエンジニアリングツールである。
今回解説したガントチャートの動的描画制御を使いこなすことで、あなたの管理するプロジェクトから「見落としによる手戻り」は完全に駆逐されるだろう。コードの美しさとパフォーマンスの限界を追求する姿勢こそが、真のシニアエンジニアの証である。
