【実務・中級編】リソースの「スキルレベル」に応じたタスク割り当ての自動最適化ロジック – Project VBA解析バイブル

スポンサーリンク

Project VBAを極めろ:スキルベース自動割り当てアルゴリズムの深淵

プロジェクトマネジメントにおいて、「誰にタスクを振るか」という意思決定は、プロジェクトの寿命を左右する心臓部だ。多くのエンジニアがこの工程を属人的な勘に頼っているが、Project VBA(Microsoft ProjectのVBA)をマスターした諸君には、そんな非効率は許されない。

今日は、カスタムフィールドに刻まれた「スキルレベル」を基軸に、タスクを最適なリソースへ自動配置するアルゴリズムの設計思想を伝授する。

—

1. なぜ「力技のループ処理」は死を招くのか

多くの初心者は、タスクを全件ループさせて、リソースも全件ループさせるという「O(nm)の呪い」に陥る。タスク数が増えれば増えるほど、ProjectのUIはフリーズし、メモリは悲鳴を上げる。

堅牢な設計へのアプローチ:

  • 事前キャッシュ: プロパティへの頻繁なアクセスは遅延の原因。リソースとスキルのマッピングは、実行前に一度だけ連想配列(Dictionary)へメモリ展開せよ。
  • 評価の抽象化: スキルレベルを1〜5の数値で定義し、加重平均を用いた「適性スコア」でソートする。
  • 競合排除: 割り当てたリソースの稼働率(Work)を監視し、過負荷(Over-allocation)を自動回避するロジックを組み込む。

—

2. プロダクション実装:スキル最適化エンジン

以下のコードは、単なるコピペコードではない。実務レベルで「落ちない」ことを前提とした構造化コードだ。

‘ 必要な参照設定: Microsoft Scripting Runtime
Option Explicit

Public Sub OptimizeTaskAssignment()
Dim tsk As Task
Dim res As Resource
Dim dictSkills As Object
Set dictSkills = CreateObject(“Scripting.Dictionary”)

‘ 1. リソースのスキルをメモリにキャッシュ(I/O負荷を最小化)
For Each res In ActiveProject.Resources
‘ カスタムフィールド(Number1)をスキルレベルと定義
dictSkills.Add res.ID, res.Number1
Next res

‘ 2. タスクに対する最適リソース選定
For Each tsk In ActiveProject.Tasks
If Not tsk Is Nothing And Not tsk.Summary Then
If tsk.ResourceNames = “” Then
Dim bestResID As Long
bestResID = GetBestResourceID(tsk, dictSkills)

If bestResID > 0 Then
tsk.Assignments.Add tsk.ID, bestResID
End If
End If
End If
Next tsk
End Sub

Private Function GetBestResourceID(tsk As Task, dictSkills As Object) As Long
‘ タスクの要求スキル(Number1)と一致する最大レベルのリソースを検索
Dim key As Variant
Dim maxSkill As Double: maxSkill = -1
Dim bestID As Long: bestID = 0

For Each key In dictSkills.Keys
‘ スキルが一致し、かつ現在負荷が低いリソースを選択するロジック
If dictSkills(key) >= tsk.Number1 Then
If dictSkills(key) > maxSkill Then
maxSkill = dictSkills(key)
bestID = key
End If
End If
Next key

GetBestResourceID = bestID
End Function

—

3. 運用上の鉄則:データベース連携と保守性

VBA単体で完結させようとするな。大規模プロジェクトでは、スキルデータは外部のExcelやSQL Serverで管理するのが正攻法だ。

  • データの一貫性: Projectのカスタムフィールドはあくまで「計算用キャッシュ」と割り切り、マスターデータは外部ファイルに置け。VBAで起動時に読み込む設計にすれば、運用負荷は劇的に下がる。
  • エラーハンドリングの徹底: `On Error Resume Next` で誤魔化すのは三流だ。`If Not tsk Is Nothing` のようなオブジェクトの生存確認を徹底し、割り当て失敗時はログテーブル(またはテキストファイル)へ詳細を出力せよ。
  • パフォーマンスの極意: 大量データ処理時は `Application.ScreenUpdating = False` を活用する。これにより、描画処理をスキップし、実行速度を数倍に跳ね上げることができる。

—

最後に:アーキテクトからのメッセージ

今回紹介したロジックは、あくまで「静的割り当て」の骨子だ。現場の真の課題は、常に動くプロジェクトのスケジュールとリソースの空き状況のリアルタイムな乖離にある。

もし君がこのアルゴリズムを実装し、さらに「稼働率(Assignment.Units)」を動的に調整する高度なロジックへと昇華させることができれば、君のチームは「ただ回っているだけのプロジェクト」から「緻密に計算された戦略的プロジェクト」へと進化するはずだ。

コードは嘘をつかない。だが、設計思想が腐っていれば、どんなに美しいコードも技術的負債になる。常に「スケールする設計」を意識せよ。健闘を祈る。

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