【テクニカル・上級編】【実務中級者向け】保存時の「DWG図面比較」自動実行:旧バージョンとの差分を検出し、変更箇所を明示した図面を別保存する – AutoCAD VBA解析バイブル

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

データの整合性を守る「差分監査」の設計思想:AutoCADにおける自動DWG比較ワークフロー

設計データの変更は、単なる数値の書き換えではない。それは、プロジェクト全体の整合性に対する挑戦である。

多くの現場では、「上書き保存」というあまりに単純なアクションが、意図しない変更や、過去の設計意図の破壊を招いている。シニアエンジニアやシステム管理者であれば、単に「ファイルを保存する」ことの危うさを理解しているはずだ。真に求められるのは、「何が変わったのか」をシステムが自律的に検知し、監査証跡(Audit Trail)を残すアーキテクチャである。

本稿では、AutoCAD VBAを用い、保存プロセスに「DWG比較(DWGCOMPARE)」を組み込み、変更箇所を視覚化した比較図面を自動生成する、プロフェッショナル向けの差分管理システムの実装手法を詳解する。

1. アーキテクチャの核心:コマンド制御と状態管理

AutoCADの`DWGCOMPARE`コマンドは、非常に強力なUIベースの機能であるが、APIから直接「比較結果のオブジェクト」を返してくれるほど甘い設計にはなっていない。これは、AutoCADが「コマンド(UI)」と「API(Object Model)」を分離したレガシーな構造を維持しているためだ。

我々エンジニアが取るべき戦略は、「シャドウ・セーブ(Shadow Save)」パターンである。

1. Pre-Save State: 現在のメモリ上の状態を一時ファイルとして保存。
2. Differential Execution: `SendCommand` を介して、既存のバックアップファイルと、一時ファイルを比較実行。
3. Artifact Generation: 生成された比較図面を、監査用ディレクトリへ別名保存。
4. Commit: 本来の保存プロセスを完遂。

このプロセスにおいて、最も注意すべきは「ファイルI/Oの競合」と「メモリリーク」である。

2. Windows APIによるファイルシステムの堅牢な制御

VBA標準の`Dir`関数は簡便だが、ネットワークドライブ上の遅延や、ファイルロックの状態を正確に把握するには力不足だ。ここでは、`kernel32.dll`を呼び出し、ファイル属性を直接参照するアプローチを取る。これにより、比較対象となる「旧バージョン」の存在確認を、より低レイヤーで確実に行う。

3. 実装:高度な差分監査モジュール

以下に、実務に耐えうるクラスレベルのロジックを示す。ここでは、オブジェクトの明示的な解放と、エラーハンドリングによるシステムの停止防止を最優先している。

'------------------------------------------------------------------------------
' Module: DiffAuditEngine
' Description: AutoCADにおける保存前差分比較・監査ログ生成エンジン
' Author: Chief Architect
'------------------------------------------------------------------------------

Option Explicit

' Windows APIによるファイル属性確認
Private Declare PtrSafe Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Private Const INVALID_FILE_ATTRIBUTES As Long = &HFFFFFFFF

' 定数定義
Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80
Private Const DIFF_EXT As String = ".diff"

''' <summary>
''' 保存プロセスに差分監査を組み込むメインルーチン
''' </summary>
Public Sub ExecuteSecureSave(ByRef acadDoc As Object)
    Dim currentPath As String
    Dim backupPath As String
    Dim tempPath As String
    Dim diffReportPath As String
    Dim shellApp As Object
    
    On Error GoTo ErrorHandler
    
    currentPath = acadDoc.FullName
    ' 既存のバックアップ(.bak)を比較対象とする
    backupPath = Replace(currentPath, ".dwg", ".bak")
    
    ' 1. バックアップの存在確認(APIレベルでの検証)
    If GetFileAttributes(backupPath) = INVALID_FILE_ATTRIBUTES Then
        Debug.Print "No backup found. Proceeding with standard save."
        acadDoc.Save
        Exit Sub
    End If
    
    ' 2. 現在の状態を一時的に保存(比較用)
    tempPath = Replace(currentPath, ".dwg", "_tmp_diff.dwg")
    acadDoc.SaveAs tempPath
    
    ' 3. DWGCOMPAREコマンドの実行
    ' SendCommandは非同期的に動作する場合があるため、DoEventsによる制御が不可欠
    Debug.Print "Executing DWGCOMPARE..."
    
    ' コマンドライン引数: DWGCOMPARE [比較対象ファイル]
    ' 注意: コマンドの入力には末尾にスペースが必要
    acadDoc.SendCommand "DWGCOMPARE " & Chr(34) & backupPath & Chr(34) & " "
    
    ' UIの応答を待機(実務上は、比較ダイアログの制御が困難なため、
    ' ここでは「比較図面が生成される」前提のワークフローを構築する)
    DoEvents
    
    ' 4. 差分図面の特定と保存
    ' AutoCADのDWGCOMPAREは、比較結果を新しい図面として開く。
    ' そのアクティブな図面を「監査用」として別保存する。
    Dim diffDoc As Object
    Set diffDoc = ThisDrawing ' 比較によってアクティブになった図面を捕捉
    
    diffReportPath = Replace(currentPath, ".dwg", "_" & Format(Now, "YYYYMMDD_HHMMSS") & DIFF_EXT)
    
    ' 差分図面を保存(メモリ解放を意識した実装)
    diffDoc.SaveAs diffReportPath
    Debug.Print "Audit report generated: " & diffReportPath
    
    ' 5. クリーンアップと本保存
    ' 一時ファイルの削除(OSのI/O完了を待つため、エラーを無視して試行)
    On Error Resume Next
    Kill tempPath
    On Error GoTo ErrorHandler
    
    ' 本来の保存を実行
    acadDoc.Save
    
    MsgBox "Secure Save Completed. Audit trail created.", vbInformation
    
CleanUp:
    Set diffDoc = Nothing
    Exit Sub

ErrorHandler:
    MsgBox "Critical Error during Secure Save: " & Err.Description, vbCritical
    ' システムの整合性を守るため、中途半端な状態での終了を避ける
    Resume CleanUp
End Sub

4. 伝説的な知見:パフォーマンスと安定性の極意

このコードを実務環境へデプロイする際、シニアエンジニアが考慮すべき「重み」が3点ある。

I. オブジェクトのライフサイクル管理

VBAはガベージコレクションが脆弱である。特に`acadDoc.SendCommand`を実行した後、AutoCADの内部状態(ドキュメントのフォーカス)が変化する。比較によって開かれた新しい図面(`diffDoc`)を、明示的に`Set diffDoc = Nothing`で解放しない限り、メモリ上に浮遊するゾンビオブジェクトとなり、長時間の稼働でAutoCADのクラッシュを引き起こす。

II. 非同期実行への対策

`SendCommand`は、AutoCADのコマンドラインに文字列を流し込むだけの「投げっぱなし」の処理だ。コマンドが完了する前に次のVBA行が実行されると、ファイルアクセス競合(Access Violation)が発生する。大規模な図面の場合、`DoEvents`をループ内で回すか、あるいはWindows APIの`Sleep`を用いて、I/Oの猶予を与える設計が不可欠である。

III. レガシー環境との互換性

`DWGCOMPARE`機能は、AutoCADのバージョンによって挙動が微妙に異なる。特に、古いバージョンのDWG形式を扱う場合、比較エンジンが内部的に変換を行うため、追加のメモリ消費が発生する。システム管理者は、この自動化スクリプトが「どのバージョンのDWG形式をターゲットにしているか」を常に監視し、メモリ閾値を超えないよう監視すべきである。

結論

「保存」を単なるデータ書き込みと捉えるか、それとも「設計変更の承認プロセス」と捉えるか。その差が、エンジニアリングの品質を決定づける。

今回提示した、APIによるファイル検証、シャドウ・セーブ、そして明示的なオブジェクト解放を組み合わせたワークフローは、レガシーなVBA環境においても、極めて堅牢な監査システムを構築するための礎となるだろう。

コードは書くものではない。設計(Design)するものだ。

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