【入門編】【プロ向け】計算エンジンの「再計算保留」状態を監視し、ユーザーに警告を出す仕組み – Project VBA解析バイブル

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

【プロ向け】計算エンジンの「再計算保留」を掌握せよ:プロジェクトの整合性を守る安全装置の作り方

こんにちは。プロジェクト自動化の世界へようこそ。

「マクロの記録」を使って、ボタン一つでタスクの名前を変えたり、日付を入力したりできるようになってきた……。もしあなたが今そこにいるなら、素晴らしい一歩を踏み出しました。でも、ここからが本当の「エンジニア」への入り口です。

今日、私があなたに伝えたいのは、単なるコードの書き方ではありません。「MS Projectという巨大な計算エンジンの挙動を、いかにしてコントロールし、データの不整合という致命的な事故を防ぐか」という、極めて実戦的な設計思想についてです。

準備はいいですか? シートの表面的な操作を超えて、エンジンの深淵へ踏み込んでいきましょう。

1. なぜ「再計算」を監視しなければならないのか?

MS Projectは、Excelとは根本的に異なります。Excelは「セルに入力された値」を扱うものですが、Projectは「依存関係(先行・後続タスク)に基づいた動的なスケジュール計算エンジン」です。

ここで、一つの恐ろしいシナリオを想像してみてください。

1. ユーザーが、プロジェクトの計算設定を「手動(Manual)」に変更した。
2. あなたはVBAで「タスクAの期間を5日間延ばす」という処理を書いた。
3. VBAはタスクAの終了日を書き換えたが、計算エンジンが「手動」なので、後続のタスクBやプロジェクト全体の終了日は更新されない。
4. そのままVBAが「タスクBの終了日」を読み取ってレポートを作成した。
5. 結果:古い(間違った)日付に基づいた、デタラメな報告書が完成した。

これが、プロの現場で最も恐れられる「サイレント・エラー(静かなる不整合)」です。プログラムはエラーを出さずに完走しますが、出力されたデータは嘘をついています。

これを防ぐには、処理を開始する前に「今、計算エンジンは最新の状態を反映できるモードか?」を必ずチェックしなければなりません。

2. 核心となるプロパティ:`Application.Calculation`

MS Projectの計算状態を司る司令塔は、`Application` オブジェクトの `Calculation` プロパティです。

設定値 (Enum) 状態 VBAでの値 説明
Automatic 自動計算 `pjCalculationAutomatic` 何か変更があれば即座にスケジュールを再計算する。
Manual 手動計算 `pjCalculationManual` 明示的に指示しない限り、スケジュールは更新されない。

プロのコードでは、この状態を「単に確認する」だけでなく、「安全が確認できなければ処理を中断する、あるいは強制的に計算させる」という制御を行います。

3. 実践:安全装置(Safety Guard)の実装

それでは、実際に現場で使える「再計算モード監視ツール」のコードを見てみましょう。
初学者の方向けに、あえて「関数(Function)」と「メイン処理(Sub)」を分けて、再利用しやすい構造にしています。

Option Explicit

' =================================================================
' モジュール名: SafetyGuardModule
' 概要: プロジェクトの計算状態を監視し、不整合を防ぐためのツール
' =================================================================

''' <summary>
''' プロジェクトの計算モードをチェックし、自動計算でない場合はユーザーに警告を出す
''' </summary>
''' <returns>計算モードがAutomaticならTrue、それ以外ならFalse</returns>
Function IsCalculationModeSafe() As Boolean
    Dim calcMode As Long
    
    ' 現在の計算モードを取得
    calcMode = Application.Calculation
    
    ' 計算モードが「自動(Automatic)」かどうかを判定
    If calcMode = pjCalculationAutomatic Then
        ' 自動計算なら、安全なのでTrueを返す
        IsCalculationModeSafe = True
    Else
        ' 手動計算(Manual)の場合、警告を表示
        Dim response As VbMsgBoxResult
        response = MsgBox( _
            "【警告】プロジェクトの計算設定が「手動」になっています。" & vbCrLf & _
            "データの整合性を保つため、計算モードを「自動」に変更して処理を続行しますか?" & vbCrLf & vbCrLf & _
            "※「いいえ」を選択すると、処理を中断します。", _
            vbExclamation + vbYesNo + vbDefaultButton2, _
            "計算エンジンの状態確認")
            
        ' ユーザーの選択に応じた処理
        If response = vbYes Then
            ' 自動計算に切り替える
            Application.Calculation = pjCalculationAutomatic
            IsCalculationModeSafe = True
        Else
            ' 中断する
            IsCalculationModeSafe = False
        End If
    End If
End Function

''' <summary>
''' メインの業務ロジック(例:タスク期間の一括更新)
''' </summary>
Sub ExecuteCriticalTaskUpdate()
    ' 1. まず、計算エンジンが安全な状態かチェック(ここがプロの作法!)
    If Not IsCalculationModeSafe() Then
        MsgBox "処理を中断しました。計算モードを確認してください。", vbCritical
        Exit Sub
    End If
    
    ' 2. 安全が確認できたので、実際の業務処理を行う
    On Error GoTo ErrorHandler
    
    ' 画面更新を止めてパフォーマンスを向上させる(お作法)
    Application.ScreenUpdating = False
    
    Debug.Print "--- 業務処理開始 ---"
    
    ' --- ここに実際の処理を書く ---
    ' 例:すべてのタスクの期間を1日増やす(テスト用)
    Dim t As Task
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            t.Duration = t.Duration + 1 ' 1日追加
        End If
    Next t
    ' ----------------------------
    
    Debug.Print "--- 業務処理完了 ---"
    
    ' 3. 終了処理
    Application.ScreenUpdating = True
    MsgBox "全ての処理が正常に完了し、スケジュールも再計算されました。", vbInformation
    
    Exit Sub

ErrorHandler:
    ' エラーが発生した場合は、画面更新を戻してからエラー内容を表示
    Application.ScreenUpdating = True
    MsgBox "予期せぬエラーが発生しました: " & Err.Description, vbCritical
End Sub

4. コードの解説と「プロの視点」

このコードには、単なる動作以上の「設計の意図」が込められています。

① `IsCalculationModeSafe` 関数の分離

「計算モードが正しいか?」という判定ロジックを、メインの処理から切り離しています。これにより、他のマクロ(例えばレポート出力マクロなど)を作るときも、この関数を一行呼び出すだけで、同じ安全策を使い回すことができます。これが「モジュール化」の第一歩です。

② ユーザーへの「選択肢」の提示

単に「エラーです」と止めるのではなく、「自動に切り替えて続行しますか?」と問いかけています。ユーザーの作業を止めすぎず、かつミスも防ぐ。この「ユーザー体験(UX)」への配慮が、現場で愛されるツールを作る鍵です。

③ `On Error GoTo ErrorHandler` の重要性

プロのコードにおいて、エラーハンドリングは必須です。もし途中でエラーが起きたとき、`Application.ScreenUpdating = False`(画面更新停止)にしたままだと、Projectの画面が固まったように見えてしまいます。エラー発生時に必ず「元の状態に戻す」処理を入れるのが鉄則です。

5. 陥りやすい罠(Pitfalls)

最後に、これを知っているだけであなたのレベルが一段上がる「落とし穴」を共有しておきます。

  • 計算コストの増大:

非常に大規模なプロジェクト(数千タスク以上)で、VBAの中で何度も `Application.Calculate` を呼び出すと、計算が終わるまでマクロがフリーズしたようになります。大規模プロジェクトを扱う場合は、「処理の最初と最後だけ」計算を行うように設計しましょう。

  • ASAP/ALAP制約との関係:

タスクに「最短開始(ASAP)」や「最遅開始(ALAP)」の制約がかかっている場合、計算エンジンが動かないと、これらの制約に従った日付の移動が一切行われません。今回学んだ「計算モードの監視」は、これらの高度な制約を正しく機能させるための「前提条件」なのです。

まとめ:ここをクリアすれば、Project VBAの基本はバッチリですよ

いかがでしたか?

1. Projectは「計算エンジン」を持つ動的なシステムである。
2. 「手動計算モード」は、VBAにとっての「沈黙の敵」である。
3. `Application.Calculation` を監視し、安全を確保してから処理を開始する。

この3点を意識するだけで、あなたの作るツールは「ただ動くマクロ」から「信頼される業務システム」へと進化します。

一歩ずつ、着実に。エンジニアとしての旅を楽しんでください。応援していますよ!

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