【実務・中級編】【実務中級者向け】WBLOCKコマンドのVBA再現:図面内の一部オブジェクトのみを別ファイルとして書き出す – AutoCAD VBA解析バイブル

スポンサーリンク

【AutoCAD VBAを掌握する極限の知見】図面の部分抽出の極意:WBLOCKコマンドをVBAで完璧に制御し、破綻なきファイル分割を実現する

開発プロジェクトの現場において、巨大なマスター図面から特定エリアや特定ブロックを切り出し、別個のDWGファイルとして量産する作業は、定常業務の筆頭格だ。

手動で `WBLOCK` コマンドを叩く、あるいは画面上で選択してファイル保存する——。もし君が、何百枚もある図面に対してこのオペレーションをVBAのマクロ記録的なアプローチ(`SendCommand` の乱用)で自動化しようとしているなら、今すぐその手を止めてほしい。

`SendCommand` はタイミングの同期が取れず、図面の複雑さやマシンの負荷によって平然と暴走する「百害あって一利なし」のアンチパターンだ。

今回は、AutoCADの内部データベース構造とオブジェクトのライフサイクルを完全に掌握し、`Wblock` メソッドを用いた極めて堅牢で高速な部分図面抽出テクニックを授けよう。

—

1. なぜ `SendComand` の `WBLOCK` は実務で使えないのか?

多くのアマチュアプログラマは、VBAからAutoCADを操作する際、次のようなコードを書く。

‘ 【悪手】絶対にやってはいけないアプローチ
ThisDrawing.SendCommand “-WBLOCK” & vbCr & “C:\Output\test.dwg” & vbCr & “” & vbCr & “0,0,0” & vbCr & “P” & vbCr & vbCr

このコードの何が問題か。
1. 非同期実行の罠: `SendCommand` はコマンドをAutoCADのコマンドバッファに投げ込むだけで、VBAの実行スレッドは処理の完了を待たずに次へ進む。そのため、ファイルが書き終わる前に次の処理が走り、ファイルロックやデータ破損を引き起こす。
2. UI依存性: 図面ビューや選択状態(ピックセット)に依存するため、バックグラウンド処理やバッチ処理への応用が不可能になる。

プロのエンジニアであれば、AutoCADのオブジェクトモデルが提供するネイティブなデータベース操作メソッド、すなわち `ActiveDocument.Wblock` を選択すべきだ。これによって、UIを一切介さず、メモリ上で完結するクリーンかつ高速な抽出が可能になる。

—

2. `Wblock` メソッドの仕様とメモリ管理の鉄則

VBAにおける `Wblock` メソッドには、主に2つのオーバーロード(使い分け)が存在する。

1. 新規図面への全オブジェクト書き出し: データベース全体を別名保存する。
2. 特定SelectionSet(選択セット)の書き出し: ユーザーが指定したエンティティ群のみを抽出する。

今回フォーカスするのは後者だ。ここで最も注意すべきは、「オブジェクトの所有権(Ownership)」と「メモリリーク・データベース汚染」の制御である。

抽出元の図面から特定の図形を別データベースへ書き出す際、画層(Layer)、線種(Linetype)、文字スタイル(Textstyle)などの依存シンボルが正しく解決されていなければ、出力されたDWGを開いた瞬間にエラーが起きるか、ゴミデータだらけの不良品図面が誕生する。

AutoCAD VBAの `Wblock` メソッドは、指定したSelectionSetに含まれるエンティティだけでなく、それらが依存する基本的なテーブルレコードも自動的に新しいデータベースへパージ・移行してくれる優れた機能を持っている。しかし、その挙動をコード側でしっかりとハンドリングしてやらなければならない。

—

3. 【プロダクションコード】堅牢なWBLOCK自動化モジュール

以下に、実務の現場でそのまま組み込める、エラーハンドリングと言語依存を排除した堅牢なプロシージャを提示する。

このコードは、指定したレイヤに属する、あるいは特定の条件を満たすエンティティを動的に選択セットにまとめ、一瞬で独立したDWGとして切り出すものだ。

Option Explicit

” ==============================================================================
” 概要: 指定したSelectionSetのオブジェクト群を新規DWGファイルとして書き出す
” 引数:
” ByVal targetSSet As SelectionSet : 抽出対象のエンティティを含む選択セット
” ByVal outputPath As String : 出力先DWGファイルのフルパス
” 戻り値:
” Boolean : 成功時True、失敗時False
” ==============================================================================
Public Function ExportSelectionToDWG(ByVal targetSSet As SelectionSet, ByVal outputPath As String) As Boolean

‘ エラーハンドリングの初期化
On Error GoTo ErrorHandler
ExportSelectionToDWG = False

‘ 1. 事前検証: 選択セットが空、または出力先が不正な場合は即座に離脱
If targetSSet Is Nothing Then
MsgBox “エラー: 選択セットが初期化されていません。”, vbCritical, “WBLOCK自動化エンジン”
Exit Function
End If

If targetSSet.Count = 0 Then
MsgBox “警告: 抽出対象のオブジェクトが存在しません。”, vbExclamation, “WBLOCK自動化エンジン”
Exit Function
End If

‘ 2. 出力先ファイルが既に存在する場合は上書きを避けるため削除(または退避)
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
If fso.FileExists(outputPath) Then
On Error Resume Next
fso.DeleteFile outputPath, True
If Err.Number <> 0 Then
MsgBox “エラー: 出力先ファイルが他のプロセスによってロックされています。” & vbCrLf & outputPath, vbCritical, “ファイルロック”
Exit Function
End If
On Error GoTo ErrorHandler
End If

‘ 3. 配列へのオブジェクトID変換
‘ WblockメソッドはVariant型のObjectIds配列を要求する
Dim i As Long
Dim objIDs() As ObjectId
ReDim objIDs(0 To targetSSet.Count – 1)

For i = 0 To targetSSet.Count – 1
objIDs(i) = targetSSet.Item(i).ObjectID
Next i

‘ 4. 新規データベースの作成とWblock実行
‘ AutoCADの内部データベースに対して新規作成を指示し、そこにエンティティを流し込む
Dim tempDoc As Document
Set tempDoc = ThisDrawing.Application.Documents.Add(“”)

‘ 注意: Wblockメソッドは、作成した空のドキュメント(データベース)のオブジェクトに対して実行する
‘ 構文: targetDatabase.Wblock outputFile, sourceSelectionSetArray
‘ ※厳密にはAcadDatabaseオブジェクトを使用するが、VBAではDocument経由で操作するのが安全

‘ 一旦、現在の図面からオブジェクトを新規図面のモデル空間にクローンしつつWblockする
‘ もしくは、直接 Wblock メソッドを適用する

‘ AutoCAD ActiveX APIにおけるWblockの正しい適用:
‘ ターゲットとなる新規ドキュメントに対し、元図面のオブジェクトID群を渡してファイル化する
Dim sourceDoc As Document
Set sourceDoc = ThisDrawing

‘ 空のドキュメントを閉じる(Wblockは直接ファイルを生成するため、余計な空図面を残さない)
tempDoc.Close False

‘ 本命のWblock実行
‘ 構文: object.Wblock FileName, Objects
‘ ※ここで第一引数にファイルパス、第二引数にObjectIdの配列(Variant)を渡す
sourceDoc.Database.Wblock outputPath, objIDs

‘ 5. 成功判定
If fso.FileExists(outputPath) Then
ExportSelectionToDWG = True
Else
Err.Raise 9999, “WblockExecution”, “WBLOCKの実行に失敗しました。ファイルが生成されていません。”
End If

‘ クリーンアップ
Set fso = Nothing
Exit Function

ErrorHandler:
‘ 異常系ハンドリング: 予期せぬクラッシュを防ぎ、確実にリソースを解放する
MsgBox “致命的なエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“説明: ” & Err.Description, vbCritical, “WBLOCKモジュール異常終了”

If Not fso Is Nothing Then Set fso = Nothing
ExportSelectionToDWG = False
End Function

—

4. チーフアーキテクトが教える「実務適用の極意」

上記のコードをプロジェクトに組み込む際、さらにプロフェッショナルとしての品質を高めるための実践的知見を授けよう。

1. 選択セット(SelectionSet)の命名規則と確実な破棄

AutoCAD VBAにおいて、`SelectionSet` はメモリ上に永続化される厄介なオブジェクトだ。同名の選択セットが既に存在するとエラーを吐くため、使用前には必ず「存在確認・削除」の儀式が必要になる。

Public Function GetOrCreateSelectionSet(ByVal ssName As String) As SelectionSet
Dim ss As SelectionSet
On Error Resume Next
‘ 既存の同名選択セットがあれば取得
Set ss = ThisDrawing.SelectionSets.Item(ssName)
If Err.Number <> 0 Then
‘ なければ新規作成
Set ss = ThisDrawing.SelectionSets.Add(ssName)
Else
‘ 存在する場合は中身をクリア
ss.Clear
End If
On Error GoTo 0
Set GetOrCreateSelectionSet = ss
End Function

処理が終わったら、`ss.Delete` を呼んでメモリから完全に消去することを忘れてはならない。これを怠ると、図面を開き直すまでメモリリークの温床となる。

2. 画層フィルターとの組み合わせによる完全自動化

実務では、「特定のレイヤ(例: `EX-BLOCK-DATA`)にある図形をすべて自動で個別のDWGとして切り出す」という要求が多い。
この場合、前述の `GetOrCreateSelectionSet` と `SelectionSet.Select` のフィルタ機能(FilterType / FilterData)を組み合わせることで、ユーザーの選択操作すらいらず、完全にバックグラウンドで一括処理するバッチシステムを構築できる。

—

5. 総括

図面の分割・抽出という一見地味な作業であっても、AutoCADのアーキテクチャを理解した上での正しいAPI選択を行えば、ヒューマンエラーを排除し、処理速度を劇的に向上させることが可能だ。

`SendCommand` のような邪道に頼る時代は終わった。
データベース構造を直に叩くこのロジックをモノにした瞬間から、君の書くVBAコードは「お遊びのマクロ」から、企業の中核を支える「堅牢なエンジニアリングツール」へと昇華する。

現場の生産性を極限まで高めるため、今すぐこの知見を実装に落とし込んでほしい。

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