Project VBAを掌握せよ:工数自動割り当てエンジンの設計思想と実装の極意
多くの開発者がVBAでのツール開発において陥る罠がある。それは「とりあえず動くコード」を書き、後から「リソースの整合性が取れない」「計算が破綻する」という地獄を見ることだ。
プロジェクト管理におけるリソース割り当ては、単なる数値の計算ではない。「Work(工数)」「Availability(稼働率)」「Assignment(割り当て)」という3つの変数の均衡を保つ、動的なシステム設計が必要だ。
本稿では、Project VBAの深淵に触れ、堅牢かつ保守性の高いリソース割り当てエンジンの設計論を伝授する。
—
1. 破綻しないリソース割り当てエンジンの設計哲学
なぜ、あなたの書いたコードはバグを生むのか。それは「状態(State)をファイルやシートに依存させすぎているから」だ。
自動化エンジンを構築する際、必ず以下の原則を守れ。
- ロジックとデータの完全分離: 計算ロジックをExcelシートのセル演算に混ぜるな。すべてVBAのクラスモジュール内で完結させろ。
- 「計算(Calculate)」と「永続化(Persist)」の分離: 割り当ての計算はメモリ内で行い、最後に一括でシートへ書き出せ。セルへの頻繁なアクセスはVBAにおいて最大のボトルネックだ。
- バリデーション・ファースト: 割り当てを確定する前に、稼働率の過負荷(オーバーアロケーション)を検知するチェック機能を必ず通せ。
—
2. 実装の心臓部:工数割り当て計算ロジック
以下は、タスクのWork量に基づき、リソースの稼働可能時間を考慮してアサインメントを算出するクラスモジュール設計の雛形だ。
クラスモジュール:`ResourceAllocator.cls`
‘ 割り当ての計算を行うコアエンジン
Option Explicit
‘ 稼働率を考慮したタスク割り当て計算
‘ @param workHours タスクの総工数(時間)
‘ @param availabilityRate リソースの稼働可能率(0.0 – 1.0)
‘ @param dailyCapacity 1日の最大労働時間(通常8.0)
Public Function CalculateAssignmentDays(ByVal workHours As Double, _
ByVal availabilityRate As Double, _
Optional ByVal dailyCapacity As Double = 8#) As Double
‘ ゼロ除算防止のガード節
If availabilityRate <= 0 Then
Err.Raise vbObjectError + 1001, "Allocator", "稼働率が0以下です。割り当て不可能です。"
End If
' 実効稼働時間を算出
Dim effectiveDailyCapacity As Double
effectiveDailyCapacity = dailyCapacity availabilityRate
' 必要な日数を算出
CalculateAssignmentDays = workHours / effectiveDailyCapacity
End Function
---
3. 現場で使えるプロダクションコード:実行モジュール
データ連携の際は、`Dictionary`オブジェクトを使用してメモリ上でリソースを管理し、最後にシートへ転記する手法を推奨する。
Sub ExecuteResourceAllocation()
‘ データベース代わりのシートからデータを読み込み
Dim wsData As Worksheet: Set wsData = ThisWorkbook.Sheets(“TaskData”)
Dim lastRow As Long: lastRow = wsData.Cells(wsData.Rows.Count, 1).End(xlUp).Row
‘ 計算ロジックの呼び出し
Dim allocator As New ResourceAllocator
Dim i As Long
Application.ScreenUpdating = False ‘ パフォーマンス向上のお約束
For i = 2 To lastRow
Dim work As Double: work = wsData.Cells(i, 2).Value
Dim rate As Double: rate = wsData.Cells(i, 3).Value
‘ 計算結果をエラーハンドリングしつつ出力
On Error Resume Next
Dim days As Double
days = allocator.CalculateAssignmentDays(work, rate)
If Err.Number <> 0 Then
wsData.Cells(i, 4).Value = “Error: ” & Err.Description
Else
wsData.Cells(i, 4).Value = Round(days, 2)
End If
On Error GoTo 0
Next i
Application.ScreenUpdating = True
MsgBox “全割り当て計算が完了しました。”, vbInformation
End Sub
—
4. プロジェクト成功のための鉄則
ファイル連携とデータベース
VBAで大規模なリソース管理を行うなら、Excelをデータベースとして使う限界を理解せよ。
- 単一ソースの真実: 割り当てのマスターデータは常に「CSV」または「外部DB(SQL Server等)」に置け。Excelはあくまで「フロントエンド(入力・出力用UI)」として扱うこと。
- トランザクションの意識: シートへの書き込みは一度に行え。ループの中で逐次書き込むコードは、将来的に必ずパフォーマンス問題を引き起こす。
保守性のための極意
- マジックナンバーの排除: `8#`(1日の労働時間)などは定数(`Const`)として定義せよ。
- エラーの可視化: 計算不能なデータが発生した際、黙ってスキップするな。必ずシート上にエラー内容を明示し、ユーザーが修正できるようにせよ。
—
最後に:エンジニアとしての矜持
VBAは「レガシーな言語」と揶揄されることもある。しかし、プロジェクトの現場で最も手軽に、かつ強力に業務を自動化できる武器であることに変わりはない。
「動けばいい」という考えは捨てろ。
あなたが書いたそのコードは、半年後の自分や、あなたのツールを使うチームメンバーが修正する可能性がある。保守のしやすさ、計算ロジックの透明性、そして何より「ビジネスロジックへの深い理解」をコードに反映させることこそが、真のエンジニアの仕事である。
さあ、このコードを土台に、君だけの最強のリソース管理ツールを構築せよ。
