【入門編】【中級者】特定の「秘密区分(極秘、社内限定、一般公開)」に応じて、PDF保存時のセキュリティ設定(印刷禁止、コピー禁止など)を動的に切り替えるマクロ – PowerPoint VBA解析バイブル

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

脱・マクロの記録。機密情報を守る「意思決定」をコードに組み込む方法

「マクロの記録」ボタンを押し、自分の操作をコードに変換する。そこから一歩踏み出し、「自分でロジックを書く」段階へ進もうとしているあなたへ。

こんにちは。今日は、単なる自動化を超えた「コンプライアンス(法令遵守)を自動化する」という、実務において極めて重要、かつエンジニアとしての腕の見せ所となるテーマについてお話ししましょう。

テーマは、「スライドの機密区分を自動判定し、それに応じたセキュリティ設定でPDF出力する」仕組みの構築です。

「スライドによって、社内限定のものもあれば、社外に出していいものもある。毎回手動でPDFの書き出し設定を変えるのは面倒だし、設定ミスで極秘資料を一般公開設定で送ってしまう……そんなヒューマンエラーを防ぎたい」

そんな現場の切実な願いを、VBAという武器で解決していきましょう。

1. アーキテクチャの設計図:どうやって「秘密」を判別するか?

まず、設計思想を固めます。エンジニアが最初に考えるべきは「どこに情報を隠し、どう読み取るか」です。

スライドの上に「極秘」というテキストボックスを置く方法もありますが、これはプロの仕事ではありません。なぜなら、プレゼン本番でそのテキストボックスを消し忘れたら、情報の機密性が台無しになるからです。

そこで、私たちは「スライドのタグ(Tags)」という、ユーザーの目には見えない「メタデータ」を利用します。

今回のロジックの流れ

1. スライドの走査: 全スライドをループで確認する。
2. タグの判定: 各スライドの `Tags` コレクションに格納された「SecurityLevel」という値を読み取る。
3. 最高機密の特定: プレゼン全体の中で「最も高い機密レベル」を決定する(一箇所でも「極秘」があれば、ファイル全体を「極秘」として扱う)。
4. 条件付きエクスポート: 判定されたレベルに基づき、保存パスや(将来的な拡張を見据えた)セキュリティ処理を行う。

2. 実装コード:意思決定エンジンを構築する

それでは、魂を込めたコードを見ていきましょう。このコードは、単に動くだけでなく、後からメンテナンスしやすいように「列挙型(Enum)」を用いて設計しています。

Option Explicit

' --- 1. 機密レベルを定義(列挙型) ---
' これにより、数字ではなく「名前」でロジックを扱えるようになります。
' コードの可読性が劇的に向上し、ミスが減ります。
Enum SecurityLevel
    PublicAccess = 0    ' 一般公開
    InternalOnly = 1    ' 社内限定
    TopSecret = 2       ' 極秘
End Enum

''' <summary>
''' プレゼンテーション全体の最高機密レベルを判定し、
''' そのレベルに応じたPDFエクスポートを実行するメインルーチン
''' </summary>
Sub SecurePDFExportManager()
    Dim pres As Presentation
    Dim sld As Slide
    Dim maxLevel As SecurityLevel
    Dim currentLevel As SecurityLevel
    Dim savePath As String
    Dim fileName As String
    
    Set pres = ActivePresentation
    maxLevel = PublicAccess ' 初期値は最も低いレベル
    
    ' エラーハンドリング:予期せぬエラーで止まらないようにする
    On Error GoTo ErrorHandler

    ' --- 2. 全スライドをスキャンして最高機密レベルを特定 ---
    For Each sld In pres.Slides
        ' スライドのタグから「SecurityLevel」を取得
        ' タグが存在しない場合は、デフォルトの0(Public)として扱う
        currentLevel = GetLevelFromTag(sld)
        
        ' 現在の最高レベルより高いレベルが見つかったら更新
        If currentLevel > maxLevel Then
            maxLevel = currentLevel
        End If
    Next sld

    ' --- 3. 保存パスの構築 ---
    ' ファイル名に機密区分を付与することで、ファイル名だけで中身がわかるようにする
    fileName = pres.Name & "_" & GetLevelName(maxLevel) & ".pdf"
    savePath = pres.Path & "\" & fileName

    ' --- 4. 機密レベルに応じたエクスポート処理 ---
    ' 注: PowerPoint標準のExportAsFixedFormatには、直接的なパスワード設定機能がありません。
    ' 本来はここでAcrobat SDKや外部APIを叩きますが、
    ' 今回は「判定ロジックに基づいた保存パスの切り分け」という基本構造を示します。
    
    Select Case maxLevel
        Case TopSecret
            ' 極秘:特定の保護フォルダへ保存する、あるいは警告を出す等の処理
            MsgBox "【警告】極秘資料として処理します。専用の保護領域へ保存します。", vbCritical
            savePath = pres.Path & "\CONFIDENTIAL\" & fileName
            
            ' ※実際の実務では、ここで外部の暗号化ツールをVBAから呼び出すのが定石です。
            
        Case InternalOnly
            MsgBox "社内限定資料として保存します。", vbInformation
            
        Case PublicAccess
            MsgBox "一般公開資料として保存します。", vbInformation
    End Select

    ' PDFとしてエクスポート実行
    pres.ExportAsFixedFormat _
        Path:=savePath, _
        FixedFormatType:=ppFixedFormatTypePDF, _
        Intent:=ppFixedFormatIntentPrint

    MsgBox "エクスポートが完了しました!" & vbCrLf & "保存先: " & savePath, vbInformation
    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました。パスの存在や権限を確認してください。" & vbCrLf & _
           "Error No: " & Err.Number & vbCrLf & _
           "Description: " & Err.Description, vbCritical
End Sub

''' <summary>
''' スライドのタグからセキュリティレベルを読み取る補助関数
''' </summary>
Private Function GetLevelFromTag(targetSlide As Slide) As SecurityLevel
    Dim tagValue As String
    
    ' Tagsコレクションから値を取得(存在しない場合はエラーになるため、存在確認が必要)
    ' ここでは簡略化のため、エラーを無視して値を取得する設計にします
    On Error Resume Next
    tagValue = targetSlide.Tags("SecurityLevel")
    On Error GoTo 0
    
    Select Case tagValue
        Case "TopSecret":    GetLevelFromTag = TopSecret
        Case "InternalOnly": GetLevelFromTag = InternalOnly
        Case Else:           GetLevelFromTag = PublicAccess
    End Select
End Function

''' <summary>
''' レベルを文字列に変換する補助関数(ファイル名用)
''' </summary>
Private Function GetLevelName(level As SecurityLevel) As String
    Select Case level
        Case TopSecret:    GetLevelName = "CONFIDENTIAL"
        Case InternalOnly: GetLevelName = "INTERNAL"
        Case Else:         GetLevelName = "PUBLIC"
    End Select
End Function

3. 【極限の知見】プロが教える「ここが分かれ道」

コードを書くだけなら、ChatGPTでもできます。しかし、実務で「動く」ものを作るには、以下の3つの視点が不可欠です。

① なぜ `Tags` を使うのか?(オブジェクトのライフサイクル)

多くの初学者は、スライドの「ノート部分」や「特定の図形」に機密情報を書こうとします。しかし、それは「データ」と「表示」を混同している状態です。
`Slide.Tags` は、スライドオブジェクトに紐付いたメモリ上の小さな辞書のようなものです。ユーザーがスライドを編集しても、図形を削除しても、タグは消えません。「データの永続性と隠蔽性」を確保するために、タグを使うのです。

② `Enum`(列挙型)の重み

コードの中に `If level = 2 Then` と書いてはいけません。これは「マジックナンバー」と呼ばれる悪習です。半年後のあなたは、`2` が何を意味するか忘れています。
`If level = TopSecret Then` と書く。この一瞬の労力が、将来のバグをゼロにします。

③ PDFセキュリティの「現実」を知る

ここが最も重要なアドバイスです。実は、PowerPoint VBAの `ExportAsFixedFormat` メソッドには、「PDFにパスワードをかける」という引数は存在しません。
「えっ、できないの?」と思ったかもしれません。その通りです。

しかし、プロのエンジニアはここで諦めません。

  • パターンA: Adobe Acrobat Proがインストールされている環境なら、Acrobatのオブジェクトライブラリを操作してPDFに制限をかける。
  • パターンB: PDF化した後、コマンドラインツール(QPDFなど)を `Shell` 関数で呼び出して暗号化する。

今回のコードは、その「判断(Decision)」の部分を完璧に自動化したものです。判断さえ自動化できていれば、その後の「実行(Action)」の部分をどのツールに繋ぐかは、技術的な選択の問題に過ぎません。

4. まとめ:次のステップへ

今回のマクロを動かすには、まずスライドにタグを付ける必要があります。
手動で行うのは大変ですので、まずは「選択しているスライドに『TopSecret』というタグを付ける」という練習用マクロを書いてみると良いでしょう。

Sub SetTestTag()
    ' 選択中のスライドにテスト用のタグを付ける練習用
    On Error Resume Next
    ActiveWindow.Selection.SlideRange.Tags.Add "SecurityLevel", "TopSecret"
    MsgBox "タグを付与しました"
End Sub

ここをクリアすれば、PowerPoint VBAの基本はバッチリですよ。
単なる「操作の自動化」から、組織を守る「システムの構築」へ。あなたのコードに、魂を込めてください。応援しています!

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