こんにちは!パワポの自動化で日々の残業を削り取る、あなたの「優しい先輩エンジニア」です。
マクロの記録から一歩踏み出し、PowerPoint VBAのオブジェクトモデルに触れ始めたあなた、素晴らしい挑戦ですね!ここをクリアすれば、スライド作成の自動化なんて怖くありません。
さて、今回は多くの実務者が頭を悩ませる「動的な目次スライドの自動生成」をテーマにお届けします。
「非表示スライドを入れたらページ番号がズレた」「セクションを移動したら目次が使い物にならなかった」……そんな悲劇を、VBAの知見で美しく解決しましょう。
ここをクリアすれば、PowerPoint VBAの基本とオブジェクトの機微はバッチリです。一緒に極限の知見をモノにしていきましょう!
—
1. なぜ「目次」の自動化は難しいのか?
PowerPointでプレゼン資料を作るとき、最初に「目次スライド」を置きますよね。
ページ数が少ないうちは手動で修正できますが、枚数が50枚、100枚と増え、さらに「非表示スライド」や「セクションの並び替え」が発生した瞬間、地獄が始まります。
ここで、PowerPoint VBA初学者が必ずハマる「2つのトラップ」があります。それが、今回解説する `SlideIndex` と `SlideNumber` の違いです。
トラップの正体:「Index」と「Number」の非同期
- `SlideIndex`(スライドインデックス)
- 物理的な「左側のサムネイル一覧における上からの順番」です。非表示だろうが関係なく、1番目、2番目とカウントされます。
- `SlideNumber`(スライド番号)
- 聴衆に見える「実際の印刷・スライドショー上のページ番号」です。「非表示スライド」はこの番号がスキップされます。
つまり、非表示スライドが存在する資料で単純に `SlideIndex` を目次に書いてしまうと、実際のページの場所と完全にズレてしまうのです。このズレをロジックでどう埋めるか? ここが今回のエンジニアとしての腕の見せ所です。
—
2. 開発の舞台裏:知っておくべきオブジェクト構造
PowerPoint VBAを操る上で、オブジェクトの階層構造(親子関係)を理解することは不可欠です。今回のアルゴリズムで鍵となるのは以下の階層です。
Application (PowerPoint全体)
└── ActivePresentation (現在開いているプレゼンテーション)
├── Slides (コレクション:すべてのスライド)
│ └── Slide (個別スライド:Indexを持つ)
└── SectionProperties (セクションを管理するプロパティ)
セクションごとに見出しを抽出し、そのセクションの先頭にあるスライドが「実際には何番のページ(SlideNumber)なのか」を計算で導き出す。これが今回のアルゴリズムの核心です。
—
3. 【実践】セクション追従型・動的目次生成アルゴリズム
お待たせしました。実際の現場でそのままコピペして使える、堅牢で美しいVBAコードを公開します。
このコードは、セクション名を取得し、そのセクションの最初のスライドが持つ「本当のページ番号」を割り出して、目次スライドのテキストフレームに流し込みます。
プレミアム・VBAコード
Sub GenerateDynamicTOC()
‘ =====================================================================
‘ 目的: セクション構成と非表示スライドに完全追従する動的目次スライドの生成
‘ 対象: アクティブなプレゼンテーションの先頭スライドを目次と仮定
‘ =====================================================================
Dim pres As Presentation
Set pres = ActivePresentation
‘ エラーハンドリングの基本:スライドが少なすぎる場合などを弾く
If pres.Slides.Count < 2 Then
MsgBox "スライドが少なすぎます。目次を作成する対象がありません。", vbExclamation, "警告"
Exit Sub
End If
On Error GoTo ErrorHandler
' -----------------------------------------------------------------
' 1. 目次スライドの特定(ここでは仮に「1枚目のスライド」を指定)
' -----------------------------------------------------------------
Dim tocSlide As Slide
Set tocSlide = pres.Slides(1)
' -----------------------------------------------------------------
' 2. セクション情報の走査と目次テキストの構築
' -----------------------------------------------------------------
Dim secProps As SectionProperties
Set secProps = pres.SectionProperties
If secProps.Count = 0 Then
MsgBox "セクションが設定されていません。セクションを定義してから実行してください。", vbExclamation, "警告"
Exit Sub
End If
Dim tocText As String
tocText = "【 本日のアジェンダ 】" & vbCrLf & vbCrLf
Dim i As Long, j As Long
Dim secName As String
Dim firstSlideIndex As Long
Dim targetSlide As Slide
Dim actualPageNumber As Long
' セクションを上から順にループ
For i = 1 To secProps.Count
secName = secProps.Name(i)
firstSlideIndex = secProps.FirstSlide(i)
' セクションの最初のスライドオブジェクトを取得
Set targetSlide = pres.Slides(firstSlideIndex)
' 【重要】非表示スライドの場合の考慮とSlideNumberの取得
' ※非表示スライドは SlideNumber が 0 を返す仕様があるため、その対策も内包
If targetSlide.SlideShowTransition.Hidden = msoTrue Then
' 非表示の場合は、直近の「表示されているスライド」の番号を探すなどのフォールバックが必要ですが、
' 今回はシンプルに「非表示なら(非表示)」と注記するロジックにします
actualPageNumber = 0 ' 非表示の目印
Else
actualPageNumber = targetSlide.SlideNumber
End If
' 目次文字列の組み立て
tocText = tocText & "・ " & secName
If actualPageNumber > 0 Then
tocText = tocText & ” ………………………………. ” & actualPageNumber & “ページ” & vbCrLf
Else
tocText = tocText & ” ………………………………. (非表示)” & vbCrLf
End If
Next i
‘ —————————————————————–
‘ 3. 目次スライドへのテキスト出力(シェイプの自動生成 or 上書き)
‘ —————————————————————–
Dim targetShape As Shape
Dim foundBox As Boolean
foundBox = False
‘ 既存の目次用テキストボックスを探す(名前を “TOC_Box” と仮定)
For Each targetShape In tocSlide.Shapes
If targetShape.Name = “TOC_Box” Then
foundBox = True
Exit For
End If
Next targetShape
‘ なければ新規作成、あれば中身を書き換え
If Not foundBox Then
Set targetShape = tocSlide.Shapes.AddTextbox(msoTextOrientationHorizontal, 100, 150, 600, 400)
targetShape.Name = “TOC_Box”
End If
With targetShape.TextFrame
.TextRange.Text = tocText
.TextRange.Font.Name = “MeiryoUI”
.TextRange.Font.Size = 18
.TextRange.Font.Color.RGB = RGB(50, 50, 50)
End With
MsgBox “目次スライドの更新が完了しました!”, vbInformation, “成功”
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End Sub
—
4. コードの深掘り:ここがプロの技術
上記のコードで、特に注目してほしいポイントを解説します。
1. `secProps.FirstSlide(i)` の活用
セクションが持つ「最初のスライドのIndex」をダイレクトに取得しています。これにより、ユーザーがセクションの順番を入れ替えても、常に正しいセクションの先頭を追跡できます。
2. 非表示(Hidden)の判定
`targetSlide.SlideShowTransition.Hidden` をチェックすることで、「非表示スライドが目次のジャンプ先になってしまっている」という不格好なミスを防いでいます。実務では、非表示スライドは目次から除外するか、上記のように明示することがプロのクオリティです。
3. シェイプの存在チェックと動的生成
いきなりテキストボックスを追加するのではなく、`”TOC_Box”` という名前のシェイプが既に存在するか走査しています。これにより、何度マクロを実行しても目次枠が重複して爆誕する事故を防いでいます。
—
まとめ:自動化の先にある快適な世界へ
今回は、PowerPoint VBAにおける `SlideIndex` と `SlideNumber` の違いを突破し、セクションに追従する動的目次生成アルゴリズムを解説しました。
ここをクリアしたあなたなら、単なる「操作の記録」ではなく、「ドキュメントの構造を理解し、ロジックで制御するVBA」の本質を掴んだはずです。
手作業によるコピペやページ番号の数え間違いから解放され、あなたはよりクリエイティブな構成案の検討に時間を割くことができるようになります。
ぜひ、あなたの実務資料にこのコードを組み込んで、周囲をあっと言わせてくださいね!
それでは、次回の極限の知見でお会いしましょう。お疲れ様でした!
