はじめに:なぜ「図面の一括PDF化」で現場のエンジニアは絶望するのか
「100枚のDWGをPDFに変換してくれ」
……この頼みを受けた瞬間、冷や汗をかいた経験はないだろうか。手動で1枚ずつ開いては `Ctrl + P`(または `PLOT` コマンド)を叩き、印刷スタイル(CTB/STB)を確認し、PDFドライバを選んで保存する。1枚に30秒かかるとしたら、100枚で50分。もし図面のレイアウト構成がバラバラだったら、発狂ものの一日仕事になる。
業務効率化の旗手である我々AutoCAD VBAエンジニアが、こんな非人道的な作業を許すわけにはいかない。
しかし、ここで安易なコードを書くと、さらに深い地獄に落ちることになる。
「AutoCADの標準VBAで印刷を自動化しようとしたが、ダイアログがポップアップして処理が止まる」「なぜか一部の図面だけ用紙サイズが勝手に変わる」「マルチプロセスで爆速にしようとしたらAutoCADのCOMサーバーがクラッシュした」――これらは実務の現場で毎日のように起る悲劇だ。
今回は、数々の修羅場を潜り抜けてきた私が、「対話型ダイアログの完全バイパス」「レイアウトの確実な走査」「エラー耐性の高いドキュメントライフサイクル管理」を網羅した、実務投入可能なプロダクションコードを授けよう。
—
1. 堅牢なPDF一括エクスポート設計の3大原則
実務で動く自動化ツールと、チュートリアル用の「動くだけの玩具」の決定的な違いは、「例外への耐性」と「環境依存性の排除」にある。設計において死守すべき3原則を解説する。
原則①: `BACKGROUNDPLOT` とダイアログの完全無効化
AutoCADの印刷処理で最も厄介なのは、エラーや警告が起きたときにUIダイアログが表示され、VBAの実行が無限にフリーズする現象だ。これを防ぐため、コードの実行前には必ずシステム変数 `BACKGROUNDPLOT` を制御し、さらにプロット設定で「ダイアログを表示しない(PlotToDevice)」を徹底する。
原則②: 複数レイアウト(Model / Layout)の厳密な識別
「図面」と言ったとき、それはModel空間を指すとは限らない。実務図面では、複数の図面枠(Layout)が同居していることが多い。「モデル空間だけPDFにするのか」「すべてのレイアウトを1ファイルずつ、あるいは単一ファイルにまとめるのか」をコード側で制御できなければ、実用に耐えない。今回は「各レイアウトごとに個別のPDFを出力する」最も汎用性の高いアプローチをとる。
原則③: ドキュメントの適切なライフサイクル管理
複数図面をループ処理する際、最もやりがちなバグが「メモリリークとアクティブドキュメントのロスト」だ。`Documents.Open` で開いた図面は、処理が終わったら必ず `Close False`(変更を保存せずに閉じる)でメモリから解放しなければならない。これを怠ると、数枚処理しただけでAutoCADがフリーズする。
—
2. プロダクションコード:実務仕様・PDF一括エクスポートモジュール
以下のコードは、指定したフォルダ内のすべてのDWGファイルを読み込み、指定したPDFプリンタ(例: “DWG To PDF.pc3″)と印刷スタイルを使用して、一括でPDFを出力するマクロだ。
標準モジュールに貼り付けて実行してほしい。
Option Explicit
‘ —————————————————————–
‘ 担当者必携:DWG図面一括PDFエクスポートエンジン
‘ —————————————————————–
Public Sub BatchExportToPDF()
Dim targetFolder As String
Dim outputFolder As String
Dim fso As Object
Dim fldrDialog As Object
‘ 1. 対象フォルダの選択(UIでの安全なパス取得)
targetFolder = GetFolderPath(“変換するDWGファイルが格納されているフォルダを選択してください”)
If targetFolder = “” Then Exit Sub
‘ 2. 出力先フォルダの選択
outputFolder = GetFolderPath(“PDFの出力先フォルダを選択してください”)
If outputFolder = “” Then Exit Sub
‘ 3. ファイルシステムオブジェクトの生成
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 4. AutoCAD環境の最適化(警告やダイアログの抑制)
Dim originalCanvasMode As Integer
originalCanvasMode = ThisDrawing.GetVariable(“BACKGROUNDPLOT”)
ThisDrawing.SetVariable “BACKGROUNDPLOT”, 0 ‘ バックグラウンドプロットを無効化し、同期処理で確実にエラーをキャッチ
On Error GoTo ErrorHandler
Dim file As Object
Dim dwgCount As Long
dwgCount = 0
‘ 5. フォルダ内のDWGファイルを走査
For Each file In fso.GetFolder(targetFolder).Files
If LCase(fso.GetExtensionName(file.Name)) = “dwg” Then
ProcessSingleDrawing file.Path, outputFolder, fso
dwgCount = dwgCount + 1
End If
Next file
‘ 6. 後処理
ThisDrawing.SetVariable “BACKGROUNDPLOT”, originalCanvasMode
MsgBox “処理が完了しました。” & vbCrLf & “処理ファイル数: ” & dwgCount & ” 件”, vbInformation, “一括PDFエクスポート”
Exit Sub
ErrorHandler:
‘ 異常終了時も必ずシステム変数を復元する
ThisDrawing.SetVariable “BACKGROUNDPLOT”, originalCanvasMode
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ —————————————————————–
‘ 単一図面のオープン・レイアウト走査・PDFパブリッシュ処理
‘ —————————————————————–
Private Sub ProcessSingleDrawing(ByVal dwgPath As String, ByVal outputFolder As String, ByRef fso As Object)
Dim targetDoc As Document
Dim layout As Layout
Dim plotConfig As AcadPlot
Dim baseName As String
Dim pdfPath As String
Dim originalTab As String
‘ 読み取り専用(ReadOnly:=True)で開くことで、元の図面への予期せぬ変更やロックを防ぐ
Set targetDoc = Application.Documents.Open(dwgPath, True)
baseName = fso.GetBaseName(dwgPath)
‘ アクティブドキュメントを一時的に切り替え
Application.ActiveDocument = targetDoc
Set plotConfig = targetDoc.Plot
‘ 図面内のすべてのレイアウト(Model空間含む)をループ
For Each layout in targetDoc.Layouts
‘ 「Model」または「レイアウト」タブが存在するかチェック
If layout.ModelSpace = True Then
‘ 必要に応じてモデル空間の出力をスキップする場合はここで判定
‘ 例: If layout.Name <> “Model” Then …
End If
‘ 出力ファイル名の組み立て (図面名_レイアウト名.pdf)
‘ ※ファイル名に使えない文字が含まれる場合の置換処理を入れておくとさらに堅牢
pdfPath = outputFolder & “\” & baseName & “_” & layout.Name & “.pdf”
‘ レイアウトを用紙サイズやスタイルのターゲットに設定
targetDoc.ActiveLayout = layout
‘ 印刷設定の適用(必要に応じてここでPlotDeviceやCanonicalMediaNameを動的変更可能)
‘ ※あらかじめレイアウト側に「DWG To PDF.pc3」等のページ設定が保存されている前提が最も安定します
‘ プロット実行(PlotToDeviceメソッド)
‘ 引数: 印刷デバイス名(PC3ファイル名など。レイアウト設定に従う場合は空欄または設定済みデバイス利用)
On Error Resume Next
plotConfig.PlotToDevice “DWG To PDF.pc3”
If Err.Number <> 0 Then
Debug.Print “エラー: ” & baseName & ” (” & layout.Name & “) の印刷に失敗しました – ” & Err.Description
Err.Clear
End If
On Error GoTo 0
Next layout
‘ 変更を保存せずにドキュメントを閉じる(メモリリーク防止の肝)
targetDoc.Close False
End Sub
‘ —————————————————————–
‘ フォルダ選択ダイアログを表示するヘルパー関数
‘ —————————————————————–
Private Function GetFolderPath(ByVal prompt As String) As String
Dim shellApp As Object
Dim browsedFolder As Object
Set shellApp = CreateObject(“Shell.Application”)
Set browsedFolder = shellApp.BrowseForFolder(0, prompt, &H10, &H0) ‘ &H10 = BIF_RETURNONLYFSDIRS
If Not browsedFolder Is Nothing Then
GetFolderPath = browsedFolder.Self.Path
Else
GetFolderPath = “”
End If
End Function
—
3. チーフアーキテクトが教える:現場でハマる「3つの罠」と対策
このコードをそのまま現場に投入しても動くはずだが、実務の図面データは一筋縄ではいかない。よくあるトラブルと、その回避策を伝授しよう。
トラブル①:PDFのファイル名が図面名になってしまい、複数レイアウトで上書きされる
上記のコードでは `baseName & “_” & layout.Name & “.pdf”` としているため回避しているが、もしAutoCAD標準の「PDFの自動名前付け機能」や古いPC3の設定に依存していると、レイアウトが変わっても同じファイル名で上書きされ、最後の一枚しか残らない現象が起きる。
対策: 出力ファイル名は必ずVBA側で完全に制御し、フルパスで組み立ててプロッタへ渡すこと。
トラブル②:レイアウトごとの「ページ設定」がバラバラで縮尺が狂う
VBAから `PlotToDevice` を叩く際、最も安全なのは「あらかじめDWG側の各レイアウトに対して、正しいページ設定(Page Setup)とPC3(例: DWG To PDF.pc3)、用紙サイズ、テーブルスタイル(CTB)を保存しておくこと」だ。
VBAコード内で無理に用紙サイズやペン割り当てを動的にコード書こうとすると、AutoCADのバージョン差異(2021と2024でのメディア名の微妙な違いなど)で痛い目を見る。「図面のレイアウト設定はCADオペレーターが整え、VBAはそれをただ『印刷実行』するトリガーに徹する」という役割分担が、最もバグを生みません。
トラブル③:巨大図面で「COMサーバーが応答しません」エラー
数十メガバイトある重厚長大な意匠図や設備図をループで開閉すると、AutoCADのガベージコレクションが追いつかなくなり、Automationエラーが発生することがある。
対策: 大量ファイル(100ファイル以上)を処理する場合は、コードのループ内に `DoEvents` を挟むか、あるいは50ファイルごとに一度AutoCADを完全に再起動するようなバッチ分割設計を取り入れると、極めて安定した稼働を実現できる。
—
おわりに:自動化の本質は「エンジニアの自由時間の創出」にある
今回提供したコードは、単なる「手作業の代行」ではない。
膨大な図面を前に絶望していた若手エンジニアをその苦行から解放し、本来向き合うべき「設計の品質向上」や「より高度な業務プロセスの構築」へとリソースをシフトさせるための戦略的武器である。
AutoCAD VBAは、レガシーと言われることもある。しかし、図面という重たい資産をダイレクトに、かつローカル環境で高速に料理できるこの技術の優位性は、今なお色褪せない。
ぜひ、あなたの現場にこのエンジンを組み込み、圧倒的な効率化を成し遂げてほしい。健闘を祈る。
