Project VBAを掌握する極限の知見
第4回:リソース割り当ての自動化とコメント同期による作業指示の完全統制
開発プロジェクトのリーダーである君なら、こんな悪夢に直面したことが一度はあるはずだ。
「リソースにタスクをアサインしたが、口頭やチャットでの指示が流れてしまい、担当者が何をどう作るべきか迷っている」「タスク管理ツールと実際の作業指示書が乖離し、手戻りが発生している」――。
Microsoft Project(Project VBA)を用いたリソース管理において、タスクへの「割り当て(Assignment)」は、プロジェクトの成否を握る心臓部だ。しかし、標準機能のままでは、リソースに対して「具体的な作業指示」を紐付ける動線が脆弱である。
今回は、タスク割り当て時にカスタムフィールドへ動的に指示内容を自動入力し、作業漏れと伝達ミスを撲滅する堅牢な自動化アーキテクチャを伝授する。
—
1. なぜ標準の「割り当てメモ」では実務で破綻するのか?
Projectには、タスクや割り当てに対して「メモ(Notes)」を付与する機能がある。しかし、大規模なプロジェクトや複数の外部ベンダーが混在する現場において、標準のメモ機能運用は以下の理由で必ず破綻する。
1. 視認性の欠如: ガントチャートやリソース配分表のビューにおいて、メモの内容を一目で確認することが不可能(わざわざダイアログを開く必要がある)。
2. レポート出力の困難さ: 進捗報告会用の資料や、週次で出力するExcelレポートにメモフィールドを美しくマージできない。
3. 作業指示の属人化: アサインする担当者のスキルセットに応じた「動的な指示書の切り替え」が手動では追いつかない。
解決アプローチ
Projectの「リソース割り当て(Assignment)オブジェクト」をVBAから完全に掌握し、アサイン発生時に特定のカスタムテキストフィールド(例: `Text1` 〜 `Text10`)へ、要件定義書やチケット番号に紐づく作業指示コメントを自動注入する仕組みを構築する。
—
2. 堅牢な設計思想:Assignment オブジェクトのライフサイクル
Project VBAにおける最大の見落としは、「Task(タスク)」と「Resource(リソース)」の間に「Assignment(割り当て)」という独立した実体が存在するという事実を無視することだ。
多くの初学者は、`Task.Notes` や `Resource.Notes` をいじろうとする。しかし、リソースマネジメントの本質は「誰が(Resource)、どのタスクに(Task)、どのような文脈で(Assignment)配置されているか」の多対多の結合管理にある。
したがって、今回の自動化エンジンは以下のライフサイクルで設計する。
- トリガー: 割り当て(Assignment)が新規作成された瞬間、またはバッチ実行による一括同期。
- 判定: 割り当てられたリソースの役割(Role)やタスクのカテゴリを判定。
- 書き込み: 割り当て固有のカスタムフィールド(`Assignment.Text1` 等)へ、構造化された作業指示を自動書き込み。
—
3. 【プロダクションコード】実務仕様のタスク指示自動化エンジン
以下のコードは、単なるサンプルではない。エラーハンドリング、オブジェクトのクリーンアップ、そしてプロジェクト全体のパフォーマンスを考慮した、プロダクション環境でそのまま稼働する実用コードだ。
プロジェクトを開いた状態で、標準モジュールに貼り付けて実行してほしい。
Option Explicit
‘ ==============================================================================
‘ módulo名: modAssignmentInstructionAutomation
‘ 概要 : タスク割り当て時にカスタムフィールドへ作業指示を自動同期する
‘ 著者 : Enterprise Project Architect
‘ ==============================================================================
Public Sub AutoInjectAssignmentInstructions()
Dim tsk As Task
Dim assn As Assignment
Dim targetField As PjField
Dim instructionText As String
Dim processedCount As Long
‘ パフォーマンス最大化のためのUI描画停止
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
processedCount = 0
‘ Project固有のカスタムフィールド指定(ここでは Assignment.Text1 を使用)
targetField = pjAssignmentText1
‘ プロジェクト内のすべてのタスクを走査
For Each tsk In ActiveProject.Tasks
If Not tsk Is Nothing Then
‘ サマリータスク(親タスク)はスキップし、実作業タスクのみ対象とする
If Not tsk.Summary Then
‘ タスクに紐づくすべてのリソース割り当てを走査
For Each assn In tsk.Assignments
If Not assn Is Nothing Then
‘ すでに指示が手動で上書きされている場合は保護する(空欄の場合のみ自動生成)
Dim currentVal As String
currentVal = assn.GetField(targetField)
If Trim$(currentVal) = “” Then
‘ タスクの属性やリソース名に基づき、動的に指示内容を構築
instructionText = BuildInstructionText(tsk, assn.Resource)
‘ 割り当てカスタムフィールドへ書き込み
assn.SetField targetField, instructionText
processedCount = processedCount + 1
End If
End If
Next assn
End If
End If
Next tsk
Application.ScreenUpdating = True
MsgBox “作業指示の自動同期が完了しました。” & vbCrLf & _
“更新された割り当て件数: ” & processedCount & ” 件”, vbInformation, “自動化エンジン”
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ ==============================================================================
‘ プライベート関数: タスクとリソースの文脈から作業指示文字列を動的に生成
‘ ==============================================================================
Private Function BuildInstructionText(ByRef tsk As Task, ByRef res As Resource) As String
Dim sb As String
‘ 基本フォーマットの構築
sb = “” & Format$(Date, “yyyy/mm/dd”) & ” 指示: ”
‘ タスク名やWBSに応じた条件分岐(実際の業務ロジックに合わせて拡張してください)
Select Case True
Case InStr(1, tsk.Name, “設計”, vbTextCompare) > 0
sb = sb & “【要レビュー】成果物をDocWikiにアップロード後、テックリードの承認を得ること。”
Case InStr(1, tsk.Name, “実装”, vbTextCompare) > 0 Or InStr(1, tsk.Name, “開発”, vbTextCompare) > 0
sb = sb & “【CI/CD必須】単体テストカバレッジ80%以上を維持し、PRには担当者名とチケットIDを明記。”
Case InStr(1, tsk.Name, “テスト”, vbTextCompare) > 0
sb = sb & “【バグ起票】不具合発見時は必ず再現手順とログを添付し、Redmineへ起票すること。”
Case Else
sb = sb & “【通常業務】期限厳守。進捗に遅延が生じる場合は前日夕会までにエスカレーションすること。”
End Select
‘ リソース固有の役割を付加
If Not res Is Nothing Then
sb = sb & ” [担当: ” & res.Name & “]”
End If
BuildInstructionText = sb
End Function
—
4. 現場で絶対に踏み抜いてはならない「3つの罠」
この仕組みを実際の企業インフラ(Microsoft Project Server / Project Online、あるいはローカルのMppファイル運用)に組み込む際、以下の設計上の落とし穴に注意してほしい。
1. ユーザーによる手動上書きの保護(楽観的ロックの概念)
コード内でも配慮している通り、すでに現場のリーダーやPMが `Assignment.Text1` にカスタムの指示を書き込んでいる場合、VBAのバッチ実行で上書きしてはならない。
「空欄の場合のみ自動生成する(`Trim$(currentVal) = “”`)」というガード条件を入れることで、自動化と手動運用の共存(ハイブリッド運用)が初めて成立する。
2. スクリーンのちらつきとパフォーマンス最適化
タスク数が数千件を超える大規模プロジェクトにおいて、`Application.ScreenUpdating = False` を記述しないコードは、画面の描画処理だけで実行時間が10倍以上に膨れ上がる。
VBAのパフォーマンスチューニングの鉄則として、一括処理の前後では必ずUI描画をロックすること。
3. ビュー側(Gantt Chart)での見せ方
この自動化で書き込んだ `Assignment.Text1` は、Microsoft Projectの「タスクビュー」の標準カラムには直接表示されない。
プロジェクト管理者が効果を実感するためには、あらかじめカスタムビューで「リソース利用状況(Resource Usage)」または「タスク利用状況(Task Usage)」ビューを表示し、列(Column)に「テキスト1 (割り当て)」を追加しておく必要がある。この初期セットアップをプロジェクトテンプレート(.mpt)に組み込んでおくのが、プロのアーキテクチャだ。
—
5. おわりに:ツールは現場の「規律」を創るためにある
業務自動化の本質は、単なる「手作業の削減」ではない。
「指示漏れやコミュニケーション不足という、人間に起因する構造的欠陥をシステムの力で構造的に排除すること」に他ならない。
今回提供したコードをベースに、自社の開発プロセス(JiraやAzure DevOpsのAPI連携、社内Wikiのリンク自動生成など)と組み合わせることで、君のプロジェクト管理基盤は一段上の次元へと進化するだろう。
妥協なき設計で、プロジェクトを勝利へと導いてほしい。
