【入門編】実務中級:プロジェクトテンプレート適用時の「制約条件クリーンアップ」自動化 – Project VBA解析バイブル

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

テンプレートの「呪い」を解く:Project VBAによる制約条件クリーンアップの極意

こんにちは。プロジェクトの進捗管理、日々お疲れ様です。

MS Projectを使ってプロジェクトを管理していると、必ずと言っていいほど直面する「ある問題」があります。それは、「テンプレートから新しいプロジェクトを作ったのに、タスクの開始日がどうしても動かない!」という現象です。

「タスクの開始日を新しいプロジェクトの開始日に合わせても、なぜか以前のテンプレートの期間に縛られてしまう……」

もしあなたが今、そんな不可解な挙動に頭を抱えているなら、おめでとうございます。あなたは今、「スケジュール計算エンジンの制御」という、MS Projectマスターへの登竜門に立っています。

今日は、マクロの記録から一歩踏み出したいあなたへ、テンプレートに潜む「不要な制約条件」を自動で一掃し、プロジェクトを真っさらな状態(ASAP状態)へリセットする技術を伝授します。ここをクリアすれば、Project VBAの基本はバッチリですよ。

1. なぜテンプレートは「動かなくなる」のか?

まず、問題の本質を理解しましょう。原因は日付そのものではなく、タスクに付与された「制約条件(Constraint Type)」にあります。

MS Projectのタスクには、大きく分けて2つの「縛り」があります。

1. 論理的制約(依存関係): 「タスクAが終わったらタスクBを始める」という、先行・後続関係。
2. 時間的制約(制約条件): 「タスクBは、〇月〇日より前には開始できない(Start No Earlier Than)」や「必ず〇月〇日に開始しなければならない(Must Start On)」という、日付に対する直接的な命令。

テンプレートを作成して保存する際、無意識のうちにタスクに「Must Start On(必ず~に開始)」などの強い制約が付与されていることがあります。

これを新しいプロジェクトにコピーすると、たとえプロジェクト全体の開始日を書き換えても、タスクは「いや、私はテンプレートに書いてあったあの日に開始せよと命令されているんだ!」と頑固に拒否してしまうのです。これが、いわゆる「テンプレートの呪い」です。

【図解】制約条件の違い

制約タイプ イメージ スケジュールの柔軟性
ASAP (Start No Earlier Than) 「準備ができ次第、最短で」 【高い】 前後関係に合わせて動く
Must Start On 「何が何でもこの日に開始せよ」 【極めて低い】 前後関係を無視して固定される

2. 実装の戦略:オブジェクトのライフサイクルを考える

この問題を解決するために、私たちはVBAを使って全タスクをスキャンし、制約条件を「Start No Earlier Than(~より前には開始しない)」、つまり実質的なASAP(できるだけ早く)状態へと書き換えるプログラムを作成します。

ここで、プロフェッショナルなエンジニアとして意識してほしいのが「オブジェクトの走査(スキャン)」の作法です。

Projectの全タスクをループで回す際、以下の3点に注意してください。
1. Nothingチェック: 空白の行(タスクが存在しない行)にアクセスしてエラーを出さない。
2. サマリータスクの扱い: 集計タスクに対して制約をいじると、配下のタスクが予期せぬ挙動をすることがあります(基本は配下タスクに任せるのが定石です)。
3. パフォーマンス: 数千タスクあるプロジェクトで、画面更新をオンにしたままループを回すと、処理が劇的に遅くなります。

3. 魂のコード:制約条件クリーンアップ・マクロ

それでは、実戦で使えるコードを見ていきましょう。このコードは、単に制約を消すだけでなく、エラーに強く、かつ高速に動作するように設計しています。

Option Explicit

''' <summary>
''' プロジェクト内の全タスクの制約条件をクリーンアップし、
''' ASAP(Start No Earlier Than)状態にリセットする。
''' </summary>
Sub CleanUpProjectConstraints()
    Dim t As Task
    Dim taskCount As Long
    Dim startTime As Double
    
    ' 処理時間の計測開始(パフォーマンス意識の第一歩)
    startTime = Timer
    
    ' 1. 画面更新と再計算を一時停止して高速化
    ' これを行わないと、タスクを一つ書き換えるたびにProjectが再計算を走り、非常に重くなります。
    Application.ScreenUpdating = False
    Application.Calculation = pjCalculationManual
    
    On Error GoTo ErrorHandler
    
    taskCount = 0
    
    ' 2. プロジェクト内の全タスクをループ処理
    For Each t In ActiveProject.Tasks
        
        ' タスクが存在しない(空行)場合はスキップ
        If Not t Is Nothing Then
            
            ' サマリータスク(親タスク)はスキップするのが安全な設計
            ' ※プロジェクトの構成によりますが、基本は子タスクの制約を整理します
            If Not t.Summary Then
                
                ' 3. 制約条件の書き換え
                ' pjTaskConstraintStartNoEarlierThan は「~より前には開始しない」
                ' これを設定することで、実質的に「ASAP」と同じ挙動になります。
                If t.ConstraintType <> pjTaskConstraintStartNoEarlierThan Then
                    t.ConstraintType = pjTaskConstraintStartNoEarlierThan
                    taskCount = taskCount + 1
                End If
                
            End If
        End If
    Next t
    
    ' 4. 設定を元に戻す
    Application.Calculation = pjCalculationAutomatic
    Application.ScreenUpdating = True
    
    MsgBox "クリーンアップが完了しました!" & vbCrLf & _
           "修正したタスク数: " & taskCount & " 件" & vbCrLf & _
           "処理時間: " & Round(Timer - startTime, 2) & " 秒", vbInformation, "完了"
    
    Exit Sub

ErrorHandler:
    ' エラーが発生した場合でも、必ず設定を元に戻して終了させる(重要!)
    Application.Calculation = pjCalculationAutomatic
    Application.ScreenUpdating = True
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical, "エラー"
End Sub

4. コードの解説と「陥りやすい罠」

このコードには、プロの現場で生き残るためのテクニックがいくつか組み込まれています。

① `Application.Calculation = pjCalculationManual`

ここが最大のポイントです。MS Projectは、タスクのプロパティが変わるたびに「スケジュール全体を計算し直そう!」と頑張ります。ループの中でこれが発生すると、タスクが1,000個あれば1,000回再計算が走ります。これを「手動(Manual)」に切り替えることで、ループが終わった後に一括で計算させる。これが「重いマクロ」を「爆速マクロ」に変える魔法です。

② `If Not t Is Nothing Then`

「マクロの記録」から始めた人が最も陥りやすいエラーが、これの欠如です。MS Projectのタスクリストには、タスクが入力されていない空の行も含まれています。空の行に対して `.ConstraintType` を操作しようとすると、「オブジェクト変数または With ブロック変数が設定されていません」というエラーで止まってしまいます。これを防ぐのがこの一行です。

③ `pjTaskConstraintStartNoEarlierThan` を選ぶ理由

「制約をなし(`pjTaskConstraintNone`)」にしても良いのですが、実務上は `Start No Earlier Than` にしておく方が安全です。なぜなら、MS Projectのエンジンは「開始日」を基準に計算するため、この制約があることで「プロジェクト開始日以降に、論理的な依存関係に従って動く」という挙動がより明確に保証されるからです。

5. まとめ:次のステップへ

いかがでしたか?
「テンプレートをコピーして、日付を直す」という手作業の苦労は、この数行のコードで自動化できます。

今回のポイントを復習しましょう。
1. 問題の本質は「日付」ではなく「制約条件(Constraint Type)」にある。
2. テンプレートの「Must Start On」を「Start No Earlier Than」へ書き換える。
3. 高速化のために `Calculation` と `ScreenUpdating` を制御する。

これをマスターしたあなたは、もう単なる「マクロ記録の利用者」ではありません。プロジェクトのデータ構造を理解し、制御しようとする「エンジニア」への第一歩を踏み出しました。

次は、このクリーンアップを行った後に、「プロジェクト全体の開始日を、特定のセルやダイアログから入力した日付へ一括変更する」機能を組み合わせてみてください。そうすれば、あなた専用の最強のプロジェクト作成ツールが完成しますよ。

応援しています。また次の技術解説でお会いしましょう!

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