【テクニカル・上級編】【中級者向け】タスクの進捗率に応じた色分けをカスタムフィールドで実現する – Project VBA解析バイブル

スポンサーリンク
スポンサーリンク

MS Project VBA Mastery: Graphical Indicators による視覚的ロジックの動的構築とアーキテクチャ設計

プロジェクトの規模が数千、数万タスクに拡大したとき、マネージャーが求めるのは「データ」ではなく「洞察(Insight)」である。膨大な行の中に埋もれた遅延タスクを、いかにして人間の認知特性に適合する形で提示するか。

MS Projectにおいて、その解はカスタムフィールドと`GraphicalIndicator`プロパティの組み合わせにある。しかし、これを単なる「色の塗り替え」として実装するのは素人の仕事だ。シニアエンジニアが向き合うべきは、プロジェクトの計算エンジンへの負荷、オブジェクトのライフサイクル管理、そしてレガシーな環境下でも破壊的変更を起こさない堅牢なコード設計である。

本稿では、タスクの進捗率(% Complete)に基づき、視覚的なインジケーターをVBAから動的に定義・制御する、極限の自動化手法を解説する。

1. Graphical Indicator の本質的理解

`GraphicalIndicator` は、単なるセルの背景色ではない。それは、プロジェクトの計算エンジンが各タスクの属性を評価し、その結果をUIレイヤーへマッピングするための「条件付き書式エンジン」の命令セットである。

VBAからこれを操作する場合、単に値を代入するのではなく、`CustomField` オブジェクトの内部構造にアクセスし、`GraphicalIndicators` コレクションに対して、論理式と視覚的属性(色、アイコン、テキスト)のペアを構築していくプロセスとなる。

考慮すべき設計上の制約

  • 計算コスト: カスタムフィールドに複雑な数式を埋め込み、かつ大量のインジケーターを設定すると、再計算(Recalculation)のたびにCPUリソースを消費する。
  • 原子性(Atomicity): インジケーターの設定中にエラーが発生した場合、フィールドが中途半端な状態で残る可能性がある。設定処理は、既存の設定をクリアしてから再構築する「全削除・全再構築」のパターンが最も安全である。

2. 高信頼性実装:進捗率によるインジケーター自動設定

以下に、タスクの進捗率に基づき、「遅延(赤)」「注意(黄)」「順調(緑)」を動的に割り当てる実装例を示す。ここでは、メモリリークを防ぐための明示的なオブジェクト解放と、実行速度を最大化するためのアプリケーション状態の制御を組み込んでいる。

Option Explicit

' ==============================================================================
' Module: modProjectAutomation
' Description: MS Project Custom Field Graphical Indicator Setup
' Author: Chief Architect
' ==============================================================================

''' <summary>
''' タスクの進捗率に基づいたカスタムフィールドのインジケーターを構築する。
''' </summary>
''' <param name="fieldName">対象となるカスタムフィールドの名前</param>
Public Sub SetupProgressVisualizer(ByVal fieldName As String)
    Dim app As MSProject.Application
    Set app = MSProject.Application
    
    Dim proj As MSProject.Project
    Set proj = app.ActiveProject
    
    Dim cf As MSProject.CustomField
    Dim gi As MSProject.GraphicalIndicator
    Dim i As Integer
    
    ' 1. パフォーマンス最適化: 画面更新と計算を停止
    ' 大規模プロジェクトでは、この処理の有無が実行時間に数倍の差を生む
    app.ScreenUpdating = False
    app.Calculation = pjManual
    
    On Error GoTo ErrorHandler

    ' 2. 対象フィールドの特定
    Set cf = Nothing
    For Each cf In proj.CustomFields
        If cf.Name = fieldName Then Exit For
    Next cf
    
    If cf Is Nothing Then
        Err.Raise vbObjectError + 513, "SetupProgressVisualizer", "指定されたフィールド名が見つかりません: " & fieldName
    End If

    ' 3. 既存設定のクリーンアップ
    ' 既存のインジケーターが残っていると、条件が重複して予期せぬ挙動を招く
    ' インジケーターのコレクションを一度クリアする
    Do While cf.GraphicalIndicators.Count > 0
        cf.GraphicalIndicators.Remove 1
    Loop

    ' 4. 数式の注入
    ' ここでは進捗率 [% Complete] を評価対象とする
    cf.Formula = "[% Complete]"
    cf.Type = pjNumber ' 数値型として定義

    ' 5. Graphical Indicators の構築
    ' 条件: 0-25% (赤), 25-75% (黄), 75-100% (緑)
    
    ' --- Case 1: Low Progress (Red) ---
    Set gi = cf.GraphicalIndicators.Add
    With gi
        .Condition = " < 25"
        .Color = pjRed
        .Icon = pjNone ' 必要に応じて pjStop 等のアイコンを指定可能
    End With

    ' --- Case 2: Medium Progress (Yellow) ---
    Set gi = cf.GraphicalIndicators.Add
    With gi
        .Condition = " >= 25 And < 75"
        .Color = pjYellow
        .Icon = pjNone
    End With

    ' --- Case 3: High Progress (Green) ---
    Set gi = cf.GraphicalIndicators.Add
    With gi
        .Condition = " >= 75"
        .Color = pjGreen
        .Icon = pjNone
    End With

    ' 完了通知
    Debug.Print "Successfully configured: " & fieldName

CleanExit:
    ' 6. 環境の復元
    ' エラーが発生しても必ず実行されるよう、Exitの直前に配置
    app.Calculation = pjAutomatic
    app.ScreenUpdating = True
    
    ' オブジェクトの明示的な解放 (Memory Management)
    Set gi = Nothing
    Set cf = Nothing
    Set proj = Nothing
    Set app = Nothing
    Exit Sub

ErrorHandler:
    MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical, "System Error"
    Resume CleanExit
End Sub

''' <summary>
''' エントリポイント
''' </summary>
Public Sub Main()
    ' 実行例: "Progress_Status" という名前のカスタムフィールドを対象とする
    ' 事前にフィールドが作成されているか、あるいは作成ロジックを別途用意すること
    Call SetupProgressVisualizer("Progress_Status")
End Sub

3. アーキテクトの視点:実戦における最適化と保守

このコードを単なるスクリプトとして終わらせてはならない。エンタープライズ環境にデプロイする際は、以下の3点を考慮せよ。

I. オブジェクト・ライフサイクルの厳格な管理

VBAはCOM(Component Object Model)を介してMS Projectを操作する。`Set cf = Nothing` のように、使用したオブジェクトを明示的に解放することは、特に長時間稼働するアドインや、他のアプリケーション(ExcelやAccess)と連携するシステムにおいて、メモリリークによるクライアントの不安定化を防ぐための鉄則である。

II. 計算エンジンのオーバーヘッド管理

`app.Calculation = pjManual` の使用は、単なるテクニックではなく、エンジニアリングとしての判断だ。カスタムフィールドの設定変更は、プロジェクト内の全タスクの再計算をトリガーする。これを `True`(Automatic)のまま実行することは、大規模プロジェクトにおいて数秒から数分の「フリーズ」をユーザーに強いることと同義である。

III. レガシー環境への耐性

MS Projectのバージョンによって、`GraphicalIndicators.Add` メソッドの挙動や、利用可能なアイコン定数が微妙に異なる場合がある。
もし、古いバージョンのMS Projectをサポートする必要がある場合は、`On Error Resume Next` を多用するのではなく、`Err.Number` を監視し、条件分岐によって「フォールバック(代替手段)」を実行する設計(例:インジケーターが使えない場合は、単に数値を表示するだけにする)を組み込むべきだ。

結論

`GraphicalIndicator` の自動化は、プロジェクト管理ツールを「記録のための道具」から「意思決定のためのプラットフォーム」へと昇華させる。

優れたエンジニアは、コードの短さを競わない。コードが実行された後のメモリの状態、計算エンジンの負荷、そしてユーザーの認知負荷までを設計の射程に収める。この極限の視点こそが、レガシーなシステムを現代のビジネススピードに適合させる唯一の道である。

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