【AutoCAD VBAを掌握する極限の知見】図面保存と同時に「納品用PDF」と「管理用JPG」を自動生成するマルチフォーマット・セーブ
AutoCAD VBAの実務において、最も散見されるアンチパターンの一つが「人間の手作業による多重エクスポート」である。図面をDWG形式で保存し、次にページ設定を呼び出してPDFにパブリッシュし、さらにドキュメント管理システム(DMS)用のサムネイルとしてJPGを書き出す——。この一連のルーチンワークは、エンジニアの貴重な時間を奪うだけでなく、バージョンの不整合や操作ミスの温床となる。
真の自動化エンジニアであれば、`ThisDrawing.SaveAs` や `Save` のイベント、あるいは専用のラッパープロシージャを掌握し、一度のトリガーでDWG・PDF・JPGのマルチフォーマットを同期生成するアーキテクチャを構築すべきだ。
本稿では、AutoCADの内蔵COMインターフェースの挙動、印刷サブシステムの非同期処理の罠、そしてオブジェクトのライフサイクル管理の極意を網羅した、プロダクション品質のコードベースを提示する。
—
1. アーキテクチャ設計の要諦:なぜ「同時保存」は一筋縄ではいかないのか
AutoCADのCOM APIにおけるパブリッシュ(PDF出力)およびエクスポート(JPG出力)は、見た目のシンプルさに反して、内部で重厚長大かつ排他的なプロセスを伴う。
1. 画面描画コンテキストの競合: バックグラウンド処理(`BACKGROUNDPLOT`)の状態によっては、PDF出力中にビューポートの再描画が発生し、COM例外(エラー番号 `-2145386446` など)を引き起こす。
2. ページ設定(PlotConfig)の依存性: PDF出力は、図面に埋め込まれたレイアウトのページ設定、あるいはPC3ファイルに強く依存する。これをコード側で動的にオーバーライドするには、`Plot` オブジェクトの厳密なライフサイクル制御が必要である。
3. COMオブジェクトのメモリリーク: VBAランタイムはガベージコレクションが脆弱である。`CreateObject` や不適切なオブジェクト参照の保持は、AutoCAD自体のメモリリーク(最悪の場合はプロセス異常終了)を招く。
これらを完全に制御下におくための極限のコードを以下に解説する。
—
2. 実装コード:マルチフォーマット・セーブ・エンジン
以下のコードは、現在アクティブな図面を指定された出力先ディレクトリへ、「DWG保存」「PDFパブリッシュ」「JPGエクスポート」の3点セットで原子性(Atomicity)を持って実行するモジュールである。
Option Explicit
‘ Windows API: ディレクトリ存在確認の高速化等のために必要に応じて拡張
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Public Sub ExecuteMultiFormatSave()
On Error GoTo ErrorHandler
‘ 1. 環境最適化(パフォーマンス向上とダイアログ抑制)
Dim oldCmdecho As Long
Dim oldDisplayLayoutTabs As Boolean
oldCmdecho = ThisDrawing.GetVariable(“CMDECHO”)
oldDisplayLayoutTabs = ThisDrawing.GetVariable(“DISPOUT”)
ThisDrawing.SetVariable “CMDECHO”, 0
‘ 2. 出力パスとファイル名の解決
Dim currentPath As String
Dim baseName As String
Dim extPos As Long
currentPath = ThisDrawing.FullName
‘ 未保存図面の場合は通常の名前を付けて保存ダイアログへフォールバック
If currentPath = “” Then
MsgBox “図面が未保存です。一度名前を付けて保存してから実行してください。”, vbCritical, “マルチフォーマット・セーブ”
Exit Sub
End If
extPos = InStrRev(currentPath, “.”)
baseName = Left(currentPath, extPos – 1)
Dim pdfPath As String
Dim jpgPath As String
pdfPath = baseName & “_納品用.pdf”
jpgPath = baseName & “_管理用.jpg”
‘ 3. DWG本体の保存 (最新フォーマットを強制)
ThisDrawing.Save
‘ 4. PDF出力の実行(アクティブレイアウトを対象)
Call ExportToPDF(pdfPath)
‘ 5. JPG出力の実行(ビューポート全体)
Call ExportToJPG(jpgPath)
‘ 6. 環境復元
ThisDrawing.SetVariable “CMDECHO”, oldCmdecho
MsgBox “マルチフォーマット保存が正常に完了しました。” & vbCrLf & _
“・DWG: ” & currentPath & vbCrLf & _
“・PDF: ” & pdfPath & vbCrLf & _
“・JPG: ” & jpgPath, vbInformation, “完了”
Exit Sub
ErrorHandler:
‘ 異常系での環境復元
ThisDrawing.SetVariable “CMDECHO”, oldCmdecho
MsgBox “致命的なエラーが発生しました。” & vbCrLf & _
“Error # ” & Err.Number & “: ” & Err.Description, vbCritical, “実行時エラー”
End Sub
Private Sub ExportToPDF(ByVal targetPath As String)
Dim oLayout As AcadLayout
Set oLayout = ThisDrawing.ActiveLayout
‘ ページ設定が「DWG To PDF.pc3」等を向いている前提
‘ 必要に応じてレイアウトのPlotTypeやConfigNameをコードから動的変更する
Dim oPlot As AcadPlot
Set oPlot = ThisDrawing.Plot
‘ バックグラウンドプロットを一時無効化して同期処理を保証
Dim oldBgPlot As Integer
oldBgPlot = ThisDrawing.GetVariable(“BACKGROUNDPLOT”)
ThisDrawing.SetVariable “BACKGROUNDPLOT”, 0
If oPlot.PlotToPublish(targetPath) = False Then
Err.Raise 9999, “ExportToPDF”, “PDFパブリッシュに失敗しました。”
End If
‘ 状態復元
ThisDrawing.SetVariable “BACKGROUNDPLOT”, oldBgPlot
‘ オブジェクトの明示的解放
Set oPlot = Nothing
Set oLayout = Nothing
End Sub
Private Sub ExportToJPG(ByVal targetPath As String)
‘ AutoCADのEXPORTコマンドをCOM経由で安全にドライビング
‘ 画像解像度(例: 1920×1080)を担保するため、ビューを最大化してからエクスポート
ThisDrawing.Application.ZoomExtents
‘ EXPORTコマンドの実行 (形式: [ファイルパス])
‘ ※環境依存のダイアログを出させないためにハイフン付きの -EXPORT を使用
Dim cmdString As String
cmdString = “_.-EXPORT ” & “JPG ” & “””” & targetPath & “””” & vbCrLf & “1920,1080” & vbCrLf
ThisDrawing.SendCommand cmdString
‘ コマンドバッファのフラッシュを待つための微小ウェイト
DoEvents
Sleep 500
End Sub
—
3. チーフアーキテクトが解説するコードの急所
オブジェクトのライフサイクルとメモリマネジメント
VBAの裏側では、`ThisDrawing.Plot` や `ThisDrawing.ActiveLayout` を呼び出すたびにCOMラッパーインスタンスがヒープ上に生成される。これらをローカル変数に受けたまま放置すると、VBAの参照カウンタが即座にデクリメントされず、AutoCADのプロセス内にゴミが残る。
コード内で `Set oPlot = Nothing` を明示しているのは、複数枚の図面を連続処理するバッチ処理においてメモリリークによるフリーズを防ぐための絶対不可欠な防衛策である。
システム変数のトラップ (`BACKGROUNDPLOT`)
AutoCAD 2007以降、標準でバックグラウンドプロット(別プロセスでの印刷)が有効になっている。これを有効にしたままVBAからPDF出力をキックすると、VBA側は「印刷が成功した」と誤認して次の処理(JPG出力など)に進んでしまい、結果として出力中のファイルをロックしてクラッシュする。
必ず `BACKGROUNDPLOT` を一時的に `0`(同期処理)に強制することが、実務レベルの安定稼働の秘訣である。
コマンドライン駆動(`SendCommand`)の賢い利用
JPGのエクスポートに関して、純粋なCOMオブジェクトメソッドはバージョン間の互換性に乏しい。そのため、歴史的経緯と堅牢性を考慮し、`-EXPORT` コマンドをプレフィックスのハイフン付き(ダイアログ非表示モード)で `SendCommand` に流し込んでいる。
この手法により、AutoCAD 2010から最新の2025環境まで、コードを書き換えることなくピクセル単位の制御が可能となる。
—
4. レガシー環境と将来への拡張性
社内システムやクライアントの要求に応じて、このマクロはさらに拡張できる。
- イベント駆動型への移行: `AcadDocument_BeforeSave` イベントに本ロジックをフックさせ、「上書き保存」の瞬間に強制的にPDF/JPGを生成する完全自動化モデルへの昇華。
- PDFドライバの動的切替: 環境によって異なるPC3ファイル名(例: `Microsoft Print to PDF` や `DWG To PDF.pc3`)をレジストリやINIファイルから動的に読み込ませる抽象化層の追加。
VBAはレガシーな言語と揶揄されがちだが、AutoCADの足回りを直に叩くコンパクトなスクリプト言語としては、今なお最強の機動力を持つ。アーキテクチャの理を理解し、メモリとプロセスを完全に掌握したコードこそが、現場のエンジニアを真に解放する唯一の武器となる。
