【入門編】【上級】AcadApplicationのEvents(AppEvents)をクラスモジュールで捕捉:図面が閉じられる直前に「未入力の属性」を強制チェックするバリデーター – AutoCAD VBA解析バイブル

スポンサーリンク

こんにちは!CAD開発の現場を渡り歩いてきたシニアアーキテクトの私です。

これまでマクロの記録ボタンを押して「動いた!」と喜んでいたあなた。あるいは、図面ごとのバラバラな手作業に頭を抱えていたあなた。おめでとうございます。今日、そのステージを完全に卒業する時が来ました。

AutoCAD VBAの真の強さは、画面上のボタンをポチポチ押すことではありません。「AutoCADという巨大なアプリケーションの鼓動(イベント)をコードで直接つかまえ、裏側で完全にコントロールすること」にあります。

今回は、数あるAutoCAD VBAの機能の中でも、特にアーキテクト好みの「アプリケーションレベルのイベント監視」を扱います。図面が閉じられるその瞬間をトラップし、社内規定の属性が未入力なら容赦なく保存を阻止する――そんな実戦的な「属性バリデーター」を一緒に作り上げていきましょう。

ここをクリアすれば、あなたのVBAスキルは「初学者」の領域を完全に抜け出し、プロのオートメーション・エンジニアの仲間入りです。さあ、深呼吸して、私の後に続いてください。

なぜ「図面を閉じる瞬間」を監視する必要があるのか?

現場でこんなミス、起きたことありませんか?

  • 「図面番号」や「設計者名」といった重要な属性(ブロック属性)が空欄のまま、平気で図面が保存・提出されてしまった。
  • 納品間際になって未入力箇所が見つかり、全図面をしらみつぶしにチェックして回る羽目になった。

人間は忘れる生き物です。だからこそ、「システムに怒ってもらう仕組み」を裏側に常駐させる必要があります。

ここで登場するのが、`AcadApplication` のイベントです。図面ごとのイベント(`AcadDocument`)ではなく、AutoCAD全体を見守る「アプリケーションの目」を使うことで、どんな図面が開かれようとも、閉じようとする瞬間を確実に捕らえて検問を行うことができるのです。

基礎知識:なぜクラスモジュールが必要なのか?

「イベント」と聞いて、標準モジュールに `Sub App_BeginClose()` と書いたそこのあなた。残念ながら、それは動きません。

AutoCADのアプリケーションイベントを受け取るためには、「クラスモジュール」という特殊な型枠を作る必要があります。

  • 標準モジュール: 手続き(プロシージャ)をただ置いておく場所。イベントは直接受け取れません。
  • クラスモジュール: 「イベントを受け取るセンサー」を備えた、自分だけのカスタムオブジェクトを定義する設計図。

オブジェクトのライフサイクルを意識してください。私たちは「AutoCADのアプリケーションそのもの(`AcadApplication`)」のイベントを監視したいので、クラスの中で `Public WithEvents` という魔法のキーワードを使い、「私、このアプリの動きを監視します!」と宣言するのです。

実装ステップ:最強の属性バリデーターを作る

それでは、実際にVBAの開発環境(VBE)を開いて、コードを組み立てていきましょう。今回は以下の2つのパーツを作ります。

1. イベントを監視するクラスモジュール(名前:`CAppEvents`)
2. 監視をスタートさせる標準モジュール(名前:`mStartup`)

ステップ1:監視センサーとなるクラスモジュールの作成

VBEを開き、「挿入」>「クラス モジュール」を選択します。プロパティウィンドウで名前を `CAppEvents` に変更してください。

ここに以下のコードを書き込みます。

‘ =================================================================
‘ クラスモジュール名: CAppEvents
‘ 役割: AutoCADのアプリケーションイベントを捕捉し、図面終了時の属性を検査する
‘ =================================================================

‘ WithEventsキーワードを使い、AutoCADアプリケーションのイベントをフックします
Public WithEvents AppEvents As AcadApplication

‘ 図面が閉じられる直前に発生するイベント
Private Sub AppEvents_BeginClose(Cancel As Boolean)
Dim doc As AcadDocument
Set doc = ThisDrawing.Application.ActiveDocument

‘ デバッグ用メッセージ
Debug.Print “【監視中】図面のクローズ要求を検出しました: ” & doc.Name

‘ 属性の未入力チェックを実行
If Not CheckRequiredAttributes(doc) Then
‘ 条件を満たさない場合、閉じる処理をキャンセル(中断)する!
Cancel = True
MsgBox “【エラー・保存中止】” & vbCrLf & _
“必須属性(図面番号または設計者名)が未入力です!” & vbCrLf & _
“修正してから再度閉じてください。”, _
vbCritical, “AutoCAD 属性バリデーター”
End If
End Sub

‘ —————————————————————-
‘ 内部関数: 図面内の特定ブロックから属性を走査し、未入力がないかチェックする
‘ —————————————————————-
Private Function CheckRequiredAttributes(TargetDoc As AcadDocument) As Boolean
Dim ent As AcadEntity
Dim blkRef As AcadBlockReference
Dim attribs As Variant
Dim i As Long
Dim hasError As Boolean

hasError = False

‘ 図面内の全エンティティを走査
For Each ent In TargetDoc.ModelSpace
‘ オブジェクトが「ブロック参照」であるか判定
If TypeOf ent Is AcadBlockReference Then
Set blkRef = ent

‘ 例として、ブロック名が “TICKET_TITLE”(表題欄)のものを対象とする
If UCase(blkRef.Name) = “TICKET_TITLE” Then
‘ ブロック内の属性を取得
attribs = blkRef.GetAttributes

For i = LBound(attribs) To UBound(attribs)
‘ 属性タグ名に応じたチェック
Select Case UCase(attribs(i).TagString)
Case “DRAWING_NO”, “AUTHOR”
‘ 値が空っぽ、あるいはスペースだけの状態を弾く
If Trim(attribs(i).TextString) = “” Or _
Trim(attribs(i).TextString) = “-” Then
hasError = True
Exit For
End If
End Select
Next i
End If
End If
If hasError Then Exit For
Next ent

‘ エラーがなければTrue(合格)、あればFalse(不合格)を返す
CheckRequiredAttributes = Not hasError
End Function

ステップ2:監視システムを起動する標準モジュール

クラスを作っただけでは、まだAutoCADは何も監視していません。「監視の目をONにするスイッチ」を標準モジュールに書きます。

「挿入」>「標準モジュール」を選択し、以下のコードを記述してください。

‘ =================================================================
‘ 標準モジュール名: mStartup
‘ 役割: アプリケーションイベントの監視インスタンスを生成・保持する
‘ =================================================================

‘ クラスのインスタンスを保持するためのグローバル変数
‘ ※プロシージャ内でローカル変数にしてしまうと、即座にメモリから消滅してイベントが消えます(超重要!)
Public Monitor As CAppEvents

‘ AutoCAD起動時、または手動で実行して監視を有効化するマクロ
Public Sub StartAutoCADMonitor()
If Monitor Is Nothing Then
Set Monitor = New CAppEvents
‘ AutoCADアプリケーション本体をイベントソースとして結びつける
Set Monitor.AppEvents = ThisDrawing.Application

MsgBox “AutoCAD 属性バリデーターの常駐監視を開始しました。”, vbInformation, “システム起動”
Else
MsgBox “監視システムはすでに稼働中です。”, vbExclamation, “確認”
End If
End Sub

‘ 監視を停止したい場合のマクロ
Public Sub StopAutoCADMonitor()
Set Monitor = Nothing
MsgBox “監視を停止しました。”, vbInformation, “システム停止”
End Sub

ここで絶対にハマる!陥りやすい罠とエンジニアの知見

このコードを組むとき、多くの初学者が次のような壁にぶつかります。

> 「あれ?コードは完璧なはずなのに、図面を閉じても何もイベントが発動しないぞ…?」

原因は、先ほどコードのコメントにも書いた「オブジェクトのライフサイクル(スコープ)」にあります。

もし `StartAutoCADMonitor` サブルーチンの「中」で `Dim Monitor As New CAppEvents` と書いてしまったらどうなるでしょうか?
そのマクロが終了した瞬間、ローカル変数である `Monitor` はメモリから綺麗さっぱり消去(解放)されます。当然、イベントのセンサーも消えてしまうため、AutoCADを閉じても何も起きないのです。

【解決策】
変数を標準モジュールの最上部(Option Explicitの下)で `Public Monitor As CAppEvents` と宣言し、AutoCADが起動している間ずっとメモリ上に「生存」させ続けること。これが、イベントプログラミングにおける鉄則中の鉄則です。

実際の挙動と現場での活用イメージ

1. AutoCADを起動したら、一度だけ `StartAutoCADMonitor` を実行します(※実務では `acad.dvb` の自動ロード機能や `AcadStartup` イベントを併用して完全自動化します)。
2. 設計者が図面を開き、表題欄(`TICKET_TITLE`)の「図面番号」や「設計者名」を空欄のまま、図面を閉じようと「×」ボタンを押します。
3. その瞬間、`AppEvents_BeginClose` が割り込み、裏側で `CheckRequiredAttributes` が発動。
4. 未入力を検知した瞬間、`Cancel = True` が走って「図面を閉じるという運命が強制キャンセル」され、警告ダイアログが画面に立ちふさがります!

これで、不完全な図面がうっかりサーバーに保存される悲劇を、根元から断つことができるわけです。

おわりに:エンジニアとしての第一歩

お疲れ様でした!今回は、単なるマクロの自動化を超えた、「アプリケーションのライフサイクルに介入する高度なイベント監視」を体験していただきました。

ここをクリアできたあなたなら、図面が開かれた時(`BeginOpen`)、新しく図面が作られた時(`NewDocument`)、あるいは画層が変更された時など、あらゆるタイミングを自分のコードで支配できるようになります。

現場の品質を守り、手戻りの絶望からエンジニアたちを救い出す――そんな頼もしい自動化ツールを、ぜひあなたの手でさらに拡張していってください。

ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ。次のステップでも、最高にエキサイティングな知見をお届けします。お楽しみに!

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