【入門編】リソースの「割り当て」を一括で「固定工数」から「固定期間」へ変更するメンテナンスツール – Project VBA解析バイブル

スポンサーリンク

皆さん、こんにちは! 最前線でプロジェクトを動かす、情熱的なPMの皆さん、そしてそれを技術で支えるエンジニアの皆さん。Project VBAの世界へようこそ。

今回は、多くのプロジェクトマネージャーが直面する、ある「もやもや」を解消する極意をお伝えします。それは、プロジェクトの進捗に応じて、リソースの割り当てタイプを一括で「固定工数」から「固定期間」へ変更し、スケジュールの安定化を図るという、一見地味ながらも強力なメンテナンスツールの話です。

「え、割り当てタイプなんて変更できるの?」「それって、どんな時に役立つの?」
そんな疑問を抱いたあなた、大正解です。これから、その本質から具体的なVBAコードまで、基礎の基礎から極限の知見まで、余すことなくお伝えしましょう。

—

なぜ「固定工数」から「固定期間」への変換が必要なのか?

まずは、この変換がなぜ重要なのかを理解することから始めましょう。Microsoft Projectには、タスクの「種類(Type)」として「固定工数」「固定期間」「固定単位」の3つがあります。これはタスク全体の挙動を制御するものです。

しかし、今回焦点を当てるのは、個々のリソース割り当て(Assignment)に設定される「割り当てタイプ」です。混乱しやすいポイントですが、タスクの種類と割り当てタイプは密接に関連しつつも、独立した概念として存在します。

  • 固定工数 (Fixed Work):

リソースがタスクに投入する「工数」が固定されます。リソースの数を増やすと期間が短縮され、リソースの数を減らすと期間が延長されます。主に、開発作業や執筆作業など、完了までに必要な「作業量」が決まっている場合に適しています。

  • 固定期間 (Fixed Duration):

タスクの「期間」が固定されます。リソースの数を増やすと、個々のリソースにかかる工数(割り当て単位)が減り、リソースの数を減らすと工数が増えます。主に、会議やレビュー、特定の試験期間など、期間自体が変更できない場合に適しています。

変換が必要になるシナリオ

プロジェクトの初期段階では、未確定要素が多いタスクに対して、必要な「工数」を見積もって「固定工数」で割り当てることがよくあります。しかし、プロジェクトが進み、フェーズが移行したり、スケジュールの確定度が高まったりすると、次のような問題に直面することがあります。

1. スケジュールの不安定化: 「固定工数」のままでは、リソースの追加や削除、進捗の変動によってタスク期間が大きく変動し、全体のスケジュールが予測しにくくなります。
2. 特定の期間内での完了が必須: テスト期間や監査期間など、開始日と終了日が厳密に決まっているタスクに対して、工数で縛られると柔軟なリソース調整ができません。
3. リソースの稼働率調整の困難さ: 特定の期間で完了させたいタスクなのに、工数が固定されていると、リソースの負荷調整が難しくなります。

このような時、「このタスクはもう期間が決まっているから、今後は期間を固定したい!」というニーズが生まれます。しかし、一つ一つ手作業で変更するのは、タスク数が多ければ多いほど非現実的です。そこで、Project VBAの出番です!

—

Project VBAで割り当てタイプを理解する

Project VBAの世界では、これらの割り当てタイプをどのように扱うのでしょうか。
実は、個々の割り当てオブジェクト(`Assignment`オブジェクト)には、その割り当てが「固定工数」であるか「固定期間」であるかを直接的に示すプロパティは存在しません。代わりに、次のプロパティを使用します。

  • `Assignment.FixedWork`: この割り当てが「固定工数」モードで計算されている場合に`True`を返します。
  • `Assignment.FixedDuration`: この割り当てが「固定期間」モードで計算されている場合に`True`を返します。

これらは排他的に設定されることが多く、どちらか一方が`True`になります。今回の目的は、`Assignment.FixedWork`が`True`の割り当てを検出し、それを`Assignment.FixedDuration = True`に設定し直すことです。

ここが肝です。タスクの「種類(`Task.Type`)」が「固定工数」であっても、そのタスク内の個々の「割り当て(`Assignment`)」は「固定期間」に設定できるのです。Projectは非常に柔軟にできていますね。

—

VBAコード作成の準備

さあ、Project VBAのコードを書き始める準備をしましょう。

1. Visual Basic Editor (VBE) の起動:
Microsoft Projectを開き、`Alt + F11`キーを押してVBEを起動します。
2. 標準モジュールの挿入:
VBEの左側にあるプロジェクトエクスプローラーで、現在開いているプロジェクト(例: `VBAProject (あなたのプロジェクト名.mpp)`)を右クリックし、`挿入(I)` > `標準モジュール(M)`を選択します。新しいモジュールが作成されます。
3. VBAコードの記述:
作成したモジュールに、以下のコードを記述していきます。

—

極限の知見を盛り込んだ!割り当て一括変換ツール

それでは、本題のVBAコードに入りましょう。単に動けばいい、というレベルではなく、オブジェクトのライフサイクル、パフォーマンス、そして何よりも安定性を考慮したコードを一緒に書いていきましょう。

Option Explicit ‘ 変数の宣言を強制し、タイプミスによるエラーを防ぎます

Sub ConvertAssignmentsToFixedDuration()

‘ — 1. 処理速度と安定性のための初期設定 —
‘ 画面更新を停止し、処理中のちらつきや描画負荷を軽減します。
Application.ScreenUpdating = False
‘ 計算モードを手動に設定し、VBAコード実行中の自動再計算を抑制します。
‘ これにより、オブジェクトのプロパティ変更時の余計な計算処理を省き、パフォーマンスを向上させます。
Application.Calculation = pjManual
‘ 元に戻す(Undo)バッファをクリアします。
‘ 大量処理を行うVBAでは、Undo情報が蓄積されメモリを圧迫し、パフォーマンスが著しく低下することがあります。
‘ ただし、これによりVBA実行前の状態にProjectのUIから戻せなくなるため、注意が必要です。
Application.UndoClear

‘ — 2. 変数の宣言 —
Dim tsk As Task ‘ タスクオブジェクトを格納する変数
Dim ass As Assignment ‘ 割り当てオブジェクトを格納する変数
Dim prj As Project ‘ 現在開いているプロジェクトオブジェクトを格納する変数
Dim lngCount As Long ‘ 変更した割り当ての数をカウントする変数
Dim lngTotalAssignments As Long ‘ 全ての割り当ての数をカウントする変数

‘ — 3. 現在開いているアクティブなプロジェクトを設定 —
‘ オブジェクトの参照を設定します。
Set prj = ActiveProject

‘ — 4. 処理の開始メッセージ —
Debug.Print “————————————————–”
Debug.Print “割り当てタイプ変換処理を開始します…”
Debug.Print “対象プロジェクト: ” & prj.Name
Debug.Print “————————————————–”

‘ — 5. プロジェクト内の全タスクをループ処理 —
‘ ActiveProject.Tasks コレクションをイテレートし、全てのタスクにアクセスします。
For Each tsk In prj.Tasks
‘ 概要タスク(IDが0のタスク)や空白行のタスクは処理対象外とします。
If Not tsk Is Nothing Then ‘ tskが有効なオブジェクトであることを確認
If Not tsk.Summary And Not tsk.IsNull Then
‘ — 6. 各タスク内の全割り当てをループ処理 —
‘ タスクに割り当てられているリソースがない場合もありますので、エラー対策も兼ねてループします。
For Each ass In tsk.Assignments
lngTotalAssignments = lngTotalAssignments + 1 ‘ 全割り当て数をカウント
‘ — 7. 割り当てタイプが「固定工数」であるかを確認 —
‘ Assignment.FixedWork が True であれば、現在の割り当てが「固定工数」モードです。
If ass.FixedWork Then
‘ — 8. 「固定期間」へ変換 —
‘ FixedWork を False にし、FixedDuration を True に設定することで、
‘ 割り当ての計算モードを「固定期間」へ変更します。
‘ この順序が重要です。FixedWorkをFalseにすることで、Projectが期間固定の挙動に切り替わります。
ass.FixedWork = False
ass.FixedDuration = True
lngCount = lngCount + 1 ‘ 変更数をカウント
Debug.Print ” 変更: タスク ‘” & tsk.Name & “‘ (” & tsk.ID & “) – リソース ‘” & ass.ResourceName & “‘ を固定期間へ”
End If
Next ass
End If
End If
Next tsk

‘ — 9. 処理の終了メッセージ —
Debug.Print “————————————————–”
Debug.Print “割り当てタイプ変換処理が完了しました。”
Debug.Print “総割り当て数: ” & lngTotalAssignments
Debug.Print “固定工数から固定期間へ変更された割り当て数: ” & lngCount
Debug.Print “————————————————–”

‘ — 10. 後処理とリソースの解放 —
‘ 念のため、計算モードを自動に戻します。
Application.Calculation = pjAutomatic
‘ 画面更新を再開し、変更が画面に反映されるようにします。
Application.ScreenUpdating = True

‘ オブジェクトを明示的に解放します。
‘ 特にProjectオブジェクトはメモリを多く消費するため、不要になったら速やかに解放することが重要です。
Set ass = Nothing
Set tsk = Nothing
Set prj = Nothing

MsgBox “全ての割り当てタイプの変換が完了しました。(” & lngCount & “件の割り当てが固定期間に変更されました)”, vbInformation

End Sub

コード解説と「極限の知見」ポイント

1. `Option Explicit`:
これはVBAの基本中の基本ですが、非常に重要です。変数宣言を強制することで、タイプミスによる予期せぬバグを防ぎ、コードの可読性を高めます。伝説のエンジニアは常にこれを活用します。

2. 初期設定 (`Application.ScreenUpdating`, `Application.Calculation`, `Application.UndoClear`):

  • `Application.ScreenUpdating = False`: 大量処理を行うVBAコードでは、Projectの画面が何度も更新されるのを抑制することで、処理速度を劇的に向上させます。ユーザーにとっては処理が速く感じられ、ストレスが軽減されます。
  • `Application.Calculation = pjManual`: プロジェクトに変更を加えるたびにProjectが自動的に再計算を行うのを防ぎます。これにより、オブジェクトのプロパティ変更ごとに発生するオーバーヘッドを排除し、処理時間を大幅に短縮できます。処理終了後に`pjAutomatic`に戻すのを忘れないでください。
  • `Application.UndoClear`: これが「極限の知見」の一つです。Projectは内部的にユーザーの操作履歴を保持し、Undo(元に戻す)機能を提供しています。しかし、VBAで大量の変更を行うと、このUndoバッファが肥大化し、メモリを消費し、処理速度を低下させます。これをクリアすることで、パフォーマンスを確保しますが、VBA実行前の状態にUIから戻せなくなるというトレードオフがあります。実行前には必ずプロジェクトのバックアップを取るようにしてください。

3. オブジェクトのループとアクセス:

  • `For Each tsk In prj.Tasks`: `ActiveProject.Tasks`コレクションをループすることで、プロジェクト内のすべてのタスクに効率的にアクセスできます。
  • `If Not tsk.Summary And Not tsk.IsNull Then`: 概要タスク(サマリータスク)や空の行は、実作業を伴わないため、変更対象から除外しています。これにより、無駄な処理を省き、意図しない変更を防ぎます。
  • `For Each ass In tsk.Assignments`: 各タスクに対して、そのタスクに割り当てられているすべてのリソース(`Assignment`オブジェクト)をループします。

4. 割り当てタイプの判定と変更:

  • `If ass.FixedWork Then`: 現在の割り当てが「固定工数」モードで計算されているかどうかを判定します。
  • `ass.FixedWork = False`
  • `ass.FixedDuration = True`: ここが肝心です。`FixedWork`を`False`に設定し、その後`FixedDuration`を`True`に設定することで、Projectは割り当ての計算方法を「固定期間」モードに切り替えます。この順序がProjectの内部ロジックと整合性が高く、意図した変更が確実に適用されます。

5. オブジェクトの明示的な解放 (`Set obj = Nothing`):
処理の最後に`Set ass = Nothing`, `Set tsk = Nothing`, `Set prj = Nothing`としています。これは、VBAにおけるメモリ管理のベストプラクティスです。特にProjectのオブジェクトはサイズが大きく、不要になったら速やかにメモリから解放することで、メモリリークを防ぎ、VBAプロセス、ひいてはProjectアプリケーション全体の安定性を保ちます。これも、単なる「おまじない」ではなく、安定稼働のための重要な作法なのです。

—

実行前の最終確認と注意点

  • 必ずプロジェクトのバックアップを取ってください! `Application.UndoClear`を使用しているため、VBA実行後にUIから元に戻すことができません。万が一に備え、実行前の状態を保存しておくことが鉄則です。
  • このツールは、すべての「固定工数」割り当てを「固定期間」に変換します。もし特定の割り当てだけを変換したい場合は、コード内の`If ass.FixedWork Then`の前に、タスク名やカスタムフィールドなど、追加の条件判定ロジックを加える必要があります。

補足:コスト管理と稼働率調整への影響

この割り当てタイプの変更は、単にスケジューリングの挙動を変えるだけでなく、プロジェクトのコスト管理やリソースの稼働率調整にも影響を与えます。

  • コスト管理: 「固定期間」に変更することで、期間は固定されますが、リソースの追加/削除によって個々のリソースの作業量(工数)が変動し、それに伴いコストも変動します。これにより、期間内での予算調整がしやすくなります。
  • 稼働率調整: 「固定期間」は、指定された期間内でタスクを完了させるという制約を優先します。これにより、期間内にリソースがどれだけの工数を投入できるか(稼働率)を調整しやすくなり、リソースの過負荷や過少負荷を管理する上でより柔軟な対応が可能になります。

—

まとめと次のステップ

今回は、Project VBAを使ってリソースの「割り当て」を一括で「固定工数」から「固定期間」へ変更するメンテナンスツールをご紹介しました。

  • なぜこの変換が必要なのか、その背景とメリットを理解しました。
  • `Task.Type`と`Assignment.FixedWork`/`FixedDuration`の関係という、Projectの奥深い概念を学びました。
  • パフォーマンスと安定性を追求したVBAコードの実装方法を習得しました。

このツールを使いこなせば、あなたのプロジェクトはより柔軟に、そしてより安定したスケジュール運用が可能になるでしょう。そして、このコードを通じて、オブジェクトのライフサイクル、パフォーマンスへの配慮、そしてエラーハンドリングの重要性といった、VBA開発における本質的な知見を肌で感じていただけたはずです。

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

さらに深く学びたい方は、特定の条件でタスクをフィルタリングする方法や、カスタムフィールドを活用したVBAの応用にも挑戦してみてください。あなたのプロジェクト管理が、よりスマートで効率的になることを心から願っています。

さあ、この知識を武器に、あなたのプロジェクトを次のレベルへと引き上げましょう!

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