【入門編】【中級者向け】リソースの単価計算をカスタムフィールドで自動化するロジック – Project VBA解析バイブル

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

Project VBAを掌握する極限の知見:カスタムフィールドに「動的な計算ロジック」を宿らせる

こんにちは。現場の設計図(アーキテクチャ)を描き、自動化の力でプロジェクトの停滞を打ち破るチーフアーキテクトです。

マクロの記録機能を使って、「あ、ボタンを押せばこの操作ができるんだ」と感動した時期は、誰にでもあります。それは素晴らしい第一歩です。しかし、もしあなたが「毎回マクロを走らせないと値が更新されない」「リソースが増えるたびにコードを書き直している」といった壁にぶつかっているなら、それはあなたが「単なる操作の自動化」から「システムの自動化」へと進化する境界線に立っている証拠です。

今日、皆さんに伝授するのは、Microsoft Projectの真の力を引き出すテクニック。それは、「VBAを使って、カスタムフィールドの中に『計算式(Formula)』を動的に書き込む」という手法です。

これをマスターすれば、あなたは「値を書き込む人」ではなく、「プロジェクトのルールを定義する設計者」になれるはずですよ。

1. なぜ「値を書き込む」のではなく「式を書き込む」のか?

ここが、初級者と中級者を分ける決定的な境界線です。

多くの初心者は、以下のようなアプローチを取りがちです。
1. リソースの属性(ランクなど)を読み取る。
2. VBA内で計算を行う。
3. 計算結果をカスタムフィールドに「値」として書き込む。

これでは不十分なのです。なぜなら、「リソースの属性が後から変更されたとき、計算結果が古いまま残ってしまう」からです。

プロのエンジニアが目指すべきは、「リソースの属性が変われば、カスタムフィールドの値も即座に、自動的に再計算される仕組み」です。そのために、VBAの仕事は「計算結果を書き込むこと」ではなく、「カスタムフィールドに『こう計算せよ』という命令(式)をセットすること」に変わります。

2. 設計図:リソース単価の動的計算ロジック

今回のシナリオを定義しましょう。

  • 前提条件:
  • `Text1` フィールドに、リソースの「ランク(Senior, Middle, Junior)」が入っている。
  • `Cost1` フィールドに、「計算後の単価」を表示させたい。
  • ロジック:
  • `Senior` なら 5,000円
  • `Middle` なら 3,000円
  • `Junior` なら 1,500円
  • それ以外は 1,000円

このロジックを、VBAを使って `Cost1` フィールドの「数式プロパティ」に流し込みます。

3. 実装:魂のコード・エグゼキューション

それでは、実際に動くコードを見ていきましょう。このコードは、単に値をセットするのではなく、Projectの計算エンジンに「ルール」をインストールするものです。

Option Explicit

''' <summary>
''' リソースのカスタムフィールドに、ランクに基づいた動的なコスト計算式を設定します。
''' </summary>
Sub SetupResourceCostFormula()
    Dim pjApp As MSProject.Application
    Set pjApp = Application
    
    Dim fd As CustomFieldDefinition
    Dim targetFieldIndex As Integer
    Dim formulaString As String
    
    ' --- 設定エリア ---
    ' 今回はリソース(Resource)の Cost フィールド(pjCost)を対象にします
    ' Index 1 は Cost1 フィールドを指します
    targetFieldIndex = 1 
    
    ' 構築する計算式(IIf関数をネストして条件分岐を作ります)
    ' Projectの数式内では、フィールド名は [Text1] のようにブラケットで囲む必要があります。
    ' 注意:VBAの文字列内でダブルクォーテーションを使う場合は、"" と2つ重ねる必要があります。
    formulaString = "IIf([Text1]=""Senior"", 5000, " & _
                    "IIf([Text1]=""Middle"", 3000, " & _
                    "IIf([Text1]=""Junior"", 1500, 1000)))"
    ' ------------------

    On Error GoTo ErrorHandler

    ' 1. カスタムフィールドの定義を探しに行きます
    ' CustomFieldDefinitions コレクションをループして、適切な型とインデックスを見つけます
    For Each fd In pjApp.CustomFieldDefinitions
        ' リソース(pjResource)かつ、指定したインデックスのコスト(pjCost)フィールドか判定
        If fd.Type = pjResource And fd.Field = pjCost And fd.Index = targetFieldIndex Then
            
            ' 2. 既存の数式をクリアし、新しい数式を流し込む
            ' ここが「設計」の核心です。
            fd.Formula = formulaString
            
            MsgBox "成功: リソースの Cost" & targetFieldIndex & " に計算式をセットしました。" & vbCrLf & _
                   "設定された式: " & formulaString, vbInformation
            Exit Sub
        End If
    Next fd

    MsgBox "エラー: 指定されたカスタムフィールドが見つかりませんでした。", vbExclamation
    Exit Sub

ErrorHandler:
    MsgBox "予期せぬエラーが発生しました: " & Err.Description, vbCritical
End Sub

4. アーキテクトの視点:陥りやすい「3つの罠」

このコードを動かそうとして、多くの人が躓くポイントがあります。ここを理解していれば、あなたはもう初心者ではありません。

① ダブルクォーテーションの地獄(String Escaping)

Projectの数式内で `”Senior”` と書きたい場合、VBAの文字列として定義すると `”””Senior”””` のように複雑な記述が必要になります。
上記のコードでは、`””Senior””` と記述しています。これは「VBAの文字列の中で、1つのダブルクォーテーションを表現する」ための作法です。ここを間違えると、数式が正しく認識されず、エラーになります。

② オブジェクトの「型」の不一致

`CustomFieldDefinitions` は、タスク用、リソース用、プロジェクト用が混在しています。
`fd.Type = pjResource` という判定を入れずに、ただインデックスだけで指定してしまうと、「タスクのコストフィールドを書き換えるつもりが、リソースのテキストフィールドを壊してしまった」という事故が起こります。必ず `Type` と `Field`(pjCostやpjTextなど)をセットで確認してください。

③ 計算エンジンの遅延

数式をセットした直後、画面上の値が更新されないことがあります。これはProjectの計算エンジンが「まだ計算の必要がない」と判断しているためです。
もしコード内で即座に計算結果を使いたい場合は、`Application.Calculate` を呼び出す癖をつけておきましょう。

5. まとめ:ここをクリアすれば、基本はバッチリです

今回の手法の凄さは、「一度マクロを実行すれば、あとは人間が一切何もしなくても、Projectが勝手に計算を続けてくれる」という点にあります。

1. マクロの記録レベル: 「AをBに書き換える」という点の操作。
2. エンジニアレベル: 「Aが変わればBが自動で変わる」という線(ロジック)の構築。

この「線」の概念が持てたなら、あなたのProject VBAスキルは一段上のステージへ到達しました。次は、この数式をさらに複雑な条件(例えば、工数や期間を掛け合わせるなど)に拡張していくのも面白いでしょう。

さあ、恐れずにコードを書いてみてください。失敗は、より堅牢なアーキテクチャを築くための大切なデータに過ぎません。

応援していますよ。

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