【テクニカル・上級編】【上級】AcadApplication.Evalメソッドの魔術:VBAからAutoLISP関数を呼び出しAPIの限界を突破する – AutoCAD VBA解析バイブル

スポンサーリンク

【上級】AcadApplication.Evalメソッドの魔術:AutoLISPとの境界を突破する極限の技術

AutoCAD VBAを極めようとする者にとって、標準API(ActiveX Automation)の壁にぶつかるのは通過儀礼だ。「なぜ、このプロパティが公開されていないのか?」「なぜ、この複雑な図形情報の取得にこれほどコストがかかるのか?」――その苛立ちは正しい。VBAのAPIは、AutoCADの全機能の6割程度しかカバーしていないからだ。

しかし、我々には「裏口」がある。それが `AcadApplication.Eval` メソッドだ。このメソッドは、AutoCADの魂であるLISPインタープリタをVBAから直接叩くための「橋頭堡」である。

1. Evalメソッドの真髄:LISPを武器にする理由

VBAが不得手とする「図形定義データの直接参照(DXFグループコードの高速抽出)」や「AutoCAD内部変数の動的制御」は、LISPの独壇場だ。`Eval` を使えば、VBAの快適な開発環境を維持したまま、LISPのパワーを召喚できる。

この連携の核心は、「文字列として構築したLISP式を、いかに安全かつ高速に実行するか」に集約される。

2. 実装:VBAからLISPを制御するアーキテクチャ

単に `Eval` を呼ぶだけでは素人だ。真のエンジニアは、戻り値の型変換とエラーハンドリング、そしてメモリの解放までを制御する。

以下は、`Eval` を用いて、標準APIでは取得が困難な「特定のシステム変数」や「図形データ」を取得するためのラッパー関数である。

‘ 伝説的なチーフアーキテクトによるEvalラッパー
‘ 戻り値の型をVariantで受け取り、LISPのリスト構造をVBAで解釈する
Public Function ExecuteLisp(ByVal lispStatement As String) As Variant
Dim acadApp As Object
Set acadApp = ThisDrawing.Application

On Error GoTo ErrHandler

‘ EvalはLISPの実行結果をVariantで返す
‘ 文字列として構築されたLISP式をコンテキストに送り込む
ExecuteLisp = acadApp.Eval(lispStatement)

Exit Function

ErrHandler:
‘ LISP実行時の構文エラーや未定義関数をトラップ
Debug.Print “LISP Execution Error: ” & Err.Description
ExecuteLisp = Null
End Function

‘ 使用例:現在のドキュメントの「保存されていない変更」状態をLISP経由で取得
Sub GetDocStatus()
Dim result As Variant
‘ (getvar “DBMOD”) はVBAのAPIで取得しにくい情報を一発で射抜く
result = ExecuteLisp(“(getvar “”DBMOD””)”)

If Not IsNull(result) Then
MsgBox “現在のDBMOD値: ” & result
End If
End Sub

3. メモリとオブジェクトのライフサイクル:伝説のエンジニアの流儀

`Eval` を多用すると、AutoCAD内部のメモリ領域(LISPヒープ)を圧迫する可能性がある。また、VBA側のオブジェクト参照が滞留すれば、AutoCADのプロセスは瞬く間に肥大化する。

  • 明示的解放の徹底: `Set acadApp = Nothing` は必須。特にCOMオブジェクトをループ内で何度も取得するのは、パフォーマンス上の自殺行為だ。
  • 文字列の構築コスト: `Eval` に渡す文字列を頻繁に生成する場合、`StringBuilder` のようなロジック(VBAでは文字列連結の最適化)を意識すること。
  • 例外処理の構造化: LISP側でエラーが発生した場合、VBA側まで巻き込まれて落ちるのを防ぐため、必ず `(vl-catch-all-apply …)` をLISP式側に組み込むこと。

LISP側での安全策の例:

;; VBAから呼ぶときは必ずエラーを包む
(vl-catch-all-apply ‘your-function-name (list arg1 arg2))

4. 限界を突破せよ:業務自動化への視座

この手法を習得した諸君は、もはや「APIにある機能」だけでシステムを考える必要はない。

  • レガシー環境の保守: 古いAutoCADバージョンでAPIが貧弱な場合でも、LISPの `entget` や `ssget` を駆使すれば、最新のAPI並みのデータ抽出が可能になる。
  • システム間連携: ExcelからVBAを介し、AutoCADのLISP環境を制御することで、CAD図面を単なる図形から「構造化されたデータベース」へと昇華させることができる。

最後に:諸君への警告

`Eval` は強力な「魔術」だが、乱用すれば保守性は崩壊する。「VBAで完結できることはVBAでやる。VBAにできないことだけをLISPに委託する」という原則を忘れてはならない。

コードは、常にシンプルで、かつ泥臭い現場の要求に応えられる強靭さを持つべきだ。貴殿の構築するシステムが、次の10年を生き抜くアーキテクチャであることを期待している。

――健闘を祈る。

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