【入門編】【上級プロフェッショナル向け】図面保存イベント「BeginSave」をフックした、禁止オブジェクトの自動検出と保存ブロック – AutoCAD VBA解析バイブル

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

【上級プロフェッショナル向け】図面保存の守護神を構築する:BeginSaveイベントによる検図コンプライアンスの実装

「あ、また禁止レイヤーが混じっている……」
「この図面、ブロック名が社内規定と違うから、後工程の自動処理でエラーが出ちゃったよ」

設計現場のリーダーや、BIM/CADマネージャーなら、一度はこうした「標準化の崩壊」に頭を抱えたことがあるはずです。

個々の設計者のスキルは高くても、図面データという「成果物」の品質を一定に保つのは至難の業です。マクロの記録で「ボタンを押せば動くツール」を作る段階を卒業し、「システムとして図面の品質を強制的に担保する」。これこそが、真のオートメーションエンジニアが目指すべき領域です。

今日は、AutoCAD VBAを使って、図面を保存しようとする瞬間に「検閲」を行い、ルール違反があれば保存をブロックする「検図コンプライアンス機能」の構築方法を伝授しましょう。

ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ。さあ、一歩上のエンジニアリングの世界へ踏み出しましょう。

1. 「イベント」という概念を理解する

これまでのあなたは、「ボタンを押したらこの処理をする」という「命令型」のプログラミングをしてきたかもしれません。しかし、プロフェッショナルな自動化において重要なのは、「イベント駆動型(Event-Driven)」の考え方です。

「イベント」とは、ユーザーの操作やシステムの動作によって発生する「出来事」のことです。

  • 図面を開いた(`NewDocument`)
  • 図面を保存しようとした(`BeginSave`)
  • オブジェクトが変更された(`Change`)

今回のミッションは、ユーザーが「保存(Save)」というイベントを発生させた瞬間に、その動きを横取り(フック)し、図面の中身をスキャンすることです。

2. コンプライアンス・ロジックの設計図

単に「保存を止める」だけでは、ユーザーは混乱します。私たちが作るべきは、「なぜ保存できなかったのか」を明確に伝え、修正を促すガードマンです。

今回のロジックは以下の3ステップで構成します。

1. スキャン(Scan): 図面内の全レイヤーと全ブロックを走査する。
2. 判定(Validate): 各オブジェクトの名前が「禁止リスト」に含まれていないか照合する。
3. 介入(Intercept): 違反が見つかったら、警告メッセージを表示し、保存処理を中断させる。

3. 実装:検図コンプライアンス・エンジン

それでは、実際のコードを見ていきましょう。このコードは、標準モジュールではなく、`ThisDrawing` モジュールに記述することを想定しています。

' =================================================================
' モジュール名: ThisDrawing (図面イベント用)
' 概要: 図面保存時にレイヤー名とブロック名をチェックし、
'       規定違反がある場合は保存を阻止する。
' =================================================================

Option Explicit

' --- 社内規定:禁止されている名前のリスト(例) ---
Private Const FORBIDDEN_LAYER_PREFIX As String = "TEMP_" ' TEMP_で始まるレイヤーは禁止
Private Const FORBIDDEN_BLOCK_NAME As String = "TestBlock" ' 特定のテスト用ブロックは禁止

''' <summary>
''' 図面の保存プロセスが開始される直前に呼び出されるイベント
''' ※VBA環境における実装の勘所を解説します
''' </summary>
Private Sub Document_BeforeSave(ByVal SaveSuccess As Boolean)
    ' SaveSuccess は、このプロシージャの終了時に True/False を返すことで
    ' AutoCAD 本体の保存処理を継続させるか決定できる仕組みです。
    
    Dim isCompliant As Boolean
    Dim errorMessage As String
    
    ' 初期状態は「適合(True)」
    isCompliant = True
    errorMessage = ""

    ' 1. 検閲プロセス開始
    ' -------------------------------------------------------------
    ' レイヤーのチェック
    If Not CheckLayers(errorMessage) Then
        isCompliant = False
    End If
    
    ' ブロックのチェック
    If Not CheckBlocks(errorMessage) Then
        isCompliant = False
    End If
    ' -------------------------------------------------------------

    ' 2. 判定結果に基づく介入
    ' -------------------------------------------------------------
    If Not isCompliant Then
        ' 違反が見つかった場合、ユーザーに警告を表示
        MsgBox "【コンプライアンス違反】" & vbCrLf & _
               "以下の項目を修正しない限り、図面を保存できません。" & vbCrLf & vbCrLf & _
               errorMessage, vbCritical, "保存ブロック"
        
        ' ここが重要!保存をキャンセルさせるために False を設定
        ' ※環境により、エラーを発生させて中断させる手法も併用します
        Err.Raise vbObjectError + 513, "ComplianceCheck", "規定違反のため保存を中止しました。"
    Else
        ' 問題なければ、そのまま保存を続行させる
        ' MsgBox "検閲完了:適合しています。", vbInformation
    End If
End Sub

''' <summary>
''' 全レイヤーを走査し、禁止された名前がないか確認する
''' </summary>
Private Function CheckLayers(ByRef msg As String) As Boolean
    Dim ent As AcadLayer
    Dim violationCount As Integer
    violationCount = 0
    
    ' 図面内の全レイヤーをループ
    For Each ent In ThisDrawing.Layers
        ' 接頭辞のチェック(例:TEMP_レイヤーの検出)
        If Left(ent.Name, Len(FORBIDDEN_LAYER_PREFIX)) = FORBIDDEN_LAYER_PREFIX Then
            msg = msg & "・禁止レイヤー: " & ent.Name & vbCrLf
            violationCount = violationCount + 1
        End If
    Next ent
    
    CheckLayers = (violationCount = 0)
End Function

''' <summary>
''' 全ブロックを走査し、規定外のブロックがないか確認する
''' </summary>
Private Function CheckBlocks(ByRef msg As String) As Boolean
    Dim blk As AcadBlock
    Dim violationCount As Integer
    violationCount = 0
    
    ' 図面内の全ブロック定義をループ
    For Each blk In ThisDrawing.Blocks
        ' 匿名ブロック(*U...)や外部参照(XREF)はチェック対象外にするのがプロの作法
        If Not (blk.IsAnonymous Or blk.IsXRef) Then
            ' 特定の禁止名と一致するかチェック
            If blk.Name = FORBIDDEN_BLOCK_NAME Then
                msg = msg & "・禁止ブロック: " & blk.Name & vbCrLf
                violationCount = violationCount + 1
            End If
        End If
    Next blk
    
    CheckBlocks = (violationCount = 0)
End Function

4. 伝説のアーキテクトが教える「ここが落とし穴」

コードをコピペして動かすだけでは、あなたはまだ「ユーザー」です。「エンジニア」になるために、以下の3つのポイントを魂に刻んでください。

① 「匿名ブロック」と「XREF」のハンドリング

初心者がやりがちな最大のミスは、`ThisDrawing.Blocks` をすべて無条件にループすることです。
AutoCADの内部には、システムが自動生成する「匿名ブロック(`*U…`)」や、外部参照(`XREF`)が含まれています。これらに対して厳格すぎるルールを適用すると、「何もしていないのに保存できない!」という、ユーザーからの怒号を浴びることになります。
`If Not (blk.IsAnonymous Or blk.IsXRef)` という一行は、現場のストレスを回避するための「知恵」です。

② エラーハンドリングの重要性

コンプライアンスチェック自体がエラーで止まってしまったら、本末転倒です。
例えば、レイヤーを削除しようとしている最中にチェックが走ると、オブジェクトが消失して実行時エラーになることがあります。プロは `On Error Resume Next` を乱用せず、オブジェクトの存在を確認してから処理を進める、あるいは堅牢なエラーハンドリングを組み込みます。

③ パフォーマンスの重み

図面が数万個のオブジェクトを持つ大規模なものになったとき、保存のたびに全スキャンを行うと、ユーザーは「保存が遅すぎる!」と感じます。
実務では、「変更があったときだけフラグを立てる」、あるいは「スキャン対象を主要なコレクションに絞る」といった、計算量の最適化(アルゴリズムの選択)が求められます。

5. まとめ:自動化の先にあるもの

今回のコードは、単なる「禁止事項のチェック」ではありません。
それは、「設計プロセスの品質を、ソフトウェアの力で強制的に引き上げる」という、マネジメントの自動化です。

マクロの記録から脱却し、オブジェクトのライフサイクル、イベントの発生、そしてユーザーの体験(UX)を意識したコードが書けるようになれば、あなたの価値は劇的に高まります。

「ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ」

次は、もっと複雑な、図面の構造そのものを解析・修正する高度な自動化に挑戦してみましょう。応援していますよ。

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