【実務・中級編】【中級者】全図形や画像に対してアクセシビリティ上の「代替テキスト」が設定されているかを検査し、不足要素へ自動補完を行ってから保存する品質管理マクロ – PowerPoint VBA解析バイブル

スポンサーリンク
スポンサーリンク

プレゼンテーションの品質を「感覚」から「統治(ガバナンス)」へ。アクセシビリティ自動補完エンジンの設計思想

企業の広報資料や公的機関への提出資料において、今や「アクセシビリティ(情報のアクセシビリティ)」の確保は、単なるマナーではなく、法的・倫理的なコンプライアンスの問題へと昇華している。視覚障害を持つユーザーがスクリーンリーダーを利用する際、図解や写真に「代替テキスト(Alt Text)」が設定されていないことは、情報の欠落を意味する。

しかし、数百枚に及ぶスライドの全図形を、人間が目視でチェックするなど不可能だ。

多くの開発者が「全図形をループで回して、テキストが空なら名前を入れる」程度の簡易なスクリプトを書く。だが、それは「ツール」ではなく、単なる「不完全なスクリプト」だ。グループ化された図形、埋め込みオブジェクト、プレースホルダーの挙動を理解していないコードは、実務の現場ではバグを量産し、かえって資料を破壊する。

本記事では、プロフェッショナルが設計すべき「堅牢なアクセシビリティ検査・補完エンジン」の作り方を伝授する。

1. 設計における致命的な陥穽:なぜ単純なループでは足りないのか

初級者が書くコードの典型的な失敗は、`For Each shp In Slide.Shapes` という単一のループで処理を完結させようとすることだ。これでは、「グループ化された図形(Group Shapes)」の内部にあるオブジェクトを見落とす。

PowerPointのオブジェクトモデルは、ツリー構造(階層構造)を持っている。グループ化された図形の中にさらに図形があり、その中にまたグループがある……。この「オブジェクトグラフ」を完全に走査するためには、再帰的探索(Recursive Traversal)の設計が不可欠だ。

また、単に「空なら補完する」というロジックも危険だ。図形には「意味を持つ図形」と「装飾的な図形」がある。装飾的な図形にまで「Rectangle 5」といった機械的な名前を付けてしまうと、スクリーンリーダーを利用するユーザーにとっては、逆にノイズ(情報のゴミ)が増える結果となる。

2. アーキテクチャの要件定義

実務レベルのプロダクションコードとして実装する場合、以下の3点を設計思想の核に据える。

1. 再帰的走査の実装: グループ化の深さに依存せず、すべての末端オブジェクトを捕捉する。
2. インテリジェントな代替テキスト生成: 図形の `Name` プロパティや `TextFrame` の内容を解析し、文脈に沿った候補を生成する。
3. 監査ログ(Audit Log)の出力: 「何を変更したか」を記録に残す。これは、自動化ツールを業務に導入する際の、責任の所在を明確にするための必須要件だ。

3. 実装例:アクセシビリティ・ガバナンス・エンジン

以下に、これらの思想を具現化したVBAコードを示す。単なるコピペ用ではない。各セクションがなぜそのように書かれているか、設計意図を読み解いてほしい。

Option Explicit

' ==============================================================================
' Module: AccessibilityEngine
' Description: PowerPoint内の図形に対し、代替テキストの欠落を検出し、
'              インテリジェントに補完を行う品質管理エンジン。
' ==============================================================================

Private m_report As String ' 変更履歴を保持するログ

''' <summary>
''' メインエントリポイント。スライド全体の検査と保存を実行する。
''' </summary>
Public Sub RunAccessibilityAudit()
    Dim pres As Presentation
    Dim sld As Slide
    Dim startTime As Double
    
    Set pres = ActivePresentation
    m_report = "--- Accessibility Audit Report ---" & vbCrLf & _
               "Execution Time: " & Now & vbCrLf & vbCrLf
    
    startTime = Timer
    
    On Error GoTo ErrorHandler
    
    ' 1. 全スライドを走査
    For Each sld In pres.Slides
        Debug.Print "Processing Slide: " & sld.SlideIndex
        ProcessSlide sld
    Next sld
    
    ' 2. 結果の出力(イミディエイトウィンドウおよびログファイル保存)
    OutputReport
    
    MsgBox "監査完了。" & vbCrLf & _
           "処理時間: " & Round(Timer - startTime, 2) & "秒" & vbCrLf & _
           "詳細な変更内容はイミディエイトウィンドウを確認してください。", vbInformation
    Exit Sub

ErrorHandler:
    MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical
End Sub

''' <summary>
''' スライド内の図形を再帰的に処理する
''' </summary>
Private Sub ProcessSlide(ByVal targetSlide As Slide)
    Dim shp As Shape
    
    ' スライド直下の図形をループ
    For Each shp In targetSlide.Shapes
        RecursiveProcessShape shp
    Next shp
End Sub

''' <summary>
''' 図形を再帰的に走査し、代替テキストを検査・補完する。
''' グループ化されている場合は、その内部へ潜り込む。
''' </summary>
Private Sub RecursiveProcessShape(ByVal shp As Shape)
    Dim i As Integer
    
    ' --- 1. 再帰処理: グループ化されている場合 ---
    If shp.Type = msoGroup Then
        For i = 1 To shp.GroupItems.Count
            RecursiveProcessShape shp.GroupItems(i)
        Next i
        ' グループ自体はスキップ(中身を処理するため)
        Exit Sub
    End If
    
    ' --- 2. 検査ロジック: 代替テキストが空かどうか ---
    ' 注意: AlternativeText プロパティは、設定されていない場合に空文字を返す
    If Trim(shp.AlternativeText) = "" Then
        ApplyIntelligentAltText shp
    End If
End Sub

''' <summary>
''' 図形の属性に基づき、最適な代替テキストを推論して設定する。
''' </summary>
Private Sub ApplyIntelligentAltText(ByRef shp As Shape)
    Dim candidateText As String
    candidateText = ""
    
    ' 戦略A: テキストボックスや図形内にテキストがある場合、それを優先
    If shp.HasTextFrame Then
        If Len(Trim(shp.TextFrame.TextRange.Text)) > 0 Then
            candidateText = Trim(shp.TextFrame.TextRange.Text)
        End If
    End If
    
    ' 戦略B: テキストがない場合、図形の名前から推論(例: "Picture 5" -> "Picture 5")
    ' 実務的には、ここでより高度な変換ロジックを挟むことが可能
    If candidateText = "" Then
        candidateText = shp.Name
    End If
    
    ' 補完の実行
    If candidateText <> "" Then
        shp.AlternativeText = candidateText
        m_report = m_report & "[FIXED] Slide Index: " & shp.Parent.SlideIndex & _
                   " | Shape: " & shp.Name & " -> '" & candidateText & "'" & vbCrLf
    Else
        m_report = m_report & "[SKIPPED] Slide Index: " & shp.Parent.SlideIndex & _
                   " | Shape: " & shp.Name & " (No content found)" & vbCrLf
    End If
End Sub

''' <summary>
''' 監査ログをイミディエイトウィンドウに出力する。
''' </summary>
Private Sub OutputReport()
    Debug.Print m_report
End Sub

4. エンジニアリングの要諦:コードの解説

再帰によるオブジェクトグラフの完全走査

`RecursiveProcessShape` 関数において、`shp.Type = msoGroup` の判定を行い、`shp.GroupItems(i)` に対して自分自身を再度呼び出している。これにより、どれほど深い階層に図形が隠れていても、確実にキャッチできる。これは、複雑なレイアウトを扱うプレゼンテーションにおいて、漏れをゼロにするための必須テクニックだ。

インテリジェントな補完戦略(Heuristics)

`ApplyIntelligentAltText` では、単なる代入ではなく、優先順位に基づいた推論を行っている。
1. コンテンツ優先: 図形の中に既に書かれている文字(`TextFrame`)を、その図形の「意味」とみなす。
2. メタデータ優先: テキストがない場合は、オブジェクト名(`Name`)を代用する。

実務レベルでは、ここに「画像ファイル名から拡張子を除去して取得する」といったロジックや、特定の命名規則に基づいた変換処理を追加することで、より「人間らしい」代替テキストへと昇華させることができる。

監査可能性(Auditability)の確保

`m_report` 変数を用いて、どのスライドのどの図形を、どう書き換えたのかを逐一記録している。自動化ツールにおいて、「何が変わったかわからない」状態は、プロダクション環境では致命的なリスクとなる。このログこそが、ユーザー(資料作成者)に対する信頼の証となる。

5. 結論

PowerPoint VBAを用いた自動化において、重要なのは「動くコード」を書くことではない。「予測可能な挙動をする、堅牢なシステム」を設計することだ。

階層構造を意識した再帰処理、コンテキストを読み取る補完ロジック、そして変更の証跡を残すログ設計。これらを備えて初めて、あなたのスクリプトは「業務ツール」へと進化する。

アクセシビリティへの対応は、技術的な課題であると同時に、企業の社会的責任を果たすためのエンジニアリングである。この視点を忘れずに、コードを書き続けてほしい。

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