PowerPoint VBAを掌握する極限の知見:アクセシビリティ自動検査・補完エンジン
PowerPointの自動化において、多くの開発者は「図形を描画する」「テキストを流し込む」という生成のフェーズにしか目を向けない。しかし、エンタープライズ環境や公共性の高いシステムにおいて真に問われるのは、生成された成果物の「品質ガバナンス」である。
今回は、社内規定やWebアクセシビリティ基準(WCAG等)の遵守において見落とされがちな「代替テキスト(Alt Text)」に焦点を当てる。スライド内のすべての図形や画像を走査し、未設定の要素を検知して自動補完を行い、安全に永続化するプロダクション品質のVBAエンジンを構築する。
レガシーなCOMオブジェクトの挙動、メモリ管理の罠、そして実戦で耐えうる堅牢なエラーハンドリングの極意をここに明かす。
—
1. 建築的アプローチ:なぜ「代替テキストの自動化」が難所なのか?
PowerPointのオブジェクトモデルにおいて、代替テキストの実装は直感的ではない。
オブジェクトによってプロパティの持ち方が異なり、さらにグループ化された図形(`GroupShapes`)やレイアウトプレースホルダーの存在が、走査ロジックを複雑怪奇にする。
素朴なループ処理を書いた瞬間、以下の地雷を踏むことになる。
- グループ図形の迷宮: グループ化された内部の図形にアクセスし損ねる。
- プレースホルダーのノイズ: ユーザーが意図しない背景や空のプレースホルダーまで検査対象にしてしまい、処理が肥大化する。
- COMメモリリーク: 再帰処理や膨大なシェイプ走査時に、参照が解放されずExcelやPowerPointがメモリリークを起こす。
これらを完璧に制御するためには、「再帰的走査(Recursive Traversal)」と「厳格なオブジェクト解放」の二大原則を死守しなければならない。
—
2. 実装:アクセシビリティ品質管理エンジン
以下のコードは、アクティブなプレゼンテーションの全スライド、全シェイプ(グループ内含む)をくまなく走査し、代替テキストが空(あるいは未設定)の要素に対して構造化されたデフォルト値を自動補完した上で、上書き保存を実行するプロフェッショナル向けのマクロである。
Option Explicit
‘ —————————————————————–
‘ 構造化された品質管理のための定数定義
‘ —————————————————————–
Private Const DEFAULT_ALT_PREFIX As String = “自動補完対象: ”
Private Const LOG_PREFIX As String = “[Accessibility-Audit] ”
Public Sub ExecuteAccessibilityAuditAndSave()
Dim targetPres As Presentation
Set targetPres = ActivePresentation
If targetPres.Path = “” Then
MsgBox “プレゼンテーションがまだ保存されていません。一度保存してから実行してください。”, vbCritical, “致命的エラー”
Exit Sub
End If
Dim startTime As Double
startTime = Timer
On Error GoTo ErrorHandler
‘ 1. 監査と補完の実行
Dim fixedCount As Long
fixedCount = AuditAndPatchShapes(targetPres)
‘ 2. 安全な保存処理
targetPres.Save
MsgBox “アクセシビリティ監査が完了しました。” & vbCrLf & _
“修正・補完された要素数: ” & fixedCount & ” 件” & vbCrLf & _
“処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, _
vbInformation, “品質管理完了”
CleanExit:
‘ 参照の明示的破棄
Set targetPres = Nothing
Exit Sub
ErrorHandler:
MsgBox LOG_PREFIX & “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “システムエラー”
Resume CleanExit
End Sub
‘ —————————————————————–
‘ スライドおよびグループを再帰的に走査するコアエンジン
‘ —————————————————————–
Private Function AuditAndPatchShapes(ByVal pres As Presentation) As Long
Dim sld As Slide
Dim totalFixed As Long
totalFixed = 0
Dim i As Long, j As Long
For i = 1 To pres.Slides.Count
Set sld = pres.Slides(i)
totalFixed = totalFixed + ProcessShapesRecursive(sld.Shapes)
Set sld = Nothing
Next i
AuditAndPatchShapes = totalFixed
End Function
Private Function ProcessShapesRecursive(ByVal shapesCol As Shapes) As Long
Dim shp As Shape
Dim fixedCount As Long
fixedCount = 0
Dim i As Long
‘ コレクションの逆順ループは原則だが、参照カウントを確実にするため順方向でオブジェクトを厳密に管理
For i = 1 To shapesCol.Count
Set shp = shapesCol(i)
On Error Resume Next
Dim altText As String
‘ Office 2010以降で有効な AlternativeText プロパティへのアクセス
altText = shp.AlternativeText
If Err.Number <> 0 Then
‘ プロパティを持たない特殊な図形(プレースホルダー等)のエラーをクリア
Err.Clear
GoTo ContinueLoop
End If
On Error GoTo 0
‘ 代替テキストが未設定(空白)の場合の自動補完ロジック
If Trim(altText) = “” Then
shp.AlternativeText = GenerateDefaultAltText(shp)
fixedCount = fixedCount + 1
End If
‘ グループ図形の場合は再帰的に内部を走査
If shp.Type = msoGroup Then
fixedCount = fixedCount + ProcessShapesRecursive(shp.GroupItems)
End If
ContinueLoop:
Set shp = Nothing
Next i
ProcessShapesRecursive = fixedCount
End Function
‘ —————————————————————–
‘ 図形の種類に応じたインテリジェントなデフォルト値生成
‘ —————————————————————–
Private Function GenerateDefaultAltText(ByVal shp As Shape) As String
Dim shapeTypeName As String
Select Case shp.Type
Case msoPicture, msoLinkedPicture
shapeTypeName = “画像”
Case msoAutoShape
shapeTypeName = “オートシェイプ”
Case msoTextBox
shapeTypeName = “テキストボックス”
Case msoTable
shapeTypeName = “テーブル”
Case Else
shapeTypeName = “オブジェクト”
End Select
‘ スライド上の名前と一意性を担保した代替テキストを構築
GenerateDefaultAltText = DEFAULT_ALT_PREFIX & shapeTypeName & ” (” & shp.Name & “)”
End Function
—
3. チーフアーキテクトが解説するコードの急所
このスクリプトが一般的な「ネットのサンプルコード」と一線を画す所以を、アーキテクチャの観点から解説する。
① 堅牢なエラーハンドリングと `On Error Resume Next` の正しい使い方
VBAにおける `On Error Resume Next` は諸刃の剣である。これを漫然と使うとバグの温床になるが、今回のコードでは「特定のオブジェクトが `AlternativeText` プロパティをサポートしていない場合(例:一部のガイドラインオブジェクトや特殊コントロール)」に備えて、ピンポイントでガードするために使用している。
直後の `If Err.Number <> 0` でエラーを即座に捕捉・クリアし、通常のロジックへ復帰させることで、処理の途中でマクロがクラッシュするリスクを完全に排除している。
② 再帰処理におけるメモリマネジメント(`Set shp = Nothing`)
PowerPoint VBAで最も恐ろしいのは、ループ内で生成されたCOMオブジェクトの参照がスタックに残り続け、メモリを圧迫・リークさせる現象である。
特にグループ図形(`GroupItems`)を再帰処理する際、このメモリ管理を怠ると、スライド枚数が多い巨大なプレゼンテーションを処理した際にExcel/PowerPointが「メモリ不足」で強制終了する。
ループのインクリメントごとに `Set shp = Nothing` を明示的に実行し、ガベージコレクションのタイミングを待たずに即座にCOM参照を解放する設計が、プロフェッショナルとアマチュアを分ける境界線である。
③ インテリジェントな自動補完戦略
単に「No Description」と機械的に埋めるアプローチは、アクセシビリティの観点からは無意味(あるいは有害)である。
本エンジンでは、`shp.Type` を判定して「画像」「テーブル」「オートシェイプ」といったコンテキストを付与し、さらに `shp.Name`(PowerPointが内部で持っている一意のシェイプ名)を結合することで、後から人間がレビューや修正を行なう際のトレーサビリティ(追跡可能性)を確保している。
—
4. エンタープライズ環境への展開とシステム間連携
このVBAマクロを単体の個人用ツールとして終わらせてはならない。社内システムやCI/CDパイプライン(例えば、SharePointやTeamsにアップロードされたプレゼン資料の自動監査フロー)の一環として組み込むべきである。
- アドイン(.ppam)化: このコードを `.ppam` として保存し、組織全体のPowerPoint起動時に自動読み込みさせることで、全社員が意識することなくアクセシビリティ基準の底上げを図ることができる。
- 外部API/ロギング連携: 修正された件数や実行ログを、Windowsイベントログや社内WebAPIへPOSTする拡張を加えることで、「どの部署の資料がアクセシビリティ違反を起こしやすいか」というメタデータを収集し、全社的な品質ダッシュボードの構築すら可能となる。
総括
VBAはレガシーな言語と揶揄されることもあるが、ホストアプリケーション(PowerPoint)のCOMモデルを骨の髄まで理解し、メモリと例外のライフサイクルを完全に手中に収めたエンジニアが書いたコードは、現代のモダン言語によるシステムと同等、あるいはそれ以上の圧倒的な実用性と処理速度を発揮する。
あなたの手元にあるプレゼンテーションの山を、妥協なきエンジニアリングの力で今すぐ「アクセシブルで美しい資産」へと昇華させてほしい。
