「マクロの記録」を卒業しよう。PowerPointの構造を支配する「フォントマネージャー」構築術
こんにちは。現場の自動化を支えるアーキテクトです。
皆さんは、外部から送られてきたプレゼンテーション資料を開いて、絶望したことはありませんか?
「フォントがバラバラだ……」「MS ゴシックだったり、Arialだったり、誰が設定したのか分からない……」
手作業で一つずつテキストボックスをクリックしてフォントを変える。それは、エンジニアではなく「作業員」の仕事です。私たちが目指すべきは、「ルール(仕様)に基づき、一瞬で秩序を取り戻す仕組み」を作ること。
今日は、単なるコードの書き方ではなく、PowerPointという巨大なオブジェクトの構造をどう捉え、どう制御するか。その本質を伝授します。これをマスターすれば、あなたは「マクロの記録」から脱却し、真のVBAエンジニアへの一歩を踏み出すことができるでしょう。
1. 脳内に「オブジェクトの地図」を描く
VBAを書く前に、最も重要なことがあります。それは「PowerPointがどのような階層構造でできているか」を理解することです。
初心者の方がエラーで躓く最大の理由は、この「地図」を持っていないからです。PowerPointの構造は、まるでマトリョーシカのようになっています。
1. Application (PowerPointというアプリ自体)
2. Presentation (開いているファイル)
3. Slide (ファイルの中にある各スライド)
4. Shape (スライドの上にある図形、テキストボックス、画像など)
5. TextFrame (図形の中にある「テキストを入れるための枠」)
6. TextRange (枠の中にある「実際の文字情報」)
7. Font (文字の「書体」という属性)
フォントを変えたいなら、「スライドを巡回し、図形を見つけ、その図形がテキストを持っているか確認し、その中のフォントにアクセスする」というルートを辿る必要があります。このルートを間違えると、VBAは「そんなものはありません!」とエラーを吐いて止まってしまいます。
2. 実装:フォントマネージャーの設計図
では、実際に「全スライドのフォントを特定のものに統一し、別名で保存する」コードを書いてみましょう。
単に動くだけのコードではありません。「エラーで止まらない」「意図しない挙動を防ぐ」という、プロの設計思想を組み込んでいます。
Option Explicit
''' <summary>
''' スライド内の全テキストのフォントを社内標準に一括置換し、別名保存する
''' </summary>
Sub FontManager_Standardize()
' --- 設定エリア ---
Const TARGET_FONT As String = "Yu Gothic UI" ' 統一したいフォント名
Dim saveName As String
' ------------------
Dim pres As Presentation
Dim sld As Slide
Dim shp As Shape
Dim i As Integer
' 現在開いているプレゼンテーションをオブジェクト変数に格納
Set pres = ActivePresentation
' 保存用のファイル名を作成(元のファイル名 + _Fixed)
' ※元のファイルを上書きしないための安全策
saveName = pres.Path & "\" & Left(pres.Name, InStrRev(pres.Name, ".") - 1) & "_Fixed.pptx"
' 処理の高速化と画面のちらつき防止
' (大量のスライドがある場合、これだけで体感速度が劇的に変わります)
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
' 1. 全スライドをループで巡回
For Each sld In pres.Slides
' 2. スライド内の全図形(Shape)をループで巡回
For Each shp In sld.Shapes
' 3. その図形が「テキストを持てる種類」かどうかを判定
' ここが重要!画像や線に対してテキスト操作をしようとするとエラーになります
If shp.HasTextFrame Then
If shp.TextFrame.HasText Then
' 4. テキスト範囲のフォントを一括変更
' TextRangeは文字の集合体です。ここに対してFontプロパティを操作します
shp.TextFrame.TextRange.Font.Name = TARGET_FONT
End If
End If
' 【中級者へのTips】グループ化された図形への対応
' 図形がグループ化されている場合、shp.HasTextFrameはFalseになることがあります。
' 本格的なツールでは、ここで再帰処理(関数の中で自分自身を呼ぶ)が必要になります。
If shp.Type = msoGroup Then
Call ProcessGroupShapes(shp, TARGET_FONT)
End If
Next shp
Next sld
' 5. 別名で保存
pres.SaveAs Filename:=saveName
Application.ScreenUpdating = True
MsgBox "完了しました!" & vbCrLf & "保存先: " & saveName, vbInformation, "Success"
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox "予期せぬエラーが発生しました。" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"内容: " & Err.Description, vbCritical, "Error"
End Sub
''' <summary>
''' グループ化された図形の中まで潜ってフォントを書き換える補助関数
''' </summary>
Private Sub ProcessGroupShapes(ByVal targetGroup As Shape, ByVal fontName As String)
Dim subShp As Shape
' グループ内の各図形をチェック
For Each subShp In targetGroup.GroupItems
If subShp.HasTextFrame Then
If subShp.TextFrame.HasText Then
subShp.TextFrame.TextRange.Font.Name = fontName
End If
End If
' グループの中にさらにグループがある場合(入れ子構造)への対応
If subShp.Type = msoGroup Then
Call ProcessGroupShapes(subShp, fontName)
End If
Next subShp
End Sub
3. ここがプロの視点!コードの解説と「落とし穴」
このコードには、初学者が「マクロの記録」では絶対に到達できない、3つの重要なエッセンスが詰まっています。
① 「HasTextFrame」によるガード(防御的プログラミング)
初心者がやりがちなミスは、スライド上のすべての図形に対して「テキストを変えろ!」と命令することです。しかし、スライドには「写真」や「ただの線」も存在します。写真に対して「テキストを書き換えろ」と命令すると、VBAはパニックを起こして停止します。
`If shp.HasTextFrame Then` という一文を入れることで、「テキスト操作が可能なオブジェクトだけに命令を下す」という、安全な設計を実現しています。
② 再帰処理による「グループ化」の攻略
PowerPointで最も厄介なのが、「図形がグループ化されているケース」です。
通常のループでは、グループという「箱」は見つけられますが、その中の「中身」までは届きません。
そこで、`ProcessGroupShapes` という関数を作り、自分自身を呼び出す「再帰(さいき)」というテクニックを使いました。これにより、どれだけ複雑に入れ子になったグループであっても、隅々までフォントを書き換えることが可能になります。
③ データの整合性を守る「別名保存」
自動化ツールにおいて、最も恐ろしいのは「元データを壊してしまうこと」です。
もし処理中にエラーが起きて、元のファイルが中途半端な状態で上書きされてしまったら……。それは取り返しがつきません。
`pres.SaveAs` を使い、必ずオリジナルのファイルとは別の名前で保存する。これが、プロのエンジニアが持つ「ユーザーの資産を守る」という責任感です。
4. さあ、次はあなたの番です
ここまで読んでくれたあなたは、もう単なる「コピペ作業者」ではありません。
オブジェクトの階層を意識し、エラーを予見し、構造的な解決策を考えられる「設計者」の思考を手に入れ始めています。
「ここをクリアすれば、PowerPoint VBAの基本はバッチリですよ」
まずは、このコードを自分の環境で動かしてみてください。そして、フォント名を自分の好きなものに変えたり、保存するファイル名のルールを変えたりして、コードを「いじって」みてください。
コードが自分の意図通りに動いた瞬間の快感。それこそが、エンジニアリングの醍醐味です。
応援しています。また次のステージでお会いしましょう!
