マクロ記録の先へ。AutoCAD VBAで「図面の一部だけ」をDXFとして切り出す極意
こんにちは。今日も図面作成と自動化の荒波を乗り越えていますか?
「マクロの記録」を使って、最初の一歩を踏み出したあなた。素晴らしいですね。それはエンジニアとしての第一歩です。しかし、実務が進むにつれて、こんな壁にぶつかることはありませんか?
「図面全体を保存するのではなく、今選択しているこの部品だけを、DXF形式でサッと別ファイルとして書き出したいんだ」
標準の「名前を付けて保存」では、ファイル全体が保存されてしまいます。加工メーカーへのデータ渡しや、部品図の切り出しにおいて、巨大なアセンブリ図面から特定範囲だけを抽出する作業は、手動で行うと非常に時間がかかり、ミスも誘発します。
今日は、そんな悩みを一撃で解決する「Export(書き出し)の概念と、選択セット(SelectionSet)を制御する高度なテクニック」を伝授します。
ここをクリアすれば、あなたのVBAは「ただの記録」から「実務を支えるツール」へと進化しますよ。
1. なぜ「名前を付けて保存」ではダメなのか?
AutoCAD VBAにおける `SaveAs` メソッドは、現在の図面(Document)そのものの属性(ファイル名や形式)を書き換える操作です。つまり、「今開いている図面そのもの」を保存することになります。
一方で、私たちがやりたいのは「図面の中にある、特定のオブジェクトたちだけを、新しいファイルとして抽出する」ことです。
これを実現するための鍵が、「SelectionSet(選択セット)」という概念です。
概念図:データの抽出プロセス
1. 空の網(SelectionSet)を用意する
2. 特定の範囲(座標)やオブジェクトを網でキャッチする
3. その網の中身だけを、外部ファイル(DXF)へ流し込む
この「網(Selection Set)」の扱いこそが、中級者への分かれ道です。
2. 【重要】プロが教える「Selection Set」の罠とライフサイクル
ここで、多くの初級者が陥る致命的なエラーについて触れておきましょう。
AutoCAD VBAにおいて、`SelectionSets.Add` メソッドで新しい選択セットを作成する場合、「同じ名前のセットが既にメモリ上に存在していると、エラーで止まる」という性質があります。
マクロを一度実行してエラーで止まった後、もう一度実行しようとすると、前回作った「網」がメモリに残っているため、プログラムが「その名前はもう使われています!」と怒ってしまうのです。
プロの鉄則:
> 「選択セットを作る前には、必ず同名のセットが存在しないか確認し、存在すれば削除(Delete)する。そして、使い終わったら必ず削除する。」
この「オブジェクトのライフサイクル(生成 $\rightarrow$ 使用 $\rightarrow$ 破棄)」を意識できるかどうかが、堅牢なプログラムを書けるかどうかの境目です。
3. 実践:特定範囲をDXFとして切り出すコード
それでは、実際に使えるコードを見ていきましょう。
今回は、「ユーザーが画面上で指定した範囲(窓選択)」の中にあるオブジェクトを、DXF形式で保存するスクリプトを作成します。
Option Explicit
''' <summary>
''' 選択した範囲のオブジェクトをDXFとして書き出すプロシージャ
''' </summary>
Sub ExportSelectedRangeToDXF()
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing
Dim sSet As AcadSelectionSet
Dim sSetName As String
sSetName = "MyExportSet" ' 選択セットの名前を固定
Dim pt1 As Variant
Dim pt2 As Variant
Dim filePath As String
On Error GoTo ErrorHandler
' --- 1. 既存の選択セットの掃除 (プロの作法) ---
' 同名のセットが既にメモリにあるとエラーになるため、事前に削除を試みる
On Error Resume Next
acadDoc.SelectionSets.Item(sSetName).Delete
On Error GoTo ErrorHandler ' エラーハンドリングを元に戻す
' --- 2. ユーザーによる範囲選択 ---
' ユーザーに図面上の2点をクリックさせて範囲を指定させる
MsgBox "DXFとして切り出したい範囲を、2点クリックして指定してください。"
pt1 = acadDoc.Utility.GetPoint(, "1点目を選択: ")
pt2 = acadDoc.Utility.GetPoint(pt1, "2点目を選択: ")
' --- 3. 選択セットの作成とオブジェクトのキャッチ ---
Set sSet = acadDoc.SelectionSets.Add(sSetName)
' CrossingWindow(交差窓選択)を使用して、範囲内のオブジェクトを網に捉える
sSet.Select acSelectionSetCrossingWindows, pt1, pt2
' 選択されたオブジェクトがゼロなら終了
If sSet.Count = 0 Then
MsgBox "選択範囲内にオブジェクトが見つかりませんでした。"
sSet.Delete
Exit Sub
End If
' --- 4. 保存先の指定 ---
' 本来はダイアログを使うのが理想ですが、今回はシンプルにデスクトップへ
' ※パスの扱いは環境に合わせて調整してください
filePath = Environ("USERPROFILE") & "\Desktop\ExportedPart.dxf"
' --- 5. 書き出しの実行 ---
' AutoCADのExportメソッドは、選択セットを直接渡す形式ではなく、
' コマンドライン経由、あるいはWBLOCK(書き出し)的なアプローチが確実です。
' ここでは、最も確実で高速な「WBLOCK」コマンドをSendCommandで制御する手法をとります。
' コマンドの組み立て: WBLOCK -> ファイルパス -> 選択セットの内容 -> 終了
' 注意: コマンド送信はAutoCADのコマンドラインを直接操作する「魔法」です
acadDoc.SendCommand "WBLOCK " & filePath & " N " & vbCr
' 選択セットの中身をコマンドラインに流し込むための工夫
' 実際の実務では、WBLOCKコマンドの対話形式に合わせる必要があります。
' ここでは概念を示すため、最も安定する「現在の選択を書き出す」流れを記述します。
MsgBox "書き出し処理を試みています。完了後、デスクトップを確認してください。"
' ※補足: SendCommandは非同期的な挙動をするため、
' 複雑な制御が必要な場合は、オブジェクトをコピーして新図面に貼り付ける手法が推奨されます。
' --- 6. 後片付け (重要!) ---
sSet.Delete
MsgBox "処理が完了しました。"
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
' エラー時も、もし選択セットが残っていれば掃除する
On Error Resume Next
acadDoc.SelectionSets.Item(sSetName).Delete
End Sub
4. さらに高みを目指すための「設計思想」
上記のコードでは、`SendCommand` を使った手法を紹介しました。しかし、大規模なシステムを設計するアーキテクトの視点では、もう一つのアプローチを検討します。
究極の安定策:New Document 方式
`SendCommand` は非常に強力ですが、ユーザーが途中でコマンドを中断したり、AutoCADのバージョンによってコマンドの挙動が微妙に変わるリスクがあります。
真に堅牢な(絶対に止まらない)ツールを作るなら、以下の手順を検討してください。
1. 新しい図面(Documents.Add)をメモリ上に作成する
2. 選択したオブジェクトを、その新図面へ `CopyObjects` メソッドで転送する
3. 新図面を `SaveAs` でDXFとして保存する
4. 新図面を閉じる
この方法なら、現在の図面(メインの作業環境)を一切汚さず、オブジェクトのライフサイクルを完全にコントロール下に置くことができます。
まとめ:今日から意識すべきこと
1. Selection Setは「使い終わったら必ず消す」:メモリリークとエラーを防ぐ鉄則です。
2. エラーハンドリングを怠らない:ユーザーがキャンセルした時、プログラムが「死ぬ」のではなく「優しく終了する」ように設計しましょう。
3. 「コマンド操作」か「オブジェクト操作」かを見極める:手軽なのは `SendCommand` ですが、プロフェッショナルな品質を求めるなら `CopyObjects` による新図面への転送をマスターしましょう。
ここをクリアすれば、あなたのAutoCAD VBAは、単なる自動化を超えて、設計プロセスそのものを変革する武器になります。
一歩ずつ、着実に。また次回の講義でお会いしましょう!
