AutoCADを起動するな:バイナリ解析によるDWGバージョン判定の極致
業務自動化の現場において、多くの開発者が陥る「致命的なアンチパターン」がある。それは、「単にファイルの情報を知りたいだけなのに、AutoCADのインスタンスを立ち上げてファイルを開く」という行為だ。
数千、数万という図面ファイルをスキャンし、バージョンごとに処理を分岐させるツールを設計する場合、この設計ミスはパフォーマンスの致命的な低下を招くだけでなく、メモリリーク、AutoCADのプロセス残留、そして予期せぬクラッシュという、地獄のような運用コストを現場に強いることになる。
プロフェッショナルなアーキテクトであれば、目的と手段を峻別せよ。図面のバージョン判定に、重厚なAutoCAD COMオブジェクトなど必要ない。必要なのは、ファイルの先頭数バイトを読み取る、極めて軽量なバイナリファイル操作だけだ。
本稿では、AutoCADを一切起動せずに、DWGファイルのヘッダー情報を直接解析し、超高速かつ堅牢にバージョンを特定する手法を伝授する。
1. 核心的知見:DWGヘッダーの構造
DWGファイルはバイナリ形式であり、そのファイル構造の冒頭(Magic Numberと呼ばれる領域)には、必ずそのファイルがどのAutoCADバージョンで作成されたかを示す識別コードが刻印されている。
具体的には、ファイルの先頭6バイトに `AC10xx` という形式の文字列が存在する。
| ヘッダーコード | AutoCAD バージョン |
|---|---|
| `AC1015` | AutoCAD 2000 |
| `AC1018` | AutoCAD 2004 |
| `AC1021` | AutoCAD 2007 |
| `AC1024` | AutoCAD 2010 |
| `AC1027` | AutoCAD 2013 |
| `AC1032` | AutoCAD 2018 |
この「6バイト」さえ読み取れば、図面の内容を一切ロードすることなく、そのファイルが「現在のシステムで開けるものか」「変換が必要な古いものか」をミリ秒単位で判定できる。
2. 設計指針:堅牢なツールを作るために
単なる「コードの書き写し」で終わらせないために、以下の3点を設計原則として組み込む。
1. リソースの厳格な管理: `Open` ステートメントを使用する場合、エラーが発生しても必ず `Close` が呼ばれる構造(エラーハンドリング)を徹底する。ファイルハンドルをリークさせることは、自動化ツールにおける死を意味する。
2. IOオーバーヘッドの最小化: ファイル全体を読み込むような愚行は避け、必要な先頭数バイトのみをピンポイントで取得する。
3. 例外への耐性: ファイルが存在しない、アクセス権限がない、あるいはDWGではないファイル(壊れたファイル)を読み込んだ場合に、アプリケーション全体が停止しないよう、例外を適切にキャッチする。
3. 実装:プロダクション・クオリティのVBAコード
以下に、そのまま実務に投入可能なレベルのモジュールを示す。このコードは、AutoCADの参照設定すら不要である。純粋なVBA(ExcelやAccess等)から動作する。
Option Explicit
'==============================================================================
' Module: dwg_analyzer
' Description: DWGファイルのバイナリヘッダーを解析し、バージョンを判定する
' Author: Legendary Chief Architect
'==============================================================================
''' <summary>
''' 指定されたDWGファイルのバージョンヘッダー(AC10xx)を取得する
''' </summary>
''' <param name="filePath">対象ファイルのフルパス</param>
''' <returns>ヘッダー文字列(例: "AC1032")。取得失敗時は空文字</returns>
Public Function GetDWGHeader(ByVal filePath As String) As String
Dim fileNum As Integer
Dim headerBuffer As String
Dim bufferSize As Integer: bufferSize = 6 ' AC10xx の長さ
' 1. ファイルの存在確認
If Dir(filePath) = "" Then
Debug.Print "Error: File not found -> " & filePath
GetDWGHeader = ""
Exit Function
End If
On Error GoTo ErrorHandler
' 2. バイナリモードでファイルを開く
' Access Read を指定することで、他のプロセスが書き込み中でも読み取りを試みる
fileNum = FreeFile
Open filePath For Binary Access Read As #fileNum
' 3. 先頭6バイトを読み込む
' Getステートメントを使用して、指定位置からバイナリデータを直接取得
headerBuffer = Space$(bufferSize)
Get #fileNum, 1, headerBuffer
' 4. ファイルを即座に閉じる(リソース解放の鉄則)
Close #fileNum
' 5. 結果を返す
GetDWGHeader = UCase(Trim(headerBuffer))
Exit Function
ErrorHandler:
' エラー発生時も必ずファイルを閉じる
If fileNum > 0 Then Close #fileNum
Debug.Print "Error: Failed to read header for " & filePath & " - " & Err.Description
GetDWGHeader = ""
End Function
''' <summary>
''' ヘッダーコードから人間が理解可能なバージョン名を返す
''' </summary>
Public Function MapHeaderToVersion(ByVal header As String) As String
Select Case header
Case "AC1015": MapHeaderToVersion = "AutoCAD 2000"
Case "AC1018": MapHeaderToVersion = "AutoCAD 2004"
Case "AC1021": MapHeaderToVersion = "AutoCAD 2007"
Case "AC1024": MapHeaderToVersion = "AutoCAD 2010"
Case "AC1027": MapHeaderToVersion = "AutoCAD 2013"
Case "AC1032": MapHeaderToVersion = "AutoCAD 2018"
Case Else: MapHeaderToVersion = "Unknown (" & header & ")"
End Select
End Function
''' <summary>
''' 実装テスト用メインルーチン
''' </summary>
Public Sub TestDWGAnalysis()
Dim targetFile As String
Dim header As String
Dim version As String
' テスト対象のパスを指定
targetFile = "C:\Temp\test_drawing.dwg"
' 実行
header = GetDWGHeader(targetFile)
If header <> "" Then
version = MapHeaderToVersion(header)
Debug.Print "--- Analysis Result ---"
Debug.Print "File: " & targetFile
Debug.Print "Header: " & header
Debug.Print "Version: " & version
Debug.Print "-----------------------"
Else
Debug.Print "Analysis failed. Check file path or format."
End If
End Sub
4. 実務におけるデータベース・連携の注意点
この手法を大規模なシステム(例えば、図面管理サーバーのインデックス作成など)に組み込む場合、以下の設計的配慮が求められる。
データベースへの格納
解析結果をSQL ServerやAccessなどのデータベースに保存する場合、`AC10xx` という生の値(Raw Header)と、`AutoCAD 2018` という表示用名称(Mapped Name)の両方を保持することを強く推奨する。
理由は、将来的に新しいAutoCADバージョンが登場した際、マッピングロジックを更新するだけで済み、過去のデータ(Raw Header)を再定義できるからだ。
ファイルロックの回避
`Open … For Binary Access Read` を使用している点に注目してほしい。`Access Read` を明示することで、他のユーザーがその図面をAutoCADで開いて編集中であっても、共有モードでの読み取りが可能になる。これは、複数人が稼働するサーバー環境での自動化において、極めて重要なテクニックである。
パフォーマンスの比較
- 手法A (AutoCAD API使用): 起動 5〜10秒 + ファイルロード 1〜3秒 = 約10秒/ファイル
- 手法B (本手法: バイナリ解析): ファイルオープン 0.001秒 = 約0.001秒/ファイル
1,000個のファイルを処理する場合、手法Aでは約3時間かかるが、手法Bなら数秒で終わる。この差が、エンジニアとしての「設計力の差」である。
結論
AutoCAD VBAの真価は、AutoCADを操作することだけにあるのではない。「AutoCADに仕事をさせずに、AutoCADの情報をいかに効率よく抜き出すか」。この逆転の発想こそが、世界最高峰の自動化エンジニアへの入り口である。
バイナリを恐れるな。構造を理解せよ。それが、堅牢で高速なシステムを構築するための唯一の道である。
