【テクニカル・上級編】【上級プロフェッショナル向け】図面オープン時のカスタムダイアログ表示と条件分岐処理 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:図面オープン前のカスタム制御と条件分岐のアーキテクチャ

AutoCAD VBAの世界において、多くの開発者は「図面が開いた後のイベント(`AcadDocument_Activate` や `Initialize` など)」の制御にとどまっている。しかし、真のエンタープライズ環境や大規模な設計オートメーションにおいては、「図面が開かれる前(Pre-Open)」の段階でいかにシステムが介入し、環境を制御するかが、システム全体の成否を分ける。

本稿では、図面オープン時のカスタムダイアログによるユーザー入力のキャプチャ、外部データベースやPLMとの同期、そしてAutoCADのシングルスレッド制約とメモリ管理の罠を回避しながら処理を分岐させる、極限のアーキテクチャを解説する。

—

1. AutoCADにおける「図面オープン前」のパラドックス

AutoCADのVBAランタイムは、図面ドキュメント(`AcadDocument`)のコンテキストに強く依存している。純粋なVBA単体では、図面が完全にロードされる前のモーダルな割り込み処理や、ファイルオープンダイアログ自体のフックには制限が多い。

ここでシニアエンジニアが取るべきアプローチは、「Applicationレベルのイベント監視」と「Windows APIによるメッセージフック(または先行UIの強制)」の組み合わせである。

特に、レガシーなAutoCAD環境(VBA 7.1ベース、32bit/64bit混在)において、メモリリークを起こさずに安全に外部ダイアログを表示し、その結果に応じて`Documents.Open`を制御する手法は、プラットフォームの挙動を熟知していなければ実装できない。

—

2. アーキテクチャ設計:事前ダイアログによる条件分岐の全体像

以下のフローで処理を構築する。

1. トリガー: ユーザーまたは外部マクロからのオープン要求。
2. 事前介入: AutoCADの標準ダイアログの代わりに、カスタムUserForm(またはWindows APIダイアログ)を最前面でモーダル表示。
3. 条件分岐: 入力されたプロジェクトコードやメタデータに基づき、以下のいずれかに分岐:

  • 正常オープン(特定レイヤの凍結設定を適用して開く)
  • バージョン互換チェック(古いDWGの場合、一時領域でマイグレーション実行)
  • 処理の中止(セキュリティポリシー違反やパラメータ不備)

4. メモリ最適化: COMオブジェクトの参照を確実に解放し、AutoCADの不安定化(Fatal Error)を防ぐ。

—

3. 実装コード:事前制御クラスと条件分岐エンジン

以下のコードは、標準の `ThisDrawing` や標準モジュールにベタ書きするレベルを超えた、クラスモジュールによるカプセル化とAPI連携のサンプルである。

A. エントリポイントおよび条件分岐制御モジュール (`ModPreOpenManager.bas`)

Option Explicit

‘ AutoCADの標準ファイルオープンをインターセプトし、事前条件を評価するメインエンジン
Public Sub ExecuteConditionalOpen()
On Error GoTo ErrorHandler

Dim targetPath As String
Dim userChoice As Boolean
Dim projectCode As String

‘ 1. カスタムダイアログの呼び出し(ユーザーからのメタデータ取得)
Load 10_UI_PreOpenDialog ‘ 独自のUserForm
10_UI_PreOpenDialog.Show vbModal

userChoice = 10_UI_PreOpenDialog.IsCanceled
projectCode = 10_UI_PreOpenDialog.SelectedProjectCode
targetPath = 10_UI_PreOpenDialog.TargetFilePath

‘ フォームのアンロードとメモリ解放
Unload 10_UI_PreOpenDialog

If userChoice Then
MsgBox “ユーザーによってオープン処理がキャンセルされました。”, vbInformation
Exit Sub
End If

‘ 2. 条件分岐処理(システム間連携・バージョン互換チェック)
If Not ValidateFileCompatibility(targetPath) Then
MsgBox “対象ファイルは現在のAutoCAD環境と互換性がないか、破損しています。”, vbCritical
Exit Sub
End If

‘ 3. メタデータに基づいた図面のオープンと環境設定
Call OpenAndConfigureDocument(targetPath, projectCode)

Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
‘ 異常終了時のクリーンアップ処理をここに記述
End Sub

Private Function ValidateFileCompatibility(ByVal filePath As String) As Boolean
‘ 簡易的なファイル存在確認およびバージョンバイナリヘッダの検証(スタブ)
If Dir(filePath) = “” Then
ValidateFileCompatibility = False
Exit Function
End If

‘ ここにDBやAPIとの連携による権限チェック等を挿入可能
ValidateFileCompatibility = True
End Function

Private Sub OpenAndConfigureDocument(ByVal filePath As String, ByVal projCode As String)
Dim doc As AcadDocument
Dim acadApp As AcadApplication

Set acadApp = ThisDrawing.Application

‘ 4. ドキュメントのオープン
‘ ReadOnlyで開くか、排他制御を行うかの分岐
Set doc = acadApp.Documents.Open(filePath, False)

‘ 5. 開いた直後のドキュメントに対するカスタム属性の注入
‘ データベース(Xrecord等)へのプロジェクトコード書き込み
Call InjectMetadataToDrawing(doc, projCode)

‘ オブジェクトの明示的解放(メモリ最適化の極意)
Set doc = Nothing
Set acadApp = Nothing
End Sub

Private Sub InjectMetadataToDrawing(ByRef targetDoc As AcadDocument, ByVal projCode As String)
On Error GoTo CleanUp

Dim dict As AcadDictionary
Set dict = targetDoc.Dictionaries.Item(“AEC_PROJECT_DATA”)
If dict Is Nothing Then
Set dict = targetDoc.Dictionaries.Add(“AEC_PROJECT_DATA”)
End If

‘ Xrecordを用いたカスタムデータの永続化
Dim xrec As AcadXrecord
Dim dataType(0) As Integer
Dim dataValue(0) As Variant

dataType(0) = 1: dataValue(0) = projCode

Set xrec = dict.AddXrecord(“ProjectInfo”)
xrc.SetXRecordData dataType, dataValue

CleanUp:
‘ COMオブジェクトの参照チェーンを完全に断ち切る
Set xrec = Nothing
Set dict = Nothing
End Sub

—

4. チーフアーキテクトが教える:メモリ最適化とレガシー保守の極意

オブジェクトのライフサイクル管理と「COMの罠」

AutoCAD VBAにおいて、`Set obj = Nothing` を怠ることは、確実にメモリリーク(特にDrawing Object Tableの肥大化)を引き起こす。
特に `Documents.Open` や `Dictionaries`、`SelectionSet` などのコレクションを操作する際は、ローカル変数として取得したCOMオブジェクトは、スコープを抜ける前に必ず `Nothing` を代入して参照カウントをデクリメントしなければならない。これを怠ると、AutoCADプロセスがバックグラウンドに残り続け、次回のオープン時にFatal Errorの温床となる。

64bit環境とWindows APIの整合性

レガシーなVBAコードを現代の64bit AutoCADで稼働させる場合、API宣言の `PtrSafe` および `LongPtr` への置き換えは必須である。もしカスタムダイアログの拡張として、Windows標準のファイル選択ダイアログをAPI経由で呼び出す場合は、以下のようなポインタ安全な実装を担保すること。

If VBA7 Then
Private Declare PtrSafe Function GetActiveWindow Lib “user32” () As LongPtr
Else
Private Declare Function GetActiveWindow Lib “user32” () As Long
End If

—

5. 結言

図面を開くという単純な動作一つをとっても、プロフェッショナルなエンジニアリングの世界では、セキュリティ、バージョン管理、メタデータの整合性、そしてメモリ管理という幾重ものレイヤーが存在する。

単に動くだけのコードではなく、「なぜその順番でオブジェクトを解放すべきか」「なぜ事前ダイアログが必要なのか」というシステム全体のライフサイクルを理解した上で実装されたアーキテクチャこそが、現場の生産性を極限まで高める唯一の解である。妥協なきコードベースで、真のAutoCAD自動化を極めてほしい。

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