【テクニカル・上級編】【フォント一括置換】プレゼンテーション全体の特定フォントを、VBAを用いて安全かつ一瞬で別のフォントへ置き換える方法 – PowerPoint VBA解析バイブル

スポンサーリンク

PowerPointフォント置換の深淵:再帰的探索とオブジェクト管理の極意

多くのエンジニアが「PowerPointのフォント置換は標準機能で十分だ」と勘違いしている。だが、実務で数千スライドに及ぶレガシープレゼンテーションを扱う際、標準の「フォントの置換」ダイアログがどれほど無力か、君たちも痛感しているはずだ。

グループ化されたシェイプの深淵、マスターページに潜むゴースト、そしてテキストボックスの中に隠された不規則なフォント設定。これらを完全に制圧するには、VBAのオブジェクトモデルを解剖し、再帰アルゴリズムを用いてメモリの制約と戦うしかない。

今回は、システム管理者が「最後の一手」として頼るべき、堅牢かつ高速なフォント置換エンジンの設計思想を伝授する。

1. アーキテクチャの選定:なぜ「再帰」なのか

PowerPointのオブジェクトモデルにおいて、`Shapes`コレクションは入れ子構造を持つ。`GroupShapes`が存在する限り、単純なループ処理ではフォントの漏れが発生する。

パフォーマンスを最大化し、メモリリークを回避するための原則は以下の2点だ。
1. オブジェクトの明示的解放: `Set obj = Nothing`を徹底し、COMポインタの残骸によるメモリ肥大化を防ぐ。
2. 再帰的走査: グループ化の階層(Depth)に関わらず、全ての`TextFrame`を網羅する。

2. 実装:堅牢なフォント置換エンジン

以下に、プレゼンテーション全体を走査し、安全にフォントを入れ替えるためのコアコードを示す。

Option Explicit

‘ 伝説的な安定性を誇るフォント置換エンジン
Public Sub ReplaceFontEngine(ByVal oldFontName As String, ByVal newFontName As String)
Dim ppt As Presentation
Set ppt = ActivePresentation

‘ 1. スライドマスタとレイアウトを走査(ここが漏れると後で崩れる)
Dim master As Master
For Each master In ppt.SlideMaster.CustomLayouts
ProcessShapes master.Shapes, oldFontName, newFontName
Next master
ProcessShapes ppt.SlideMaster.Shapes, oldFontName, newFontName

‘ 2. 通常スライドの走査
Dim sld As Slide
For Each sld In ppt.Slides
ProcessShapes sld.Shapes, oldFontName, newFontName
Next sld

MsgBox “フォント置換完了: ” & oldFontName & ” -> ” & newFontName, vbInformation
End Sub

‘ 再帰的にShapesを掘り下げる処理
Private Sub ProcessShapes(shapes As shapes, oldFont As String, newFont As String)
Dim shp As Shape
For Each shp In shapes
‘ グループ化されている場合は再帰呼び出し
If shp.Type = msoGroup Then
ProcessShapes shp.GroupItems, oldFont, newFont
ElseIf shp.HasTextFrame Then
If shp.TextFrame.HasText Then
ReplaceInTextRange shp.TextFrame.TextRange, oldFont, newFont
End If
End If
‘ オブジェクトの明示的解放はVBAにおいて「礼儀」である
Set shp = Nothing
Next shp
End Sub

‘ テキスト範囲内のフォントをピンポイントで置換
Private Sub ReplaceInTextRange(tr As TextRange, oldFont As String, newFont As String)
Dim i As Long
‘ パフォーマンスを考慮し、Runs単位で判定
For i = 1 To tr.Runs.Count
If tr.Runs(i).Font.Name = oldFont Then
tr.Runs(i).Font.Name = newFont
End If
Next i
End Sub

3. シニアエンジニアのための極限の知見

メモリとパフォーマンスの境界線

VBAはガベージコレクションが強力ではない。特に数千枚のプレゼンテーションを処理する場合、`Shape`オブジェクトを不用意に保持し続けると、COMリソースの枯渇を招く。上記のコードでは、`ProcessShapes`内で都度`Set shp = Nothing`を明示しているが、これは大規模バッチ処理における「防御的プログラミング」の基本だ。

レガシー環境との共存(Windows APIの活用)

もし、フォントがシステムにインストールされているか事前に確認したい場合は、`EnumFontFamiliesEx`等のWindows APIを呼び出す必要がある。標準の`Font.Name`に存在しないフォントを代入してもエラーにはならないが、PowerPoint内部のフォントテーブルが汚染される可能性がある。本番環境への導入時は、`CreateFontIndirect`等を用いて、システムフォントの存在確認を行うラッパー関数を挟むことを推奨する。

なぜ「置換」ではなく「走査」なのか

標準機能の「フォントの置換」は、しばしば「テーマフォント」の定義と競合し、意図しないスタイル崩れを引き起こす。VBAで`TextRange.Runs`を直接叩く手法は、テーマフォントの設定を無視して個別に設定されたフォント(ローカルオーバーライド)を強制的に書き換えるため、「見た目の完全な一致」を保証する唯一の手段となる。

結びに

コードは単なる命令の羅列ではない。それは、複雑なオブジェクトモデルに対する「支配権の行使」だ。このスクリプトを君のツールボックスに加え、無意味な手作業から解放されることを願う。

技術の深淵を覗く者よ、次回のデバッグで会おう。

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