【上級プロフェッショナル向け】AutoCAD VBAで「社外秘」を漏洩させない:BeginSaveイベントによる自動スクリーニングの極意
設計現場において、図面は単なる幾何学データの集合体ではない。それは企業の知的財産(IP)そのものだ。しかし、皮肉なことに、CADという自由度の高いツールは「消し忘れの機密情報」を内包したまま外部へ流出させるリスクを常に孕んでいる。
「非表示レイヤーに隠したはずのコスト情報が残っていた」
「図面枠外のワークスペースに社外秘のメモを放置していた」
こうしたヒューマンエラーを「個人の注意」に委ねているうちは、プロフェッショナルな組織とは言えない。今回は、AutoCAD VBAのイベントハンドリングを極限まで活用し、保存(Save)という最終防衛ラインで機密情報を自動検知・遮断する「スクリーニング・エンジン」の構築手法を伝授する。
—
1. なぜ「標準機能」では不十分なのか
多くの開発者が陥る罠は、`ThisDrawing` モジュールに場当たり的なコードを書くことだ。しかし、真に堅牢なシステムを構築するには、アプリケーションレベルのイベント・ライフサイクルを掌握しなければならない。
設計の急所:イベントの二重性
AutoCADにおける保存イベントには `BeginSave` と `EndSave` がある。スクリーニングにおいて重要なのは当然 `BeginSave` だ。ここで図面をスキャンし、問題があれば「保存処理そのものをキャンセルさせる」必要がある。
しかし、VBAの `BeginSave` イベント自体には `Cancel` 引数が存在しない。ここが設計者の腕の見せ所だ。VBAから保存を中断させるには、`VBA.SendKeys “{ESC}”` という泥臭い手法ではなく、「保存フラグの制御」と「ユーザーへの強制的フィードバック」を組み合わせたロジックを構築する必要がある。
—
2. アーキテクチャ:クラスモジュールによる常駐監視
「特定の図面」だけでなく、AutoCADを開いている間、すべての図面を監視対象にする。そのためには、アプリケーションレベルのイベントリスナーをクラスモジュールで実装するのが定石だ。
クラスモジュール:`clsAppEvents`
まずは、AutoCADアプリケーションそのものを捕捉するクラスを定義する。
‘ クラス名: clsAppEvents
Option Explicit
Public WithEvents App As AcadApplication
‘ 保存開始時のイベント
Private Sub App_BeginSave(ByVal FileName As String)
Dim isSafe As Boolean
‘ 1. スクリーニング実行
isSafe = PerformSecurityScan(ThisDrawing)
‘ 2. リスク検知時の処理
If Not isSafe Then
‘ 注意: VBAのBeginSaveは標準でCancelできないため、
‘ 致命的な場合はユーザーに警告し、手動で修正を促すか、
‘ 業務ルールとして「保存失敗」の状態を意図的に作り出す設計が必要。
MsgBox “【セキュリティ警告】” & vbCrLf & _
“この図面には社外秘情報(特定のキーワードまたは非表示レイヤー)が含まれています。” & vbCrLf & _
“保存を中断し、内容を確認してください。”, vbCritical, “保存ブロック”
‘ 物理的に保存を止めるための究極の策(SendCommandによるエスケープ)
‘ ※環境により挙動が異なるため、運用ポリシーに合わせて調整すること
‘ ThisDrawing.SendCommand Chr(27)
End If
End Sub
‘ スクリーニングのコアロジック
Private Function PerformSecurityScan(ByRef doc As AcadDocument) As Boolean
On Error GoTo ErrHandler
Dim i As Integer
Dim objEntity As AcadEntity
Dim objLayer As AcadLayer
Dim keywords As Variant
Dim k As Variant
‘ スクリーニング対象のキーワード(本来は外部設定ファイルから読み込むべき)
keywords = Array(“機密”, “社外秘”, “Confidential”, “COST”, “見積”)
‘ — フェーズ1: 非表示・フリーズレイヤーのチェック —
‘ 隠れた場所に情報が残留しているケースが最も危険
For Each objLayer In doc.Layers
If objLayer.LayerOn = False Or objLayer.Freeze = True Then
‘ 非表示レイヤーが存在すること自体を警告するか、
‘ その中のテキストを全走査するかはポリシー次第
End If
Next
‘ — フェーズ2: 全エンティティのテキストスキャン —
‘ モデル空間・ペーパー空間のすべてのテキスト情報を精査する
‘ パフォーマンス向上のため、本来はSelectionSetsを使用すべきだが、
‘ 「漏れ」を許さないためにはイテレータによる全走査が最も確実
Dim layout As AcadLayout
For Each layout In doc.Layouts
Dim bBlock As AcadBlock
Set bBlock = layout.Block
For Each objEntity In bBlock
‘ MText (マルチテキスト) または Text (一行文字) を対象
If TypeOf objEntity Is AcadMText Or TypeOf objEntity Is AcadText Then
Dim textContent As String
textContent = IIf(TypeOf objEntity Is AcadMText, objEntity.TextString, objEntity.TextString)
‘ キーワード照合
For Each k In keywords
If InStr(1, textContent, k, vbTextCompare) > 0 Then
‘ ヒットした時点でFalseを返す(早期リターン)
Debug.Print “検知されたキーワード: ” & k & ” (Object ID: ” & objEntity.ObjectID & “)”
PerformSecurityScan = False
Exit Function
End If
Next k
End If
Next objEntity
Next layout
‘ すべてのチェックを通過
PerformSecurityScan = True
Exit Function
ErrHandler:
‘ エラー時は安全側に倒して「保存不可」とする
PerformSecurityScan = False
Debug.Print “Error in PerformSecurityScan: ” & Err.Description
End Function
—
3. 実装のキモ:なぜこの設計なのか
① 外部データベース(CSV/JSON)との連携
上記のコードではキーワードを配列で持たせているが、実務では「機密キーワードリスト」をサーバー上のCSVやデータベースで一括管理すべきだ。
保存のたびにファイルを読み込むとパフォーマンスが低下するため、`clsAppEvents` の初期化時(`Class_Initialize`)に一度だけDictionaryオブジェクトへ読み込む設計にせよ。
② 非表示情報の「不可視属性」への対応
AutoCADには、図面データに隠された「XData(拡張データ)」や「XRecord」が存在する。
上級者であれば、エンティティのテキストだけでなく、DictionaryコレクションやXDataに埋め込まれたシステム固有の情報もスキャン対象に含めるべきだ。悪意あるスクリプトや、古いプラグインが残した機密メタデータがそこに潜んでいる可能性があるからだ。
③ パフォーマンスとUXのトレードオフ
数万個のオブジェクトが存在する図面で、保存のたびに全走査を行うのはユーザー体験を著しく損なう。
- 差分スキャン: 前回の保存から変更されたオブジェクトのみを対象にする(要 `Modified` イベント連携)。
- バックグラウンド処理: スキャンを別スレッド(VB.NETアドイン経由)で行う。
VBA単体で行う場合は、スキャン対象を「特定のレイヤー」や「特定のプロパティ」に絞り込むSelectionSetsのフィルタリング機能を活用し、計算量を $O(n)$ から最小限に抑える工夫が求められる。
—
4. プロダクション導入へのロードマップ
このツールを現場に投入するなら、以下の初期化コードを `AcadVBA.arx` ロード時に実行される標準モジュールに記述する。
‘ 標準モジュール
Public g_AppEvents As New clsAppEvents
Public Sub InitializeSecurityEngine()
‘ AutoCADアプリケーションオブジェクトをクラスにバインド
Set g_AppEvents.App = ThisDrawing.Application
MsgBox “セキュリティ・スクリーニング・エンジン稼働中”, vbInformation
End Sub
運用上の注意点
1. 誤検知(False Positive)への対応: 「見積」という言葉が図面枠に含まれる場合など、例外処理を認める「ホワイトリスト」のロジックを必ず実装すること。
2. バイパスの禁止: ユーザーがVBAを無効にして保存することを防ぐため、社内標準のテンプレート自体にこのVBAを埋め込むか、レジストリでアドインのロードを強制する運用が必要だ。
—
結論:エンジニアの誇りをコードに込める
「保存ボタン」は、設計者の思考が「成果物」へと変わる神聖な儀式である。そこに自動化されたセキュリティ・ゲートを設けることは、単なる制約ではなく、組織全体の信頼を守るためのインフラである。
今回紹介した `BeginSave` フックによるスクリーニングは、AutoCAD VBAが提供する強力な制御権限の氷山の一角に過ぎない。このコードをベースに、自社の業務要件に合わせた最強の検閲エンジンを構築してほしい。
「守るべきものを、技術で守る。」 これこそが、我々チーフアーキテクトに課せられた使命である。
