【入門編】ガントチャートの「制約インジケーター」をVBAで操作し、進捗報告を効率化 – Project VBA解析バイブル

スポンサーリンク

こんにちは!Project VBAの世界へようこそ。
マクロの記録ボタンを押すだけの日常から一歩踏み出し、「自分の手でプロジェクトの時間をコントロールしたい」と願うあなたを、今日は心から歓迎します。

私たちが普段何気なく眺めているMicrosoft Projectのガントチャート。そこには「ASAP(できる限り早く)」や「ALAP(できる限り遅く)」といったスケジュール計算エンジンの心臓部である「制約条件」が潜んでいます。

進捗報告のたびに、どのタスクにどんな制約がかかっていて、どこがクリティカルパスなのかを目視で確認し、資料に手動でまとめる……そんな不毛な残業は今日で終わりです。

今回は、「制約インジケーターをVBAで華麗に判定し、一瞬で進捗報告用のカスタムビューを生成する実務自動化テクニック」を伝授します。ここをクリアすれば、あなたのProject VBAの基本と「オブジェクトを操る感覚」はバッチリものになりますよ。それでは、深淵なるエンジニアリングの世界へ一緒に出発しましょう!

—

1. なぜ「制約条件」をVBAで操る必要があるのか?

Microsoft Projectは非常に優秀なスケジュールエンジンです。タスク間の依存関係(先行・後続)を自動計算してくれますが、実務では現場の都合で「このタスクは〇月〇日以降にしか始められない(開始日固定・SNET等)」といった「制約(Constraint)」がガシガシかけられます。

これを放置して進捗報告を作ると、予期せぬスケジュール遅延の真犯人を見落とします。
人間が一つひとつのタスクプロパティを開いて制約を確認するのは、砂漠で針を探すようなもの。だからこそ、VBAにこう命令するのです。

> 「おい、全タスクを巡回して、デフォルト(ASAP)以外の強固な制約がかかっているやつをあぶり出してくれ。そして、そいつらだけを浮き彫りにする報告用ビューを作ってくれ」

このロジックを組めるようになると、あなたのプロジェクト管理のスピードは文字通り「10倍」に跳ね上がります。

—

2. Project VBAの基本:タスクの「ライフサイクル」を捉える

Excel VBAと違い、Project VBAには独特の「階層構造(オブジェクトモデル)」があります。
まずは、今回私たちが操作する世界地図を確認しておきましょう。

Application (Project本体)
└── ActiveProject (今開いているプロジェクト)
└── Tasks (タスクの集合体)
└── Task (個別のタスク)
├── .Name (タスク名)
├── .ConstraintType (制約の種類)
└── .ConstraintDate (制約の日付)

Excelの「セル(Range)」に相当するのが、Projectにおける「タスク(Task)」です。すべてのタスクを `For Each` ループで1つずつ取り出し、そのプロパティを覗き見していくのがProject VBAの基本中の基本となります。

—

3. 実装コード:制約を検知し、カスタムビューを生成する

それでは、実際の現場でそのままコピペして使える実用コードを公開します。
このマクロは、以下の2ステップを自動で行います。
1. 制約の判定: デフォルト(ASAPまたはALAP)以外の「厳しい制約」がかかっているタスクを検知。
2. ビューの自動生成・切り替え: 抽出されたタスク群がひと目でわかるカスタム「フィルタ」と「ビュー」を動的に作成・適用。

VBE(Visual Basic Editor)を開き、標準モジュールに以下のコードを貼り付けてください。

‘ ==============================================================================
‘ テーマ: ガントチャートの「制約インジケーター」をVBAで操作し進捗報告を効率化する
‘ 著者: チーフアーキテクト
‘ ==============================================================================
Sub GenerateConstraintReportView()
Dim tsk As Task
Dim constrainedCount As Long
Dim reportViewName As String
Dim reportFilterName As String

reportViewName = “【自動生成】制約タスク進捗レポート”
reportFilterName = “【自動生成】特殊制約フィルター”

‘ エラーハンドリングの基本:プロジェクトが開かれていない場合の対策
If ActiveProject Is Nothing Then
MsgBox “アクティブなプロジェクトがありません。”, vbCritical, “エラー”
Exit Sub
End If

constrainedCount = 0

‘ 1. 既存の同名カスタムフィルタ・ビューがあれば一旦削除(クリーンアップ)
On Error Resume Next
ViewList(reportViewName).Delete
FilterList(reportFilterName).Delete
On Error GoTo 0

‘ 2. カスタムフィルタの作成
‘ ※ここでは「ASAP(できる限り早く)」および「ALAP(できる限り遅く)」以外の制約を検知対象とします
‘ pjConstraintAsap = 0, pjConstraintAlap = 1
FilterEdit Name:=reportFilterName, _
TaskFilter:=True, _
Create:=True, _
OverwriteExisting:=True, _
Fieldname:=”Constraint Type”, _
Test:=”<>“, _
Value:=”できる限り早く”, _
ShowInMenu:=False

‘ 3. タスクをループして、制約がかかっているものをログ出力(イミディエイトウィンドウへ)
Debug.Print “=== 特殊制約タスクの検出リスト ===”
For Each tsk In ActiveProject.Tasks
‘ サマリータスク(親タスク)やマイルストーンを除外したい場合はここで条件分岐を追加可能
If Not tsk Is Nothing Then
‘ 制約タイプがASAPでもALAPでもない場合を「特殊制約」と定義
If tsk.ConstraintType <> pjConstraintAsap And tsk.ConstraintType <> pjConstraintAlap Then
constrainedCount = constrainedCount + 1
Debug.Print “タスク名: ” & tsk.Name & ” / 制約日: ” & tsk.ConstraintDate

‘ ここでフラグ用のカスタムフィールド(例: Text1)にマークを入れることも実務では有効です
tsk.Text1 = “要確認制約”
Else
tsk.Text1 = “”
End If
End If
Next tsk

‘ 4. 新しいビュー(ガントチャート+作成したフィルタ)の生成
‘ 既存の「ガント チャート」をベースにカスタムビューを定義します
ViewEditSingle Name:=reportViewName, _
Create:=True, _
NewWindow:=True, _
Title:=reportViewName, _
Screen:=pjScreenGantt, _
SinglePane:=True, _
Table:=”&Standard”, _
Filter:=reportFilterName, _
Group:=”No Group”

‘ 5. 生成されたビューへ切り替え
ViewApply Name:=reportViewName

‘ 完了メッセージ
MsgBox “進捗報告用ビューの生成が完了しました!” & vbCrLf & _
“検知された制約タスク数: ” & constrainedCount & “件”, _
vbInformation, “自動化完了”

End Sub

—

4. コードの解説:ここがエンジニアのこだわりポイント!

初心者の方が「おっ」とつまずきやすいポイントを、優しく紐解いていきましょう。

① `ActiveProject Is Nothing` によるガード

Project VBAでは、プロジェクトが1つも開いていない状態でマクロを実行すると、容赦なく実行時エラー(オブジェクト変数がいません)が発生してVBEに強制送還されます。プログラミングの第一歩は「予期せぬ無の状態」から身を守ること。このガードを最初に置くのがプロの作法です。

② 制約タイプの定数(`pjConstraintAsap` など)

Projectには、スケジュールを縛る数多くの制約(指定日開始、指定日終了など)が存在します。今回は「システムが勝手に計算して良い状態(ASAP/ALAP)」以外のものをすべて「人間の意思や外部要因でガチガチに固められた制約」と見なし、抽出の網にかけました。この判定ロジックにより、スケジュール遅延のボトルネックが一発で浮き彫りになります。

③ 既存の同名オブジェクトのクリーンアップ

何度もマクロを実行すると、「すでに同じ名前のフィルターがあります」というエラーに直面します。これを防ぐために、あらかじめ `On Error Resume Next` を使って古いものを消去してから新しく作り直す(イデポテント / 冪等性の担保)という、実務で必須のテクニックを組み込んでいます。

—

5. 陥りやすいエラーと回避のコツ

1. 「実行時エラー ‘1100’: 引数が正しくありません」と言われる

  • 原因: 日本語版のMicrosoft Projectを使用している場合、`FilterEdit` メソッド内で指定するフィールド名や値(`”できる限り早く”` など)が、お使いの環境のローカライズ(言語設定)と一致していない可能性があります。
  • 対策: 一度マクロの記録機能を使って、手動でフィルターを作成した際のコードを吐き出し、そこに記述されている正確な文字列を確認してください。

2. サマリータスク(親タスク)まで抽出されてしまう

  • 対策: プロジェクトの要約タスク(ID 0)や、子を持つ親タスクは自動的に制約が入り込むことがあります。コード内の `If Not tsk Is Nothing Then` の中に `If tsk.Summary = False Then` という条件を加えると、より現場で実用的な「末端の実行タスクのみ」を対象にできます。

—

おわりに:あなたの手で、プロジェクトを「動かす」

いかがでしたでしょうか?
「制約インジケーター」という一見地味な機能も、VBAのレンズを通して見れば、プロジェクトの健康状態を測る強力なセンサーに早変わりします。

マクロの記録から脱却し、自分の手でオブジェクトを定義し、動かす。この快感を一度知ってしまったら、もう元の手作業には戻れなくなるはずです。

「ここをもっとこうしたい」「こんな応用はできる?」といった疑問があれば、いつでもまたこのブログを訪れてください。あなたのVBAライフが、最高にエキサイティングで効率的なものになることを、チーフアーキテクトとして心から応援しています!

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