こんにちは!Project VBAの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、自分の手でプロジェクトを意のままにコントロールしたい――そう思っているあなたへ。
今回は、実務で間違いなく重宝する「タスクの名前から自動的に階層(WBS)を判定し、インデントを自動適用するパーサー」の作り方を解説します。
「1. 〇〇」「1.1 〇〇」「1.1.1 〇〇」といった命名規則のテキストから、自動的にレベルを算出してProjectのタスクツリーを組み上げる……これぞエンジニアのロマンであり、日々の作業を劇的に楽にする魔法です。
ここをクリアすれば、Project VBAの基本と「タスク操作の本質」はバッチリです。優しく、そして深く解説していきますので、一緒にコーヒーでも飲みながら進めましょう!
—
1. なぜ「タスクの階層化」で躓くのか?
Excel VBAと違って、MS ProjectのVBAには独特の「癖」があります。それは「タスクは上から順番に追加するだけで勝手にツリーになるわけではない」という点です。
例えば、Excelならセルに文字を入れるだけですが、Projectでは「タスクを作る(`Tasks.Add`)」ことと、「インデントを下げる(`Outdent` / `Indent`)」ことは別の命令です。
【私たちがやりたいこと】
1. 計画フェーズ <- レベル1(親)
1.1 要件定義 <- レベル2(子)
1.1.1 ヒアリング <- レベル3(孫)
これを手動でやっていると、プロジェクトの規模が大きくなったときに発狂しそうになりますよね。だからこそ、「名前のドット(.)の数やパターンを読み解くパーサー(解析器)」をVBAで組む価値があるのです。
—
2. 階層構造を自動構築する全体像(アルゴリズム)
今回実装するパーサーの頭の中身(アルゴリズム)は非常にシンプルです。
1. テキストを1行ずつ読み込む(今回は簡単のため、あらかじめ用意した配列やテキストを想定)
2. タスク名に含まれる「ドット(.)」の数を数える、あるいは「番号の深さ」を正規表現や文字列操作で判定する
3. Projectにタスクを追加する
4. 直前のタスクと比較して、インデント(レベル)を調整する
特に重要なのが「4」のインデント調整です。Project VBAでは、タスクの階層を上下させるために `.OutlineIndent` や `.OutlineOutdent` メソッドを使います。
—
3. 実装コード:一撃でWBSを構築するVBAプロシージャ
それでは、開発環境(VBE)を開いて、以下のコードを標準モジュールに貼り付けてみてください。実務ですぐに使えるよう、丁寧なコメントを入れています。
Option Explicit
‘ ==============================================================================
‘ テーマ: タスク名から階層(WBS)を自動判定してインデントを構築するパーサー
‘ 解説: 命名規則(例: “1. 計画”, “1.1 要件定義”)を解析し、Projectのツリーを自動生成します。
‘ ==============================================================================
Sub AutoBuildWBS()
Dim rawData As Variant
Dim i As Long
Dim tsk As Task
Dim currentLevel As Long
Dim prevLevel As Long
Dim taskName As String
‘ 【サンプルデータ】実際の業務ではExcelや外部ファイルから読み込んでもOKです
rawData = Array( _
“1. 立ち上げフェーズ”, _
“1.1 キックオフミーティング”, _
“1.2 ステークホルダー調整”, _
“2. 計画フェーズ”, _
“2.1 要件定義”, _
“2.1.1 業務フロー作成”, _
“2.1.2 画面デザイン確定”, _
“2.2 スケジュール作成”, _
“3. 実行フェーズ” _
)
‘ エラーハンドリングの基本
On Error GoTo ErrorHandler
‘ 処理速度向上のための画面更新停止(Project VBAでも有効です)
Application.ScreenUpdating = False
prevLevel = 1 ‘ 初期レベル
‘ データを上から順に処理していく
For i = LBound(rawData) To UBound(rawData)
taskName = rawData(i)
‘ ① タスク名から現在の階層レベルを算出する(自作関数を呼び出し)
currentLevel = GetTaskLevel(taskName)
‘ ② Projectにタスクを追加する
Set tsk = ActiveProject.Tasks.Add(Name:=taskName)
‘ ③ 最初のタスク以外で、レベルに応じたインデント調整を行う
If i > 0 Then
If currentLevel > prevLevel Then
‘ 子タスクにする(一段階インデントを下げる)
Dim j As Long
For j = 1 To (currentLevel – prevLevel)
tsk.OutlineIndent
Next j
ElseIf currentLevel < prevLevel Then
' 親階層に戻る(インデントを上げる)
For j = 1 To (prevLevel - currentLevel)
tsk.OutlineOutdent
Next j
End If
' ※ currentLevel = prevLevel の場合は何もしなくてOK(同じ階層)
End If
' 次の比較のために現在のレベルを保持
prevLevel = currentLevel
Next i
Application.ScreenUpdating = True
MsgBox "WBSの自動構築が完了しました!", vbInformation, "成功"
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox "エラーが発生しました: " & Err.Description, vbCritical, "予期せぬエラー"
End Sub
' ==============================================================================
' 補助関数: タスク名に含まれるドット(.)の数からインデントレベルを判定する
' 例: "1." -> Level 1, “1.1” -> Level 2, “1.1.1” -> Level 3
‘ ==============================================================================
Private Function GetTaskLevel(ByVal taskName As String) As Long
Dim firstSpacePos As Long
Dim prefix As String
Dim dotCount As Long
‘ スペースで区切られた最初の部分(例: “1.1.1”)を取り出す
firstSpacePos = InStr(taskName, ” “)
If firstSpacePos > 0 Then
prefix = Left(taskName, firstSpacePos – 1)
Else
prefix = taskName
End If
‘ プレフィックスに含まれる「.」の数を数える
‘ 例: “1.” -> 1個, “1.1.” -> 2個、末尾のドットを考慮して調整
Dim i As Long
dotCount = 0
For i = 1 To Len(prefix)
If Mid(prefix, i, 1) = “.” Then
dotCount = dotCount + 1
End If
Next i
‘ ドットがない場合(例: “1” のみ)はレベル1とする
‘ ドットがある場合、ドットの数 + 1 が階層レベルになる(例: “1.1” はドット1個なのでレベル2)
If dotCount = 0 Then
GetTaskLevel = 1
Else
‘ 末尾にドットがあるケース(”1.1.”など)も考慮しつつ基本はドット数+1
If Right(prefix, 1) = “.” Then
GetTaskLevel = dotCount
Else
GetTaskLevel = dotCount + 1
End If
End If
End Function
—
4. コードの深掘りポイントと「初心者が陥りやすい罠」
ここで、プロの視点からコードの重要ポイントと、現場でやりがちな失敗をいくつかシェアしておきます。
罠その1:インデントの方向を間違えてタスクが迷子になる
初心者が一番やりがちなのが、`Indent` や `Outdent` をループで適当に呼び出してしまい、気づけば全タスクが一番下の階層に吸い込まれてしまう現象です。
> 【知見】
> Projectのインデント操作は「現在の位置」を基準にします。そのため、「前回のレベル(`prevLevel`)」と「今回のレベル(`currentLevel`)」の差分を正確に計算し、その差分(`Abs(currentLevel – prevLevel)`)の回数だけ正確に `OutlineIndent` または `OutlineOutdent` を叩く必要があります。今回のコードはその差分制御を完璧に実装しています。
罠その2:画面描画のチラつきを放置する
タスクを100個、1,000個と追加するマクロを実行するとき、`Application.ScreenUpdating = False` を書き忘れると、画面が猛烈に点滅し、処理速度が何倍も遅くなります。
Project VBAにおきましても、大量のオブジェクト操作を行う際は描画のミュートがエンジニアのたしなみです。
—
5. おわりに:ここをクリアすれば、もう怖くない!
お疲れ様でした!ここまで読み解けたあなたは、単なる「マクロの記録ユーザー」ではなく、立派なProject VBAエンジニアの第一歩を踏み出しています。
タスクの階層構造をプログラムで自在に操れるようになると、Excelで管理していたWBSをボタン一つでMS Projectにインポートしたり、外部システムから送られてきたJSONやCSVのタスク群を綺麗なツリー構造にして自動展開したりと、業務自動化の幅が無限に広がります。
「難しそう」に見えたProjectのオブジェクトモデルも、一つひとつのルール(ライフサイクルとインデントの仕組み)を紐解けば、あなたの忠実な部下になってくれます。
ぜひ、ご自身のプロジェクト環境でこのコードを試して、カチッと綺麗なWBSが一瞬で組み上がる爽快感を味わってみてください。
それでは、次回の極限知見でお会いしましょう!
