AutoCAD VBAを掌握する極限の知見
第1回:`ListArx` と `LoadArx` による ObjectARXアドインの動的ロードと依存関係管理
開発プロジェクトのリーダーである私たちが直面する最大のフラストレーションの一つは、「現場のオペレーターが、カスタムツールの前提となるObjectARX(.arx)や関連アドインをロードし忘れて図面を開き、マクロエラーを踏み抜く」という不毛な事故だ。
「マクロを実行する前に、必ず手動でAPPLOADコマンドからARXを読み込んでください」——そんな運用ルールは設計の敗北を意味する。プロフェッショナルな自動化エンジニアであれば、VBAのエントリーポイント(`Workbook_Open` やコマンドの起点)で環境を完全同期させ、必要なアドインが未ロードであればプログラム側で自動的に検知・ロードする「自己完結型ランチャー」を構築すべきだ。
今回は、AutoCADの根幹である `AcadApplication` オブジェクトのメソッド、`ListArx` と `LoadArx` を駆使し、依存関係を完璧に制御するプロダクションコードの全貌を伝授する。
—
1. なぜ「静的ロード」ではなく「動的ロード」が必要なのか?
AutoCADの起動時にARXを読み込ませる方法(`acad.rx`への記述やスタートアップスイート)は一見手軽だが、大規模なエンタープライズ環境では以下の致命的な課題を抱えている。
1. 環境の不統一: クライアントPCごとにCADのインストールパスやプロファイルが異なり、設定が頻繁に破綻する。
2. バージョン間の競合: AutoCADのバージョン(2021〜2025など)によってARXのバイナリが異なる場合、静的な自動ロードは誤作動を起こす。
3. 不要なリソース消費: すべての図面で使わない重量級のARXを常時ロードしておくことは、メモリ効率の観点から愚行である。
したがって、「必要なときに、必要なモジュールを、メモリ上に安全にロードする(オンデマンド・ロード)」というアプローチが、堅牢なCADインフラストラクチャの絶対条件となる。
—
2. アーキテクチャの核心:`ListArx` との対話
アドインをロードする前に、必ず行わなければならない作業がある。それは「すでにロードされているかどうかの厳密なチェック」だ。無闇に `LoadArx` を叩けば、AutoCADはエラーを吐くか、最悪の場合メモリリークや不安定化を招く。
ここで登場するのが `AcadApplication.ListArx` メソッドである。
`ListArx` の仕様の罠
`ListArx` は、現在ロードされているすべてのObjectARXアプリケーションのリストを配列(Array of String)として返す。しかし、ここには開発者が知っておくべき極限の知見がある。
- 返される文字列には、モジュールのファイル名だけでなく、フルパスが含まれる場合がある。
- 大文字・小文字の揺れ(例: `MyCustomTool.arx` vs `MYCUSTOMTOOL.ARX`)が存在する。
そのため、単純な文字列比較ではなく、ファイル名(拡張子含む)を抽出し、大文字小文字を区別しない(Case-Insensitive)比較を行うアルゴリズムが必須となる。
—
3. 【プロダクションコード】堅牢なARXマネージャー実装
以下のコードは、実務の現場でそのまま組み込める、エラーハンドリングを極めたクラスモジュール、あるいは標準モジュールの実装例だ。コピペして即座にプロジェクトに組み込んでほしい。
Option Explicit
‘ ==============================================================================
‘ モジュール名: mArxLoader
‘ 概要: ObjectARXアドインのロード状態を監視し、動的に依存関係を解決するマネージャー
‘ ==============================================================================
‘ 定数定義: 自社開発の重要ARXモジュール名とファイルパス(環境に合わせて変更してください)
Private Const TARGET_ARX_NAME As String = “StructuralOptimizer.arx”
Private Const TARGET_ARX_PATH As String = “C:\CompanyCAD\Plugins\StructuralOptimizer.arx”
Public Sub EnsureArxLoaded()
On Error GoTo ErrorHandler
Dim acadApp As AcadApplication
Set acadApp = ThisDrawing.Application
acadApp.Utility.Prompt vbCrLf & “[ARX Manager] 依存関係の検証を開始します…” & vbCrLf
‘ 1. ターゲットが既にロードされているかチェック
If IsArxLoaded(acadApp, TARGET_ARX_NAME) Then
acadApp.Utility.Prompt “[ARX Manager] ターゲット ARX は既にロードされています: ” & TARGET_ARX_NAME & vbCrLf
Exit Sub
End If
‘ 2. 未ロードの場合、ファイルの存在確認を行ってから動的ロードを実行
If Not FileExists(TARGET_ARX_PATH) Then
Err.Raise vbObjectError + 1000, “EnsureArxLoaded”, “必須ARXファイルが見つかりません。パスを確認してください: ” & TARGET_ARX_PATH
End If
acadApp.Utility.Prompt “[ARX Manager] ARXが見つかりません。動的ロードを実行します: ” & TARGET_ARX_PATH & vbCrLf
‘ LoadArxの実行
acadApp.LoadArx TARGET_ARX_PATH
‘ 3. ロード成功の事後検証
If IsArxLoaded(acadApp, TARGET_ARX_NAME) Then
acadApp.Utility.Prompt “[ARX Manager] ARXの動期ロードに成功しました。” & vbCrLf
Else
Err.Raise vbObjectError + 1001, “EnsureArxLoaded”, “ARXのロード命令を発行しましたが、ロードを確認できませんでした。”
End If
Exit Sub
ErrorHandler:
MsgBox “【致命的なエラー】ARXアドインのロードに失敗しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “AutoCAD VBA 依存関係管理”
‘ 必要に応じてログ出力や処理の緊急中断を行う
End Sub
Private Function IsArxLoaded(ByRef app As AcadApplication, ByVal arxFileName As String) As Boolean
Dim arxList As Variant
Dim i As Long
Dim loadedName As String
IsArxLoaded = False
‘ ListArxメソッドは現在ロードされているARXの配列を返す
arxList = app.ListArx
‘ 配列が空(何もロードされていない)の場合は抜ける
If Not IsArray(arxList) Then Exit Function
For i = LBound(arxList) To UBound(arxList)
‘ フルパスからファイル名のみを抽出して比較
loadedName = GetFileNameFromPath(CStr(arxList(i)))
‘ 大文字小文字を無視して比較
If StrComp(loadedName, arxFileName, vbTextCompare) = 0 Then
IsArxLoaded = True
Exit Function
End If
Next i
End Function
Private Function GetFileNameFromPath(ByVal fullPath As String) As String
Dim pos As Long
pos = InStrRev(fullPath, “\”)
If pos > 0 Then
GetFileNameFromPath = Mid(fullPath, pos + 1)
Else
GetFileNameFromPath = fullPath
End If
End Function
Private Function FileExists(ByVal filePath As String) As Boolean
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
FileExists = fso.FileExists(filePath)
Set fso = Nothing
End Function
—
4. プロフェッショナルとしての設計上の注意点
このコードを実務環境に投入するにあたり、チーフアーキテクトとして以下の2点を厳命しておく。
① セキュリティとパスのハードコーディング回避
サンプルコードではパスを固定値(Const)にしているが、実際のエンタープライズ環境では、レジストリやネットワーク上の共通設定ファイル(INIやJSON、あるいは図面のカスタムプロパティ)から動的にパスを解決すべきだ。開発環境と本番環境でパスが変わるたびにVBAコードを書き換えるような設計は、今すぐ廃止しなさい。
② タイミングの制御(アタッチの猶予)
`AcadApplication.LoadArx` を実行した直後、AutoCAD内部ではC++の `AcRxDynamicLinker` が初期化ルーチン(`kInitMsg` 等)を走らせる。
大規模なARXの場合、ロードコマンドの実行直後に依存するカスタムコマンド(`C:MyCommand` など)を連続して呼び出すと、初期化が完了しておらず「未知のコマンド」エラーになることがある。
もしロード直後にARX側のカスタムコマンドをVBAからキックする場合は、必要に応じて `DoEvents` を挟むか、ロードの成否を再確認するウェイトロジックを考慮すること。
—
5. まとめ
AutoCAD VBAにおける真の自動化とは、単に図形を描画するコードを書くことではない。「実行環境の不確実性をコードの力で完全にねじ伏せること」だ。
今回紹介した `ListArx` と `LoadArx` を組み合わせた依存関係管理をマスターすれば、オペレーターのヒューマンエラーは根絶され、あなたのツールベースは圧倒的な堅牢性を手に入れる。
妥協のない設計で、次のプロジェクトも完全に制圧してほしい。
