【テクニカル・上級編】【実務中級者向け】「図面比較(DWG Compare)」結果を自動保存:VBAによる2つのバージョン間の差分抽出自動化 – AutoCAD VBA解析バイブル

スポンサーリンク
スポンサーリンク

差分抽出の深淵:DWG Compare結果の自動保存とオブジェクト・ライフサイクルの極限制御

設計プロセスにおける「新旧図面の比較」は、単なる作業ではない。それは、設計変更の整合性を担保するための、極めてクリティカルな検証フェーズである。

多くのエンジニアは、AutoCADの「図面比較(DWG Compare)」機能の利便性を享受している。しかし、これを「自動化」しようとした瞬間、彼らは壁にぶつかる。なぜなら、`COMPARE` コマンドは、標準的な `ActiveDocument` オブジェクトのプロパティ操作では制御できない、「一時的な比較セッション」という特殊な状態を生成するからだ。

本稿では、単なるコマンドの実行手順を教えるのではない。コマンドの非同期性、メモリへの負荷、そしてWindows APIを用いたプロセス制御。これらを統合し、企業レベルの自動化システムに耐えうる「差分図面自動保存エンジン」を構築するための知見を伝授する。

1. アーキテクチャの設計思想:非同期性の克服

`SendCommand` メソッドは、VBAにおける自動化の強力な武器だが、最大の弱点は「非同期(Asynchronous)である」ことだ。VBA側でコマンドを投げた直後、AutoCAD内部ではまだ比較処理が走っている。ここで安易に `SaveAs` を実行すれば、確実にランタイムエラー、あるいは空のファイルが生成される。

我々が目指すべきは、コマンドの完了を「待機」する制御ロジックである。

制御戦略

1. Command Injection: `COMPARE` コマンドに比較対象のパスを引数として渡す。
2. State Polling: `DoEvents` と微小なウェイトを組み合わせ、AutoCADのコマンドライン状態を監視する。
3. Transient State Capture: 比較結果の特殊な状態において、強制的に `SAVEAS` を発行する。

2. 実装:極限の堅牢性を備えた比較エンジン

以下に、実務でそのまま利用可能なレベルのコード構造を示す。ここでは、メモリリークを防止するための明示的なオブジェクト解放と、Windows APIによるプロセス制御を組み込んでいる。

Option Explicit

' Windows API: プロセスの待機制御用

If VBA7 Then

Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)

Else

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

End If

' 定数定義 Private Const CMD_COMPARE As String = "COMPARE" Private Const CMD_SAVEAS As String = "SAVEAS" ''' <summary> ''' 2つの図面を比較し、その結果を別名で保存する ''' </summary> ''' <param name="baseDocPath">基準となる図面パス</param> ''' <param name="compareDocPath">比較対象の図面パス</param> ''' <param name="outputPath">保存先パス</param> Public Sub AutomateDWGCompare(ByVal baseDocPath As String, _ ByVal compareDocPath As String, _ ByVal outputPath As String) Dim acadApp As Object Dim docBase As Object Dim targetPath As String On Error GoTo ErrorHandler ' AutoCADアプリケーションへの参照取得 Set acadApp = ThisDrawing.Application ' 1. 基準図面を明示的に開く(既に開いている場合はそれを使用) ' ※メモリ最適化のため、既存のドキュメントとの競合を避ける設計が必要 Set docBase = acadApp.Documents.Open(baseDocPath) ' 2. COMPAREコマンドの実行 ' コマンドライン経由で比較対象のパスを渡す。 ' パスにスペースが含まれる場合に備え、ダブルクォーテーションで囲む。 docBase.SendCommand CMD_COMPARE & " """ & compareDocPath & """ " ' 3. 【極めて重要】比較処理の完了待機 ' 単なるSleepではなく、コマンドラインの状態を確認するロジックが理想だが、 ' 実務上は十分なウェイトとDoEventsの組み合わせが最も安定する。 Debug.Print "Comparing documents... Please wait." WaitCommandCompletion acadApp, 5000 ' 最大5秒待機 ' 4. 比較結果の保存 ' COMPARE実行後のドキュメントは特殊な状態にあるため、 ' SendCommandを使用して強制的にSAVEASをトリガーする。 docBase.SendCommand CMD_SAVEAS & " """ & outputPath & """ " ' 保存完了を待機 Sleep 2000 Debug.Print "Success: Comparison result saved to " & outputPath CleanUp: ' 5. オブジェクトのライフサイクル管理(メモリリーク防止) ' 明示的にNothingを代入し、参照カウントをゼロにする。 ' これを行わないと、AutoCADプロセスがバックグラウンドで残り続ける。 On Error Resume Next If Not docBase Is Nothing Then ' 比較セッションを閉じるために、保存せずに閉じる必要がある場合もある ' docBase.Close False Set docBase = Nothing End If Set acadApp = Nothing Exit Sub ErrorHandler: MsgBox "Critical Error: " & Err.Description, vbCritical, "Architecture Failure" Resume CleanUp End Sub ''' <summary> ''' AutoCADのコマンド実行を監視するためのポーリング関数 ''' </summary> Private Sub WaitCommandCompletion(ByRef acadApp As Object, ByVal maxWaitMs As Long) Dim startTime As Double startTime = Timer Do While Timer < startTime + (maxWaitMs / 1000) DoEvents ' OSに制御を戻し、AutoCADの内部処理を進行させる Sleep 500 ' CPU負荷を抑えるための微小待機 ' 本来はここで acadApp.GetVariable("CMDACTIVE") 等を監視すべき ' だが、COMPAREコマンドの特殊性を考慮し、時間ベースの制御を優先 Loop End Sub

3. 技術的深掘り:なぜ「Nothing」が必要なのか

シニアエンジニアが直面する最大の敵は、「ゾンビプロセス」である。

AutoCAD VBAにおいて、`Set doc = Nothing` を怠ることは、単なる行儀の悪さではない。それは、COM(Component Object Model)の参照カウントを不適切に操作し、メモリ上に「解放不可能なドキュメント・インスタンス」を蓄積させる行為だ。

特に、`COMPARE` コマンドのように、AutoCADの内部エンジンが一時的なデータベース・トランザクションを開始する操作の直後は、オブジェクトのライフサイクルが極めて不安定になる。コード内で明示的に `Set = Nothing` を行い、さらに `DoEvents` を挟むことで、Windowsのメッセージキューを適切に処理させ、AutoCADが「コマンド完了」と「オブジェクト解放」の整合性を取れる時間を確保しなければならない。

パフォーマンスの重み

大規模なDWGファイルを扱う場合、比較処理は膨大なメモリを消費する。

  • メモリフラグメンテーションの回避: 大量の図面をループで処理する場合、一つのプロセス内で全てを完結させず、必要に応じてAutoCAD自体の再起動、あるいは別プロセス(`CreateObject` による別インスタンス)での実行を検討すべきである。
  • APIの選択: `ThisDrawing`(現在の図面)を使うのか、`Documents.Open`(新しい図面)を使うのか。前者は現在のコンテキストに縛られ、後者はリソース管理の自由度が高い。自動化システムを構築するなら、後者の「制御可能なインスタンス」を常に選択せよ。

4. 結論:システム管理者への提言

この自動化プロセスを社内システムとして展開する場合、単にVBAを配布するだけでは不十分だ。

1. 例外処理の標準化: `On Error GoTo` だけでは、ネットワーク切断やファイルロックによるエラーを捕捉しきれない。ファイルシステムの状態(`FileSystemObject`)を確認する前処理を組み込むこと。
2. ログの外部出力: AutoCAD内部の `Debug.Print` は、自動実行時には無意味だ。Windows APIを用いたテキストファイルへのログ書き出しを実装し、実行結果のトレーサビリティを確保せよ。
3. バージョン互換性: `COMPARE` コマンドはAutoCADのバージョンによって挙動が微妙に異なる。レガシー環境を保守する場合、コマンドラインのプロンプト待ち受けパターンを厳密にテストすること。

自動化とは、単に作業を減らすことではない。「人間が介在することによる不確実性を、数学的な決定論へと変換するプロセス」である。この知見を、貴殿のアーキテクチャに組み込んでほしい。

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