こんにちは!プロジェクト管理の現場で、日々「このタスク、誰に割り当てたら一番効率いいんだっけ…?」と頭を悩ませていませんか?
Excelでのリソース調整に限界を感じ、Microsoft ProjectのVBA(Visual Basic for Applications)の世界に踏み込んだあなたへ。今日は、Project VBAの真骨頂とも言える「Assignment(割り当て)オブジェクト」を自在に操り、工数配分の自動化を極める方法を伝授します。
「マクロの記録」ボタンを押すだけの世界は今日で卒業です。ここをクリアすれば、あなたも立派なProject VBAのアーキテクトです。優しく、そして本質的なところまでしっかりと解説していきますね。
—
なぜ、Assignment(割り当て)の自動化が必要なのか?
プロジェクトが大規模化するにつれて、手動でのリソース割り当ては地獄のような作業になります。
「Pythonが得意なAさんにタスクが集中している…」「この工程にはシニアレベルのリソースをアサインしたいのに、誰が空いているか分からない…」
Microsoft Projectにおいて、「タスク(Task)」と「リソース(Resource)」は、いわば「仕事」と「人」という別々の世界線にいます。この2つを橋渡しし、「誰が、どのタスクに、どれだけの工数(Work)を費やすか」を結びつけるのが「Assignment(割り当て)オブジェクト」です。
[ Task (仕事) ] <--- ( Assignment ) ---> [ Resource (人) ]
この三者関係のライフサイクルをVBAで完全に掌握できれば、スキルセットや空き状況に基づいた「スマートな自動アサイン」が実現できます。
—
Project VBAの基本構造とAssignmentへのアクセス
まずは、Projectのオブジェクト階層の基本を押さえましょう。
Excel VBAと違い、Project VBAでは`ActiveProject`がすべての起点となります。
Application
└─ Project (ActiveProject)
├─ Tasks (タスク群)
│ └─ Task ── Assignments (このタスクに割り当てられたリソースたち)
└─ Resources (リソース群)
└─ Resource ── Assignments (このリソースが持つ割り当てたち)
タスクにリソースを割り当てるには、タスク側の `Assignments.Add` メソッドを使用します。ここが今回の魔法の杖です。
—
実践!スキルセットに合わせた工数配分の自動化コード
それでは、現場で即戦力として使える実用コードを公開します。
このスクリプトは、「特定のスキル(テキストカスタムフィールドで判定)を持つリソースを自動選定し、タスクに割り当てて、工数を等分に配分する」という高度な処理を行います。
ご自身のProject環境にコピー&ペーストし、開発タブのVBE(Visual Basic Editor)に貼り付けて実行してみてください。
Sub AutoAssignResourcesBySkill()
Dim tsk As Task
Dim res As Resource
Dim tgtAssignment As Assignment
Dim targetSkill As String
Dim assignedCount As Integer
‘ エラーハンドリングの基本:画面描画を停止して爆速化
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
‘ 今回探すスキルの定義(例:テキスト1フィールドに “Python” と入っているリソースを探す)
targetSkill = “Python”
‘ アクティブプロジェクトの全タスクをループ
For Each tsk In ActiveProject.Tasks
‘ タスクが有効(サマリータスクや削除済みではない)かつ、まだ未割当の場合
If Not tsk Is Nothing Then
If tsk.Summary = False And tsk.Active = True Then
‘ すでにリソースが割り当てられていないかチェック
If tsk.ResourceNames = “” Then
‘ リソースプールから条件に合う人を探す
For Each res In ActiveProject.Resources
If Not res Is Nothing Then
‘ リソースのテキスト1フィールドに指定スキルが入っているか判定
‘ ※実務では Text1 などをスキルマップとして活用します
If res.Text1 = targetSkill Then
‘ 【核心】TaskのAssignmentsコレクションにリソースを追加!
Set tgtAssignment = tsk.Assignments.Add(TaskID:=tsk.ID, ResourceID:=res.ID)
‘ 割り当てたリソースの工数(Work)を明示的に設定(例:16時間)
tgtAssignment.Work = “16h”
Debug.Print “成功: ” & res.Name & ” を ” & tsk.Name & ” に割り当てました。”
‘ 1つのタスクに1人割り当てたら次のタスクへ(ロジックの簡略化のため)
Exit For
End If
End If
Next res
End If
End If
End If
Next tsk
MsgBox “リソースの自動割り当てが完了しました!”, vbInformation, “自動化完了”
CleanUp:
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “予期せぬエラー”
Resume CleanUp
End Sub
—
コードの深掘り:ここがエンジニアの腕の見せ所
上記のコードで、特に重要なポイントを3つ解説します。ここを理解すると応用力が跳ね上がります。
1. `ScreenUpdating = False` によるパフォーマンスの最適化
Project VBAは、オブジェクトを操作するたびにガントチャートの再描画やスケジュール再計算(リソース平準化など)を裏で走らせようとします。タスクが数百件ある場合、これを行っていると処理が何分も終わらなくなります。
処理の最初に画面更新を止め、最後に元に戻す。これがプロの常套手段です。
2. `tsk.Assignments.Add(TaskID, ResourceID)` の魔力
タスクとリソースを繋ぐのがこの `Add` メソッドです。
「どのタスクに、どのリソースをぶつけるか」をIDで指定することで、Projectのデータベース内部で頑健なリンク(Assignment)が生成されます。
3. オブジェクトのライフサイクルと `Nothing` 判定
Projectのコレクション(`Tasks`や`Resources`)を `For Each` で回すとき、途中で削除されたタスクや空のインデックスが挟まることがあります。そのため、`If Not tsk Is Nothing Then` という安全装置(ガード節)が絶対に欠かせません。これをサボると「オブジェクト変数または With ブロック変数が見つかりません」という呪いのエラーに悩まされることになります。
—
陥りやすい罠とエラー回避の知見
現場でこのコードを実装する際、多くの人が以下の壁にぶつかります。
- 罠1:工数(Work)を設定したついでに期間(Duration)が変わってしまう
- 対策: Projectのエンジンは賢すぎるため、リソースをアサインした瞬間にタスクの日数が勝手に変動することがあります。必要に応じて `tsk.Type = pjTaskFixedWork`(固定工数タスク)などをコードの最初に指定し、スケジュールの勝手な変形を防ぎましょう。
- 罠2:オーバーアサイン(過負荷)の検知
- 対策: 今回はシンプルにアサインのみを行いましたが、実務では `res.Overallocated` プロパティを監視し、`True` であれば別の人格(リソース)を探すロジックに拡張すると、より実用的な「最強の自動化ツール」になります。
—
おわりに
お疲れ様でした!今回は、Project VBAにおける「Assignmentオブジェクト」の操作と、それを通じた工数配分の自動化について解説しました。
最初は難しく感じた「タスクとリソースの橋渡し」も、コードの構造を紐解けば、VBAがどれほど強力な味方になってくれるか実感できたのではないでしょうか?
ここをクリアすれば、Project VBAの基本はバッチリです。ぜひ明日の実務に取り入れて、面倒な手作業を自動化し、プロジェクトマネジメントの本質的な戦略立案に時間を割いてくださいね。あなたのエンジニアライフを応援しています!
