【入門編】【実務中級】「ASAP」と「開始日固定」の切り替えをVBAでトグル実装する:ツールバー連携のUI設計 – Project VBA解析バイブル

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

Project VBAを掌握する極限の知見:ASAPと開始日固定を自在に操る「トグル実装」の極意

こんにちは。現場の設計図をコードで描き変える、チーフアーキテクトです。

Microsoft Projectを使いこなしていると、必ず直面する壁があります。それは「スケジュールの柔軟性と厳格さのジレンマ」です。

「このタスクは、準備ができ次第すぐに始めてほしい(ASAP)」
「いや、このタスクだけは絶対にこの日に開始させなければならない(開始日固定)」

これらをマウス操作で、タスク情報ダイアログを開いて……と繰り返していませんか? 実務のスピード感では、これは「時間の損失」でしかありません。

今日は、マクロの記録から一歩踏み出し、「選択したタスクの制約条件を、ボタン一つで『ASAP』と『開始日固定』の間で交互に切り替える(トグル)」という、プロフェッショナルなUI実装のステップを伝授します。

ここをクリアすれば、あなたは「Projectの操作者」から「Projectの制御者」へと進化できるはずですよ。

1. 核心:Projectオブジェクトモデルの「制約条件」を理解する

コードを書く前に、まずProjectが内部でどのように「制約」を管理しているかを知る必要があります。ここが曖昧だと、どんなにコードが書けても「動かない、あるいは挙動が予測できない」という事態に陥ります。

Projectにおいて、タスクの開始タイミングを縛るルールは `ConstraintType` プロパティで管理されています。今回扱うのは、主に以下の2つです。

定数名 意味 動作のイメージ
`pjTaskConstraintAsSoonAsPossible` ASAP (可能な限り早く) 前工程が終わったらすぐに開始。スケジュール計算エンジンに計算を委ねる状態。
`pjTaskConstraintStartMustStartOn` 開始日固定 指定された日付に強制的に開始。スケジュール計算エンジンの介入を拒絶する状態。

エンジニアの視点:
「ASAP」とは、単なる状態ではなく、「計算エンジンに対して、制約をかけない(自由を与える)という命令」なのです。この概念を理解していると、スケジュールの再計算が走った時に「なぜか日付が動いてしまう!」というトラブルを論理的に解決できるようになります。

2. 実装:トグルロジックの構築

それでは、実際にコードを書いていきましょう。
目指す挙動は、「選択されているタスクを一つずつチェックし、ASAPなら固定へ、固定ならASAPへ、と状態を反転させる」というロジックです。

Option Explicit

''' <summary>
''' 選択されたタスクの制約条件を「ASAP」と「開始日固定」で切り替える
''' </summary>
Sub ToggleTaskConstraint()
    Dim t As Task
    Dim selection As TaskSelection
    
    ' 1. 現在の選択範囲を取得
    Set selection = ActiveSelection
    
    ' 2. エラーハンドリング:何も選択されていない場合のガード
    If selection.Tasks.Count = 0 Then
        MsgBox "タスクを選択してから実行してください。", vbExclamation, "実行エラー"
        Exit Sub
    End If

    ' 3. 描画更新の停止(パフォーマンス最適化の定石)
    ' 大量タスクを処理する場合、画面更新を止めると劇的に速くなります
    Application.ScreenUpdating = False

    On Error GoTo ErrorHandler

    ' 4. 選択された各タスクに対してループ処理
    For Each t In selection.Tasks
        ' Taskオブジェクトが有効であることを確認
        If Not t Is Nothing Then
            
            ' --- ここがトグル(切り替え)の核心ロジック ---
            If t.ConstraintType = pjTaskConstraintAsSoonAsPossible Then
                ' 現在が ASAP ならば、開始日固定に切り替える
                t.ConstraintType = pjTaskConstraintStartMustStartOn
            Else
                ' それ以外(固定など)ならば、ASAPに切り替える
                t.ConstraintType = pjTaskConstraintAsSoonAsPossible
            End If
            ' ------------------------------------------
            
        End If
    Next t

CleanUp:
    ' 5. 後処理:画面更新を再開させる
    Application.ScreenUpdating = True
    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical, "致命的エラー"
    Resume CleanUp
End Sub

コードの解説:ここがプロの仕事

  • `ActiveSelection.Tasks` の利用:

「今、ユーザーがマウスで選んでいるもの」に直接アクセスします。これにより、単一のタスクだけでなく、範囲選択された複数のタスクを一度に処理できます。

  • `Application.ScreenUpdating = False`:

これは重要です。タスクの状態を変えるたびにProjectが画面を書き換えると、処理が重くなります。大量のタスクを扱う実務では、この一行が「数秒の差」を生みます。

  • `If Not t Is Nothing`:

オブジェクトのライフサイクル管理において、念のための安全策です。選択範囲の中に、何らかの理由で参照できないオブジェクトが混じっていた場合にクラッシュするのを防ぎます。

3. UI設計:ツールバー(クイックアクセスツールバー)への連携

コードを書いただけでは、ユーザーは使えません。実務で「魔法のボタン」として機能させるには、UIへの組み込みが必要です。

最も手軽で、かつ強力なのは「クイックアクセスツールバー (QAT)」への登録です。

1. Projectの画面上部にある、クイックアクセスツールバーの右端の「▼」をクリックします。
2. [その他のコマンド…] を選択します。
3. 「コマンドの選択」のドロップダウンから [マクロ] を選びます。
4. 先ほど作成した `ToggleTaskConstraint` を選択し、中央の [追加 >>] ボタンを押します。
5. 右側のリストに追加されたマクロを選択し、下部の [変更…] ボタンを押して、アイコン(「矢印」や「スイッチ」のようなイメージ)と表示名を整えます。
6. [OK] を押して完了です。

これで、あなたの画面上部に「ワンクリックで制約を切り替える専用ボタン」が誕生しました。

4. 陥りやすいエラーと回避策(トラブルシューティング)

プロのエンジニアは、動くコードを書くだけでなく、「壊れないコード」を書きます。

① 「手動スケジューリング」との競合

タスクが「手動スケジューリング」になっている場合、制約条件を変えても日付が自動計算されず、ユーザーが混乱することがあります。

  • 対策: もし「制約を変えると同時に自動スケジューリングに切り替えたい」なら、コード内に `t.Manual = False` を追加しましょう。

② 依存関係による制約の衝突

「開始日固定」にしたタスクが、他のタスクの「先行タスク」になっている場合、スケジュール全体が歪む(ネガティブ・ラグが発生するなど)ことがあります。

  • 助言: このツールを使う際は、「制約をかけることが、プロジェクト全体の論理的整合性を壊さないか」を常に意識してください。ツールの責任は「操作の簡略化」であり、「スケジュールの正当性」を保証することではないからです。

最後に:一歩先へ進むあなたへ

今回の実装は、非常にシンプルに見えるかもしれません。しかし、「オブジェクトの状態を判定し、その逆を適用する」というロジックは、あらゆる業務自動化の基礎となる極めて重要な思考パターンです。

マクロの記録機能は「操作の録画」に過ぎませんが、今回のようにコードを組み立てることは「思考の構築」です。

「もっとこう動かしたい」「こういう条件の時だけ除外したい」……そんな欲求が湧いてきたら、それがあなたがエンジニアとして成長している証拠です。

ここをクリアすれば、Project VBAの基本はバッチリですよ。自信を持って、次の自動化に挑戦してくださいね。応援しています!

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