【テクニカル・上級編】【上級】AcadDocument.Database.CopyObjectsを用いた「図面間高速オブジェクトコピー」:クリップボードを経由しない安定実装 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAの深淵:CopyObjectsによる図面間転送の極致

AutoCADの自動化において、最も「素人」が陥りやすい罠が、クリップボード経由のコピー&ペースト(`SendCommand`等による`_COPYCLIP`や`_PASTECLIP`)だ。これはUIスレッドに依存し、メモリを浪費し、何より予期せぬ外部要因で処理が停止する。

真のエンジニアは、AutoCADのメモリ空間を直接操作する。今回は、`Database.CopyObjects`を用いた、図面間転送の決定版を伝授する。

なぜCopyObjectsなのか:メモリと安定性の物理学

`CopyObjects`は、単なるコピーコマンドではない。AutoCADのデータベース・エンジンが提供する、「オブジェクトの所有権を別データベースへ移行する」ための低レベルAPIである。

  • クリップボード不要: Windowsのクリップボード汚染を回避し、バックグラウンドで完結する。
  • アトミックな操作: 大量オブジェクトを一括で処理でき、トランザクションの整合性を保ちやすい。
  • 名前衝突の制御: `IdMapping`を利用することで、ブロック定義や画層、線種の名前衝突時に自動でサフィックスを付与するか、既存の定義を継承するかを厳密に制御できる。

実装の核心:CopyObjectsによる図面間転送

以下のコードは、アクティブ図面からターゲット図面へ、選択したオブジェクトを直接転送するプロフェッショナル・実装テンプレートだ。

Option Explicit

‘ 図面間転送の最速解
Public Sub ExportObjectsToDrawing(ByVal targetDoc As AcadDocument, ByVal objectsToCopy() As AcadEntity)
Dim sourceDb As AcadDatabase
Dim targetDb As AcadDatabase
Dim idMap As New AcadIdPair
Dim objCollection() As AcadObject
Dim i As Long

‘ 1. オブジェクト配列の型変換(AcadEntity -> AcadObject)
ReDim objCollection(LBound(objectsToCopy) To UBound(objectsToCopy))
For i = LBound(objectsToCopy) To UBound(objectsToCopy)
Set objCollection(i) = objectsToCopy(i)
Next i

‘ 2. データベースの取得
Set sourceDb = ThisDrawing.Database
Set targetDb = targetDoc.Database

‘ 3. CopyObjects実行
‘ 第4引数にNothingを渡すと、オブジェクトは所有者を持たない状態で生成される
‘ その後、targetDb.ModelSpaceへAppendする必要がある場合が多い
sourceDb.CopyObjects objCollection, targetDb.ModelSpace, idMap

‘ メモリ最適化:明示的な解放
‘ VBAは参照カウント方式だが、大規模処理では明示的なNothing化が重要
Set sourceDb = Nothing
Set targetDb = Nothing
Set idMap = Nothing
End Sub

シニアエンジニアが意識すべき「3つの制約」

この手法を本番環境で運用する場合、以下の技術的制約を無視してはならない。

1. 依存関係の解決(Deep Cloning)

`CopyObjects`は指定したオブジェクトのみをコピーする。もしコピー対象が「外部参照」や「複雑なブロック」を含む場合、依存する辞書データ(Dictionary)や名前付きオブジェクトが不足し、転送先で図面が破損(またはエラー)する。

  • 解決策: 依存オブジェクトもコレクションに含めるか、`WBlock`メソッドによる図面単位の切り出しを検討せよ。

2. IdMappingの活用

`CopyObjects`の第3引数である`IdMapping`を精査することで、コピーされたオブジェクトの「転送先での新しいObject ID」を追跡できる。

  • 極意: これを使えば、コピー直後に属性ブロックの値を書き換えたり、画層を動的に変更するなどの後処理が、確実に行える。

3. レガシー環境でのメモリリーク

VBA(COM)環境では、`AcadObject`の参照が保持され続けるとガベージコレクションが正しく働かないことがある。

  • 運用上の鉄則: ループ内でオブジェクトを生成・操作する場合は、必ず `Set obj = Nothing` を徹底すること。特に図面をまたぐ処理では、`targetDoc`のオブジェクトモデルへの参照をスコープアウトさせるタイミングを厳密に制御せよ。

アーキテクトからの提言:次のステップへ

もし君が扱っている図面が数万要素を超えるなら、VBAの限界を認め、ObjectARX(C++)または.NET APIへ移行する準備をすべきだ。しかし、VBAであっても`CopyObjects`の特性を理解していれば、クリップボード経由の低俗なスクリプトとは一線を画す、圧倒的な安定性を誇るツールを構築できる。

AutoCADは「描画ツール」ではない。「データベース管理システム」である。
この視点を持った時、君の自動化コードは、ただの「作業補助」から、真の「エンジニアリング・インフラ」へと昇華するはずだ。

健闘を祈る。

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