【実務・中級編】【中級者】プレゼンテーション内のすべての図形・画像に対して、適切な「代替テキスト(アクセシビリティ情報)」が設定されているかを検査し、不足分を自動補完して保存するマクロ – PowerPoint VBA解析バイブル

スポンサーリンク

PowerPoint VBAを掌握する極限の知見

アクセシビリティの罠:すべての図形・画像に「代替テキスト」を強制し、安全に保存する自動化アーキテクチャ

開発現場でプレゼンテーション資料の品質管理を任されたとき、最も見落とされがちなのが「アクセシビリティ(代替テキスト)」だ。
WCAG(Web Content Accessibility Guidelines)やJIS X 8341-3などの基準が厳格化する昨今、企業が外部に公開する、あるいは社内ニッチなコンプライアンス基準をクリアしなければならない資料において、図形や画像に代替テキスト(Alt Text)が設定されていない状態は、いわば「コンプライアンス違反の爆弾を抱えている」と同義である。

しかし、数百枚スライドがある巨大なデッキに対して、人間が目視でプロパティを確認し、マウスでカチカチと入力していく作業は、エンジニアの人生の無駄遣いであり、ヒューマンエラーの温床でしかない。

今回は、PowerPoint VBAのオブジェクトモデルを限界までハックし、「未設定の代替テキストを検知し、ファイル名や図形の種類から動的に自動補完した上で、安全にバリデーション・保存を行うプロダクションコード」を伝授する。

—

1. なぜ従来のVBAコードは現場で破綻するのか?

ネットの海を漂う「PowerPoint 代替テキスト VBA」のコードの大半は、お遊戯レベルのプロトタイプに過ぎない。実務の現場でそれらを動かすと、確実に以下の壁にぶつかる。

1. `AlternativeText` と `Title` の混同
PowerPointのオブジェクトモデルにおいて、代替テキストには「タイトル(Title)」と「説明(Description)」の2つのプロパティが存在する。バージョンやOfficeの仕様によって参照すべき領域が異なり、ここを誤ると「設定したはずなのに空欄扱いになる」という現象が起きる。
2. グループ化された図形(`ShapeRange` / `GroupShapes`)の無視
素人が書いたコードは、トップレベルの `Shapes` コレクションしか走査しない。グループ化された内部の図形は完全にスルーされ、監査で一発レッドカードを喰らう。
3. プレースホルダー(`Placeholder`)の誤爆
タイトルや本文を入力するための標準プレースホルダーにまで無理やり代替テキストを設定しようとして、意図せぬ例外エラーを発生させる。

これらを完全に克服した「実戦投入可能な堅牢なコード」を次項で公開する。

—

2. 【プロダクションコード】代替テキストの自動検査・補完エンジン

以下のコードは、アクティブなプレゼンテーションを走査し、すべての描画オブジェクト(グループ内も再帰的に走査)をチェック。代替テキストが空であれば、図形の種類やインデックスからフォールバック文字列を自動補完し、監査ログをイミディエイトウィンドウに出力した上で上書き保存する。

Option Explicit

‘ ==============================================================================
‘ 処理名 : AuditAndPatchAccessibilityAltText
‘ 概要 : プレゼン内の全図形(グループ内含む)の代替テキストを検査・補完し保存する
‘ ==============================================================================
Public Sub AuditAndPatchAccessibilityAltText()
Dim targetPres As Presentation
Set targetPres = ActivePresentation

Dim totalChecked As Long
Dim totalPatched As Long
totalChecked = 0
totalPatched = 0

Dim sld As Slide
For Each sld In targetPres.Slides
‘ スライド内の全シェイプを再帰的に走査
Call ProcessShapesRecursive(sld.Shapes, totalChecked, totalPatched)
Next sld

‘ 変更を安全に保存
On Error GoTo SaveError
targetPres.Save
On Error GoTo 0

‘ 完了レポート
MsgBox “アクセシビリティ監査が完了しました。” & vbCrLf & _
“・検査総数: ” & totalChecked & ” 個” & vbCrLf & _
“・自動補完数: ” & totalPatched & ” 個”, vbInformation, “監査完了”
Exit Sub

SaveError:
MsgBox “保存中にエラーが発生しました: ” & Err.Description, vbCritical, “致命的なエラー”
End Sub

‘ ==============================================================================
‘ 関数名 : ProcessShapesRecursive
‘ 概要 : シェイプコレクションを再帰的に走査し、代替テキストの有無を判定する
‘ ==============================================================================
Private Sub ProcessShapesRecursive(ByVal shapesCol As Shapes, ByRef checkedCount As Long, ByRef patchedCount As Long)
Dim shp As Shape
Dim altText As String

For Each shp In shapesCol
‘ 1. プレースホルダーや非表示図形など、代替テキストが不要・設定不可なものをスキップ
If ShouldSkipShape(shp) Then GoTo ContinueLoop

checkedCount = checkedCount + 1

‘ 2. 代替テキスト(Description)の取得
‘ ※PowerPointの仕様上、AltTextは Description プロパティに格納される
On Error Resume Next
altText = shp.AlternativeText
On Error GoTo 0

‘ 3. 代替テキストが未設定(空文字、またはデフォルトのプレースホルダー名等)の場合の処理
If Trim(altText) = “” Or altText = shp.Name Then
‘ 自動補完ロジック:図形の種類や名前から意味のある代替テキストを生成
altText = GenerateFallbackAltText(shp)

‘ 代替テキストを書き込む
On Error Resume Next
shp.AlternativeText = altText
‘ 一部の古いバージョンや特殊オブジェクト対策としてTitleも設定
shp.Title = “Auto-generated: ” & shp.Name
On Error GoTo 0

patchedCount = patchedCount + 1
Debug.Print “[補完実行] スライドID: ” & shp.Parent.SlideIndex & ” / 図形名: ” & shp.Name & ” -> 補完値: ” & altText
End If

‘ 4. グループ図形の場合は再帰処理
If shp.Type = msoGroup Then
Call ProcessShapesRecursive(shp.GroupItems, checkedCount, patchedCount)
End If

ContinueLoop:
Next shp
End Sub

‘ ==============================================================================
‘ 関数名 : ShouldSkipShape
‘ 概要 : 代替テキストの検査対象外とすべき図形を判定する
‘ ==============================================================================
Private Function ShouldSkipShape(ByVal shp As Shape) As Boolean
‘ プレースホルダー(タイトルや本文の枠)は通常、スクリーンリーダーはテキスト自体を読むためスキップ
If shp.Type = msoPlaceholder Then
ShouldSkipShape = True
Exit Function
End If

‘ ガイドや不可視の図形などはスキップ(必要に応じて拡張)
If Not shp.Visible Then
ShouldSkipShape = True
Exit Function
End If

ShouldSkipShape = False
End Function

‘ ==============================================================================
‘ 関数名 : GenerateFallbackAltText
‘ 概要 : 不足している代替テキストを文脈に合わせて動的に生成する
‘ ==============================================================================
Private Function GenerateFallbackAltText(ByVal shp As Shape) As String
Dim baseName As String
baseName = “図形”

Select Case shp.Type
Case msoPicture, msoLinkedPicture
baseName = “画像”
Case msoChart
baseName = “グラフ”
Case msoTable
baseName = “テーブル”
Case msoSmartArt
baseName = “SmartArtグラフィック”
Case msoGroup
baseName = “グループ化された図版”
Case Else
baseName = “デザイン図形”
End Select

‘ 現場のルールに合わせ、図形名やインデックスを付与してユニークかつ説明的なテキストにする
GenerateFallbackAltText = baseName & ” (” & shp.Name & “)”
End Function

—

3. チーフアーキテクトが教える、実務適用の極意と注意点

このスクリプトを実際の業務フロー(例えば、月次報告書の自動生成パイプラインや、ファイルサーバーへの一括保存前フック)に組み込む際、以下のアーキテクチャ上のポイントを押さえておく必要がある。

Ⅰ. オブジェクトのライフサイクルとメモリ管理

VBAにおける `Shape` や `Slide` オブジェクトの参照は、ループを抜ける際に適切に解放される。しかし、巨大なプレゼンテーション(例えば50MB超のファイル)を処理する場合、ガベージコレクションのタイミングやメモリリークに注意しなくてはならない。
不要なオブジェクト変数への `Set xxx = Nothing` の明示的な記述は、長時間のバッチ処理においてプロセスが突然落ちる現象(COM例外)を防ぐ防壁となる。

Ⅱ. 「自動補完」の限界とヒューマンレビューの担保

このコードでは、未設定の代替テキストに対して `GenerateFallbackAltText` 関数で「画像 (Picture 4)」のようなフォールバック文字列を動的に流し込んでいる。
これは「アクセシビリティ監査ツールによるエラー判定(ヌル抜け)を回避する」ためには極めて有効だが、視覚障害者に対する本来のアクセシビリティ(画像の意味を的確に伝えること)としては不十分である。
したがって、本番運用においては、このマクロで「未設定をゼロ(エラーフリー)」にした上で、デザイナーや作成者が主要な図形のみ手動で詳細な説明に書き換える、という「2段階の品質統制プロセス」を構築するのが最もスマートである。

Ⅲ. ファイルのトランザクション管理(上書き保存の危険性)

コード内では素直に `targetPres.Save` を叩いているが、実務の自動化パイプラインにおいては、元ファイルを直接書き換えるのではなく、処理の途中で一時ファイル(Temp)に別名保存し、すべての例外処理を無事に通過したことを確認してから元のパスにアトミックに置き換える(上書きする)設計が望ましい。

—

総括

PowerPoint VBAは、単なる「お絵描きマクロの記録ツール」ではない。適切に設計されたオブジェクト走査と例外ハンドリングを組み合わせることで、企業のコンプライアンスリスクを自動で担保する強力なガバナンス・エンジンへと昇華させることができる。

「手作業で数千個の図形を確認する」という前時代的な悪習は、今日この瞬間で終わりにしよう。コードをデプロイし、真に価値のある創造的な業務にリソースを集中させよ。

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