こんにちは。今日は、Microsoft Projectを単なる「予定表」から、プロジェクトの「守護神」へと進化させるための、少し踏み込んだテクニックについてお話ししましょう。
「マクロの記録」を使って、ボタン一つで色を変えたり、文字を入力したりすることには慣れてきた。でも、プロジェクトのスケジュールが動くたびに、「あ、このマイルストーンの納期を固定し忘れていた!」とヒヤヒヤすることはありませんか?
今日は、そんな不安を解消するために、「特定のフラグが立ったマイルストーンに対して、一括で『終了日固定制約』を叩き込む自動化ツール」を作っていきましょう。
ここをマスターすれば、あなたは「ただマクロが書ける人」から、「プロジェクトの計算ロジックを制御できるエンジニア」への一歩を踏み出すことになりますよ。
1. なぜ「日付を入れるだけ」では足りないのか?
ここが、初級者と中級者を分ける最も重要な境界線です。
多くのユーザーは、納期を守らせたいとき、タスクの「終了日」のセルに直接日付を入力します。しかし、Microsoft Projectの計算エンジン(スケジューリング・エンジン)にとって、それは単なる「一時の希望」に過ぎないことが多いのです。
「日付入力」と「制約(Constraint)」の違い
- 日付だけを入力した場合:
前後のタスクとの関係(先行・後続)が変更されたり、リソースの制約が入ったりすると、Projectは「あ、このタスクは後ろにずらしたほうが合理的だな」と判断し、入力した日付を勝手に書き換えてしまいます。
- 「制約(Constraint)」を設定した場合:
これは計算エンジンに対する「命令」です。「何があっても、この日に終わらせろ(あるいは、この日より後にずらすな)」という、ロジックのルールを定義することになります。
今回私たちが実装するのは、後者の「制約(ConstraintType)」の制御です。これこそが、プロジェクトの納期を死守するためのプロの手法です。
2. 設計図:どのような仕組みを作るか
いきなりコードを書く前に、設計図(アルゴリズム)を整理しましょう。エンジニアの仕事は、コードを書くことではなく「設計すること」です。
今回作るツールの動きはこうです:
1. ユーザーの準備:
- マイルストーンの「テキスト1」列に、`FIX` という文字を入れる(これがフラグになります)。
- 「日付1」列に、守るべき「納期」を入力しておく。
2. VBAの動作:
- プロジェクト内の全タスクを一つずつチェックする。
- もし「テキスト1」が `FIX` だったら……
- そのタスクの制約タイプを「Must Finish On(必ずこの日に終了)」に書き換え、制約日を「日付1」に設定する。
3. 完了:
- 一瞬で、すべての重要納期が「ガチガチに固定」される。
3. 実装:魂を込めたコード例
それでは、コードを見ていきましょう。コピー&ペーストして動かすこともできますが、ぜひコメントを読みながら「なぜこう書くのか」を感じ取ってください。
Option Explicit
''' <summary>
''' マイルストーンの納期を強制適用するプロシージャ
''' テキスト1列に "FIX" と入力され、日付1列に納期が入っているタスクを対象とする
''' </summary>
Sub ApplyMilestoneConstraints()
Dim t As Task
Dim count As Integer
count = 0
' 画面更新を停止してパフォーマンスを向上させる(大規模プロジェクト対策)
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
' プロジェクト内の全タスクをループ処理
For Each t In ActiveProject.Tasks
' タスクが存在しない(空行)場合はスキップ
If Not t Is Nothing Then
' --- 条件判定のロジック ---
' Text1列に "FIX" というフラグが立っているか?
If t.Text1 = "FIX" Then
' 日付1列に有効な日付が入っているか確認
If t.Date1 <> "N/A" Then
' 【ここが心臓部】制約タイプを「Must Finish On(必ずこの日に終了)」に変更
' pjMustFinishOn = 3 (定数)
t.ConstraintType = pjMustFinishOn
' 制約日を、日付1列に入力された値に設定
t.ConstraintDate = t.Date1
count = count + 1
Else
' フラグはあるのに日付がない場合は、警告としてセルに色をつける等の処理も可能
' 今回はシンプルにスキップ
End If
End If
End If
Next t
' 画面更新を再開
Application.ScreenUpdating = True
MsgBox count & " 件のマイルストーンに納期固定制約を適用しました。", vbInformation, "完了"
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox "エラーが発生しました: " & Err.Description, vbCritical, "エラー"
End Sub
コードのポイント解説
1. `If Not t Is Nothing Then`:
Projectのタスクリストには、途中に空行が含まれることがあります。空のオブジェクトに対してプロパティを操作しようとするとエラーで止まってしまうため、この一行は「エンジニアの嗜み」として必ず入れましょう。
2. `pjMustFinishOn`:
これはProject VBAが定義している「定数」です。数字の `3` と書いても動きますが、後でコードを読み返したときに「何をしているか」を一目で理解するために、名前(定数)を使いましょう。
3. `Application.ScreenUpdating`:
タスクが数千件あるプロジェクトでは、一つずつ処理するたびに画面がチカチカ動くと、それだけで計算リソースを食いつぶします。これを `False` にすることで、処理速度が劇的に向上します。
4. 陥りやすい「罠」と、プロの回避術
このツールを使っていると、必ずと言っていいほど直面する問題があります。それは、「スケジュールが矛盾して、見た目がめちゃくちゃになる」ことです。
なぜ矛盾が起きるのか?
「必ずこの日に終わらせろ!」という強力な命令(制約)を、前後のタスクとの関係を無視して無理やり適用すると、Projectの計算エンジンはパニックを起こします。
例えば、
- タスクA(先行)が終わるのが10日。
- タスクB(マイルストーン)を「必ず5日に終わらせろ」と制約。
- 結果 $\rightarrow$ 「マイナスの期間」や「不可能なスケジュール」が発生。
プロのアドバイス
制約を適用した後は、必ず「クリティカルパス」と「スラック(余裕時間)」を確認してください。
もし、制約を適用したせいでスケジュールが赤くなったり、矛盾が出たりした場合は、その制約は「物理的に不可能」であることを意味しています。
自動化ツールは「命令を実行する道具」であって、「無理な計画を正当化する道具」ではありません。ツールが教えてくれた矛盾を、人間が調整する。この「機械のスピード」と「人間の判断」の協調こそが、真のプロジェクト管理です。
まとめ:ここをクリアすれば、基本はバッチリです
いかがでしたか?
単に日付を書き換えるのではなく、`ConstraintType` を操作して「計算エンジンに命令を出す」という考え方。これが理解できれば、あなたはもう「マクロの記録」の域を完全に脱しています。
今回のステップアップ・ポイント:
1. オブジェクトのプロパティ(ConstraintType)を直接制御する。
2. カスタムフィールド(Text1, Date1)を「司令塔」として利用する。
3. エラーハンドリングとパフォーマンス(ScreenUpdating)を意識する。
これらを意識して、ぜひ自分のプロジェクトで試してみてください。
もしエラーが出ても、それは成長のチャンスです。コードの向こう側にある「プロジェクトの論理」を、楽しんでくださいね。
応援していますよ!
