【入門編】【実務中級】SendCommandメソッドの光と影:API未対応コマンドをVBAから実行する際の同期制御と注意点 – AutoCAD VBA解析バイブル

スポンサーリンク

こんにちは!AutoCADの自動化の海へようこそ。
VBAの基本オブジェクト(LineやCircleなど)をひと通り操作できるようになり、「よし、次はもっと複雑な作業を自動化するぞ!」と意気込んでいる頃ではないでしょうか。

図面を描いていると、「あ、このコマンド、VBAのメソッドに用意されてない……!」という壁にぶつかります。例えば、一部の編集コマンドや、サードパーティ製アドオンの独自コマンドなどですね。

そんな時、「VBAでは無理か……」と諦めるのはまだ早い!
今回は、AutoCAD VBAの最終兵器であり、同時に諸刃の剣でもある`SendCommand`メソッドについて、その「光と影」を徹底的に解説していきます。

ここをクリアすれば、あなたのAutoCAD VBAスキルは確実に実務レベルの「中級者」へとステップアップします。温かく導いていくので、一緒にリラックスしてマスターしていきましょう!

1. `SendCommand`メソッドとは?(光の側面)

AutoCAD VBAの標準オブジェクトモデルは非常に洗練されていますが、すべてのCADコマンドを網羅しているわけではありません。

そんなとき、「まるで人間がキーボードからコマンドを打ち込むかのように、AutoCADに文字列として命令を送り込む」ことができるのが、`SendCommand`メソッドです。

基本的な使い方

使い方は驚くほどシンプルです。操作したい図面(Documentオブジェクト)に対して、実行したいコマンド文字列を渡すだけです。

Sub Sample_SendCommand_Basic()
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.Application.ActiveDocument

‘ 「CIRCLE」コマンドを、画面上で中心点と半径を指定する流れで実行する
‘ 半角スペースや改行(VbCr)は、キーボードの「Enter」キーを意味します
acadDoc.SendCommand “CIRCLE ” & vbCr

MsgBox “コマンドを送信しました!”, vbInformation
End Sub

このように、VBAのオブジェクトとして用意されていない複雑なコマンドや、お決まりのルーティンワークをコマンドライン経由で一網打尽にできるのが、このメソッド最大の「光(強力なメリット)」です。

2. 誰もがハマる「最大の影」:非同期処理の罠

さて、ここからが本題であり、実務で最も恐れられている「影」の部分です。

プログラミング初心者〜中級者が必ずと言っていいほどハマる罠、それが「非同期実行(非同期処理)」という性質です。

同期と非同期ってなに?

  • 同期(Normal): 指示を出したあと、それが「完全に終わるのを待ってから」次の行のコードに進む。
  • 非同期(Asynchronous): 指示を出したら、完了を待たずに「一瞬で次の行のコードに進む」

`SendCommand`は、完全に「非同期」で動作します。
つまり、VBA側から「CIRCLEコマンドを実行しろ!」と命令した瞬間、AutoCADがまだ円を描いている最中であっても、VBAは「次の行の処理」を勝手に始めてしまうのです。

恐ろしいエラーの例

もし、以下のようなコードを書いたとします。

Sub Sample_TheTrap()
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.Application.ActiveDocument

‘ 1. 何らかの重いコマンドを実行する
acadDoc.SendCommand “-PURGE ” & vbCr & “A ” & vbCr & “” & vbCr & “N ” & vbCr

‘ 2. 続けて、たった今パージされたはずのオブジェクトを操作するコード
‘ ⚠️【大惨事】パージが終わっていないのに次のコードが走るため、エラーになるか、意図しない図面を破壊します!
MsgBox “パージ完了!”, vbInformation
End Sub

これが、実務でマクロが暴走したり、タイミングによって成功したり失敗したりする(いわゆる「タイミング依存のバグ」を生む)最大の原因です。

3. 影を克服する!実務で使える同期制御のテクニック

「じゃあ、SendCommandを使うときはどうやって待てばいいの?」と思いますよね。
実は、AutoCAD VBAには「コマンドの完了を直接検知するイベント」が標準のSendCommandにはありません。

そこで、実務の現場ではいくつかの工夫を凝らしてこの「タイムラグ」を乗り越えています。代表的なアプローチを2つご紹介しましょう。

アプローチ①:AutoCADの「WHILE」や「IDLE」状態を利用する(概念的なアプローチ)

VBA側で単純に`DoEvents`を挟みながら、AutoCADがビジー状態(何かを計算・描画している状態)から抜けるのをポーリング(監視)する方法があります。しかし、コードが複雑になりがちです。

アプローチ②:AutoCAD LISP(AutoLISP)との連携(【推奨】最も確実な手法)

実務で最も堅牢(ロバスト)とされるのが、「AutoLISPを挟む」というテクニックです。
AutoLISPは、AutoCADの内部で同期的に動作しやすい特性を持っています。`SendCommand`を通じてLISPの式を送り込むことで、処理の順序を完全にコントロールしやすくなります。

Sub Sample_WithLisp()
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.Application.ActiveDocument

‘ LISP式を使って、コマンドの実行と事後処理をラップして送り込む
‘ (※イメージしやすいよう簡略化した構文です)
Dim lispCommand As String
lispCommand = “(progn (command “”_.CIRCLE”” “”0,0,0″” “”50″”) (princ “”\n円を描画しました!””)) ” & vbCr

acadDoc.SendCommand lispCommand

MsgBox “LISP経由の命令を送信しました。”, vbInformation
End Sub

4. `SendCommand`を使うときの鉄則チェックリスト

最後に、実務で`SendCommand`を採用する際に、必ず頭に入れておいてほしい「3つの鉄則」をまとめます。ここをクリアしていれば、もう怖いものはありません!

1. 極力、標準のオブジェクト操作を優先する

  • 直線を引きたいなら `acadDoc.ModelSpace.AddLine` を使う。
  • 削除したいなら `ent.Delete` を使う。
  • 「どうしてもAPIで用意されていない機能(一部の特殊な編集・削り出しなど)」の時だけ `SendCommand` を使うのがプロの鉄則です。

2. コマンド文字列の「スペース」と「VbCr(Enter)」の数に細心の注意を払う

  • 人間がキーボードを叩くとき、「コマンド名打つ ➔ Enter ➔ オブジェクト選択 ➔ Enter」というステップを踏みますよね。
  • VBAから送る文字列も、この「人間のキーストローク」と完全に一致させる必要があります。不足していると、AutoCADがコマンド待ちのまま固まってしまいます。

3. 日本語のコマンド名やレイヤ名は避ける

  • 日本語版AutoCADであっても、コマンドやオプションは英語のコマンド名(頭に `_` や `-` をつけるとなお安全)で指定するようにしてください。環境依存のエラーを防げます。
  • 例: `_-LAYER` や `_ZOOM` など

まとめ

今回は、AutoCAD VBAの『SendCommandメソッド』の光と影について解説しました。

  • 光: 標準APIでは操作できないあらゆるコマンドを、文字列として実行できる無限の可能性。
  • 影: 処理の完了を待たずに先へ進んでしまう「非同期処理」の罠。

この影の性質をしっかりと理解し、「本当にこのメソッドが必要か?」を見極めながら適切に使いこなせるようになれば、あなたの業務自動化の引き出しは圧倒的に広がります。

「ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ!」
ぜひ、実際の図面やテスト用ファイルで試しながら、コードの挙動を肌で感じてみてくださいね。あなたの自動化ライフを心から応援しています!

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