【テクニカル・上級編】【中級者】プレゼンテーション内の不要なスライドマスターや未使用レイアウトを自動検出してパージし、ファイルサイズをスリム化した状態で保存する軽量化マクロ – PowerPoint VBA解析バイブル

スポンサーリンク

PowerPoint VBAを掌握する極限の知見:肥大化したプレゼンテーションを外科手術でパージせよ

長年運用されてきたPowerPointファイル(.pptx)は、テンプレートの継ぎ接ぎや度重なるコピペの果てに、「ゾンビ・レイアウト」と「見えないバイナリの残骸」を大量に蓄積していく。これらはGUIからの手動操作では完全に駆除できず、ファイルサイズを不当に膨らませ、ネットワーク転送のボトルネックやメモリリークの温床となる。

今回は、PowerPoint VBAのオブジェクトモデルの深層を突くことで、未使用のスライドマスターおよびレイアウトを完全にパージし、極限までファイルサイズを圧縮して安全に保存するメンテナンス・エンジンの全貌を公開する。

レガシーなCOMコンポーネントの挙動を知り尽くしたシニアエンジニアだけが扱える、実戦投入可能なコードだ。

—

1. 肥大化の元凶:なぜマスターとレイアウトは削除できないのか?

PowerPointの内部構造において、スライドマスターとそれに従属するスライドレイアウトは、一種の「参照カウント方式」に近い親子関係を持っている。

しかし、GUI上で不要になったレイアウトを削除しようとしても、以下のような理由で拒絶されるか、ファイル内にゴミとして残存する。

  • 過去に一度でもスライドに適用された履歴がある場合、内部の参照ポインタが残留する。
  • 破損したXML構造や、OLEオブジェクトのキャッシュがレイアウト内部に隠蔽される。

これをコードから正確に検知するには、「全スライドが実際にどのレイアウト・マスターを参照しているか」の依存関係グラフをメモリ上に構築し、どのスライドからも参照されていない孤立ノード(孤児)を特定して物理削除しなければならない。

—

2. アーキテクチャ設計:パージエンジンの要件

本マクロは、以下のステップで安全かつ確実なスリム化を実行する。

1. 参照整合性チェック(Dependency Mapping):
プレゼンテーション内の全スライド(`Slide`オブジェクト)を走査し、使用されている `CustomLayout` のIDをハッシュ(VBAではDictionary)に収集する。
2. 未使用レイアウトのパージ(Layout Pruning):
マスターに紐づく全レイアウトを走査し、収集したIDリストに含まれないものを `Delete` メソッドで完全抹消する。
3. 未使用スライドマスターのパージ(Master Pruning):
レイアウトが1枚も残らなくなった、あるいは最初から使われていないスライドマスターを特定し、削除する(※PowerPointの仕様上、最低1つのマスターは保持される点に注意)。
4. バイナリ最適化保存(Garbage Collected Save):
単なる `Save` ではなく、内部の不要なストリームを切り落として再構築させるための別名保存(または最適化プロセス)を挟む。

—

3. 実装コード:スリム化メンテナンス・エンジン

以下のコードをVBAの標準モジュールに実装し、実行せよ。エラーハンドリングとオブジェクトの明示的解放を徹底し、長大プレゼンターのメモリ破綻を防ぐ設計としている。

Option Explicit

‘ ==============================================================================
‘ 致命的なファイル肥大化を解消するスライドマスター&レイアウト・パージエンジン
‘ Architecture Type: DOM Manipulation & Reference Graph Pruning
‘ ==============================================================================
Public Sub PurgeUnusedLayoutsAndOptimize()
Dim targetPres As Presentation
Set targetPres = ActivePresentation ‘ または Workbooks.Open 等で指定

Dim startTime As Single
startTime = Timer

On Error GoTo ErrorHandler

‘ 画面描画の完全停止(DOM操作の高速化)
Application.ScreenUpdating = False

Dim initialSize As Double
initialSize = GetFileSize(targetPres)

MsgBox “メンテナンスを開始します。” & vbCrLf & _
“初期ファイルサイズ: ” & Format(initialSize / 1024 / 1024, “0.00”) & ” MB”, vbInformation, “アーキテクチャ・診断”

‘ ————————————————————————–
‘ Step 1: 使用されているレイアウトのハッシュマップ(Dictionary)構築
‘ ————————————————————————–
Dim usedLayouts As Object
Set usedLayouts = CreateObject(“Scripting.Dictionary”)

Dim sld As Slide
Dim layoutName As String

For Each sld In targetPres.Slides
On Error Resume Next
‘ カスタムレイアウトの固有名またはポインタをキーとして登録
layoutName = sld.CustomLayout.Name
If Err.Number = 0 Then
If Not usedLayouts.Exists(layoutName) Then
usedLayouts.Add layoutName, True
End If
End If
On Error GoTo ErrorHandler
Next sld

‘ ————————————————————————–
‘ Step 2: 未使用カスタムレイアウトのパージ
‘ ————————————————————————–
Dim master As Design
Dim lay As CustomLayout
Dim deletedLayoutCount As Long
deletedLayoutCount = 0

‘ 後ろからループ(コレクション削除の鉄則)
For Each master in targetPres.Designs
For i = master.SlideLayouts.Count To 1 Step -1
Set lay = master.SlideLayouts(i)

‘ 既定の標準レイアウト(表題、白紙など)は保護対象とする場合があるが、
‘ 完全パージを目指す場合は依存関係のみで判定する
If Not usedLayouts.Exists(lay.Name) Then
‘ 安全装置:もしマスターに紐づくレイアウトがすべて消えるとエラーになるため最低限は残す考慮が必要だが、
‘ PowerPointの仕様上、アクティブなレイアウトは削除できないため、エラーは無視する
On Error Resume Next
lay.Delete
If Err.Number = 0 Then
deletedLayoutCount = deletedLayoutCount + 1
End If
On Error GoTo ErrorHandler
End If
Next i
Next master

‘ ————————————————————————–
‘ Step 3: 未使用スライドマスターのパージ
‘ ————————————————————————–
Dim deletedMasterCount As Long
deletedMasterCount = 0

‘ デザイン(マスター)の中に有効なレイアウトが1つもない、あるいはスライドから参照されていないものを削除
For i = targetPres.Designs.Count To 2 Step -1 ‘ 最初のマスター(既定)は原則削除不可のため2以降
Set master = targetPres.Designs(i)
If master.SlideLayouts.Count = 0 Then
On Error Resume Next
master.Delete
If Err.Number = 0 Then
deletedMasterCount = deletedMasterCount + 1
End If
On Error GoTo ErrorHandler
End If
Next i

‘ ————————————————————————–
‘ Step 4: 最適化保存(ガベージコレクションを伴うリセーブ)
‘ ————————————————————————–
Dim savePath As String
If targetPres.Path = “” Then
‘ 未保存の場合は一時フォルダ等へ強制保存
savePath = Environ(“TEMP”) & “\Optimized_” & Format(Now, “yyyymmdd_hhnnss”) & “.pptx”
Else
‘ 同名で上書き、または最適化サフィックスを付与
Dim ext As String
ext = Right(targetPres.Name, 5)
savePath = targetPres.Path & “\Optimized_” & targetPres.Name
End If

targetPres.SaveAs savePath

Application.ScreenUpdating = True

Dim finalSize As Double
finalSize = FileLen(savePath)

Dim compressionRate As Double
If initialSize > 0 Then
compressionRate = (1 – (finalSize / initialSize)) 100
Else
compressionRate = 0
End If

MsgBox “メンテナンスが正常終了しました。” & vbCrLf & _
“———————————-” & vbCrLf & _
“削除された未使用レイアウト: ” & deletedLayoutCount & ” 件” & vbCrLf & _
“削除された空マスター: ” & deletedMasterCount & ” 件” & vbCrLf & _
“最終ファイルサイズ: ” & Format(finalSize / 1024 / 1024, “0.00”) & ” MB” & vbCrLf & _
“圧縮率: ” & Format(compressionRate, “0.0”) & ” %” & vbCrLf & _
“保存先: ” & savePath, vbInformation, “パージ完了”

Exit Sub

ErrorHandler:
Application.ScreenUpdating = True
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “Critical Error”
End Sub

‘ ——————————————————————————
‘ 補助関数: ファイルサイズの安全な取得
‘ ——————————————————————————
Private Function GetFileSize(pres As Presentation) As Double
On Error Resume Next
If pres.Path <> “” Then
GetFileSize = FileLen(pres.FullName)
Else
GetFileSize = 0
End If
On Error GoTo 0
End Function

—

4. チーフアーキテクトの視点:コードの急所と実戦上の注意点

このマクロを導入するにあたり、以下の「現場の罠」を理解しておく必要がある。

1. コレクション逆順ループの鉄則

レイアウトやデザインを削除する際、`For i = 1 To Count` の順方向でループを回すと、インデックスのズレ(Index Shift)が発生し、必ず `Run-time error ‘438’` や予期せぬスキップを引き起こす。コレクションの破壊的変更は、必ず末尾から先頭に向かって(Step -1)実行しなければならない。

2. オブジェクトモデルの制限(Default Masterの保護)

PowerPointの仕様上、最後に残った1つのスライドマスター、および各マスター内の主要なビルトインレイアウト(表題やタイトルとコンテンツなど)は、たとえ現在どのスライドからも参照されていなくても削除できない(APIレベルで拒絶される)。そのため、エラーハンドリング(`On Error Resume Next`)による安全な無視がアーキテクチャ上必須となる。

3. XMLパッケージの再構築効果

`SaveAs` を実行することで、PowerPointは内部のZIPパッケージ(`ppt/slides/`, `ppt/slideLayouts/` 等)のXML構造を再構築し、使われなくなったリレーションシップ(`.rels`)やメディアファイルを完全に物理領域から消去する。これが、単なるメモリ上の削除にとどまらず、劇的なファイルサイズ圧縮を生むメカニズムの正体である。

—

結語

レガシーなPowerPoint資産の管理は、放置すればするほどシステム的な負債となり、RPAや自動生成バッチのメモリクラッシュを引き起こす。
今回提供したパージエンジンを社内の自動化パイプラインや定時メンテナンススクリプトに組み込むことで、肥大化したプレゼンテーションの悩みを根本から断ち切ってほしい。

技術とは、常にコードによって秩序を取り戻すためにある。

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