こんにちは!プロジェクト管理の現場で、日々スケジュールやコストの調整に頭を悩ませていませんか?
「マクロの記録」はなんとなく使えるようになったけれど、そこから一歩進んで、実務でバリバリ使える自動化ツールを作りたい――。そんなあなたに向けて、今回はMS Project VBAの真髄とも言えるテーマをお届けします。
今回のテーマは「リソースの単価レートテーブルをVBAで動的に切り替える運用自動化」です。
プロジェクトが進むにつれ、「初期フェーズ(レートA)」「実行フェーズ(レートB)」「保守フェーズ(レートC)」と、同じ人間であってもコストの単価が変わることはよくありますよね。これを手動で一人ひとり切り替えていると、ミスも起きるし時間も溶けます。
ここをクリアすれば、Project VBAの基本と「リソース・コスト管理の自動化」の仕組みはバッチリです!優しく、そして本質的な部分までしっかりと解説していきますので、ぜひ最後までついてきてくださいね。
—
1. MS Projectにおける「レートテーブル」の基本と落とし穴
まず、Projectの裏側の仕組みを少しだけ覗いてみましょう。
MS Projectのリソースには、単価を最大5つ(A〜E)まで持たせることができます(これを「レートテーブル」と呼びます)。
GUI(画面)で操作する場合、[リソース シート]ビューを開き、リソースをダブルクリックして[コスト]タブを開き、レートテーブルのタブ(A, B, C…)を切り替えて単価を入力しますよね。さらに、タスク側の[リソース名]に `山田[2]` のように記述することで、「このタスクにはレートBを適用する」と指定できます。
【ここが罠!】VBAでのアプローチの難しさ
初学者が陥りがちなのが、「画面と同じノリでVBAからセルのように直接レートテーブルを書き換えようとする」ことです。
実は、Project VBAにおいてリソースのコストレートテーブルは、通常のセルプロパティのように直感的にはアクセスできません。`CostRateTable` というプロパティを正しく理解し、タスクの割り当て(Assignment)単位、あるいはリソース単位で適切に指示を出してあげる必要があります。
—
2. 今回目指す自動化ツールの仕様
プロジェクトのフェーズ(カスタムフィールドやフラグ、あるいは特定のタスク群)に応じて、一括して適用するレートテーブル(A、B、C)を切り替えるVBAマクロを作成します。
今回はシンプルかつ実用的に、「プロジェクト全体の全タスクの割り当てリソースに対して、指定したレートテーブル(A, B, or C)を強制適用する」というエンジンを作ってみましょう。
—
3. 実装コード:レートテーブル一括切替マクロ
それでは、実際のコードを見ていきましょう。開発タブの「Visual Basic」Editorを開き、標準モジュールに以下のコードを貼り付けてください。
プログラミング初心者でも迷わないよう、一行ナマのコードにならないよう丁寧にコメントを入れています。
‘ ==============================================================================
‘ 処理名 : 全リソース割り当てのコストレートテーブル一括切替マクロ
‘ 概要 : プロジェクト内のすべてのタスク割り当て(Assignment)に対し、
‘ 指定したレートテーブル(A, B, C)を強制適用します。
‘ 開発者 : あなたの先輩エンジニア
‘ ==============================================================================
Sub SwitchCostRateTable()
Dim tsk As Task
Dim asn As Assignment
Dim targetTable As String
Dim userResponse As VbMsgBoxResult
‘ 1. ユーザーにどのレートテーブルに切り替えるか入力させる
targetTable = UCase(Trim(InputBox( _
“切り替えるレートテーブルを半角アルファベットで入力してください。” & vbCrLf & _
“(A: 初期フェーズ / B: 実行フェーズ / C: 保守フェーズ)”, _
“レートテーブル切替ツール”, “A”)))
芭
‘ 入力値のバリデーション(A, B, C以外は弾く)
If targetTable <> “A” And targetTable <> “B” And targetTable <> “C” Then
MsgBox “無効な値が入力されたため、処理を中断します。” & vbCrLf & _
“「A」「B」「C」のいずれかを入力してください。”, vbCritical, “入力エラー”
Exit Sub
End If
‘ 2. 実行確認のメッセージボックス
userResponse = MsgBox( _
“プロジェクト内の全タスクのコストレートを 「” & targetTable & “テーブル」 に一括変更します。” & vbCrLf & _
“よろしいですか?”, _
vbYesNo + vbQuestion, “確認:レートテーブル切替”)
If userResponse = vbNo Then
MsgBox “処理をキャンセルしました。”, vbInformation, “キャンセル”
Exit Sub
End If
‘ 3. エラーハンドリングの有効化(万が一のデータ破損を防ぐプロの作法)
On Error GoTo ErrorHandler
‘ 処理速度向上のための画面描画停止(※Project VBAでは慎重に扱うが、大量データ時は有効)
‘ Application.ScreenUpdating = False ‘ ※環境により挙動が異なるためコメントアウト気味に
Dim updateCount As Long
updateCount = 0
‘ 4. プロジェクト内の全タスクをループ
For Each tsk In ActiveProject.Tasks
‘ 念のため、空行(タスクが存在しない行)をスキップ
If Not tsk Is Nothing Then
‘ タスクに割り当てられているリソース(Assignments)をループ
For Each asn In tsk.Assignments
‘ コストレートテーブルを設定
‘ CostRateTableプロパティには “A”, “B”, “C” などの文字列を渡す
Select Case targetTable
Function_Skip: ‘ 内部ラベル
asn.CostRateTable = pjAssignmentCostRateTableA ‘ 組み込み定数を使う場合
‘ 文字列直接指定の方が柔軟な場合もあるため、今回は分かりやすく文字列で制御
End Select
‘ 実際に文字列で代入する場合(pjAssignmentCostRateTable… の代わりに直接 “A”〜を描写)
Select Case targetTable
Case “A”: asn.CostRateTable = pjAssignmentCostRateTableA
Case “B”: asn.CostRateTable = pjAssignmentCostRateTableB
Case “C”: asn.CostRateTable = pjAssignmentCostRateTableC
End Select
updateCount = updateCount + 1
Next asn
End If
Next tsk
‘ 5. 完了報告
‘Application.ScreenUpdating = True
MsgBox “処理が完了しました!” & vbCrLf & _
“更新された割り当て数: ” & updateCount & ” 件”, vbInformation, “成功”
Exit Sub
ErrorHandler:
‘Application.ScreenUpdating = True
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”
End Sub
—
4. コードの深掘り解説:ここがエンジニアの腕の見せ所
初心者から一歩抜け出すために、このコードの重要なポイントを3つに絞って解説します。
① タスク(Task)と割り当て(Assignment)の階層構造を理解する
MS Projectのデータ構造は、Excelのように単純な「行と列」ではありません。
- Task(タスク):「何をやるか」の入れ物
- Resource(リソース):「誰が・何が」やるか
- Assignment(割り当て):「どのタスクに、どのリソースが、どれくらい関わるか」の交差点
コストレートテーブルは、リソース単体というよりも「そのタスクにその人がアサインされている状態(Assignment)」ごとに保持されます。そのため、`For Each tsk In ActiveProject.Tasks` の中で、さらに `For Each asn In tsk.Assignments` と二重のループを回す必要があるのです。ここがExcel VBAとの決定的な違いであり、につまづきやすいポイントです。
② 安全性を高めるバリデーションとEnum(列挙体)の活用
コード内にある `pjAssignmentCostRateTableA` といった見慣れない英字は、MS Projectがあらかじめ用意してくれている「定数(Enum)」です。これを使うことで、タイポ(打ち間違い)によるバグを防ぐことができます。
また、処理の最初に `InputBox` で入力を受け付け、想定外の文字が入ってきたら即座に `Exit Sub` で弾く。こうした「ディフェンシブなプログラミング」ができるようになると、現場で信頼されるツールエンジニアになれます。
—
5. 現場でよくあるエラーと回避のコツ
1. 「割り当て(Assignment)が一件もありません」というエラー
- 原因: タスクにリソースが一切アサインされていない状態で `tsk.Assignments` を回そうとすると、NULL参照エラーや予期せぬ挙動をすることがあります。
- 対策: 今回のコードでは `If Not tsk Is Nothing Then` でタスクの存在チェックを入れていますが、さらにリソースがアサインされているか(`tsk.ResourceNames <> “”` など)を事前にチェックする条件を挟むと、より堅牢になります。
2. 変更したのにコストが再計算されない?
- 原因: VBAでプロパティを変更した際、Projectの画面側で再計算(再スケジュール)が走るタイミングがズレることがあります。
- 対策: マクロの最後に `CalculateAll` メソッドを挟むことで、プロジェクト全体のコストとスケジュールを强制的に再計算させることができます。必要に応じてコードの最後に `CalculateAll` を追加してみてください。
—
まとめ:ここをクリアすればProject VBAは怖くない!
今回は、リソースの単価レートテーブルを動的に切り替える運用自動化について解説しました。
- Task と Assignment のオブジェクト階層の違いを把握する
- 入力値のバリデーションやエラーハンドリングを仕込んで「壊れないツール」にする
この2つを意識するだけで、あなたが書くVBAのコードの質はプロフェッショナル水準へと劇的に跳ね上がります。
「マクロの記録」の枠を飛び出し、自分の手でプロジェクト管理の歯車をガッチリ噛み合わせていく感覚は、本当にエキサイティングですよ。ぜひ、ご自身のプロジェクト環境でも試してみてくださいね。
それでは、次回の応用編でお会いしましょう!バッチリ自動化をキメて、定時で帰りましょう!
