【実務中級】AutoCAD VBAで図面内の全レイアウトを検索し、ページ設定(Page Setup)を自動適用・変更する
AutoCADの実務において、数十から数百におよぶペーパー空間のレイアウト(Layout)に対して、手動で「ページ設定(Page Setup)」を適用していく作業ほど、非生産的でミスの温床になるものはありません。
「印刷デバイスをPDF出力に変更し、用紙サイズをA1からA3に縮小、さらに図面枠に合わせて『オブジェクト範囲』で1:1出力する」
このような定型処理は、VBAによる自動化の格好の標的です。しかし、ネット上に転がっている「動くだけ」のサンプルコードをそのまま実務に投入すると、高確率で実行時エラーを引き起こし、最悪の場合は図面データを破損させます。
本記事では、AutoCAD VBAのオブジェクトモデルを深く理解し、「絶対に止まらない、極めて堅牢なページ設定自動適用ツール」を開発するための設計思想と、そのままプロダクション環境に投入できる高品質なコードを提示します。
—
1. なぜあなたのコードは実務で落ちるのか? 3つの致命的な「罠」
レイアウトのループ処理とページ設定の適用には、AutoCAD APIの仕様に根ざしたいくつかのトラップが存在します。これらを無視してコードを組むことは、時限爆弾を抱えることと同義です。
罠①:`Layouts` コレクションには「モデル空間」が含まれている
AutoCADの `ThisDrawing.Layouts` コレクションを単純に `For Each` で回すと、ペーパー空間のレイアウトだけでなく、モデル空間(Model Space)も1つの要素として取得されてしまいます。
モデル空間に対してペーパー空間専用のページ設定(特定の用紙サイズやレイアウト印刷設定など)を適用しようとすると、APIは即座に実行時エラーを吐いて沈黙します。
罠②:`CopyFrom` メソッドの挙動と不完全な初期化
ページ設定の複製には、`Layout.CopyFrom(PlotConfiguration)` メソッドを使用するのが最もクリーンです。しかし、適用元となる `PlotConfiguration`(ページ設定)オブジェクトが正しく初期化されていない、あるいは図面内に存在しない名前を指定した場合、プログラムはクラッシュします。
さらに、適用先のレイアウトが「一度もアクティブ(表示)にされたことがない未初期化状態」である場合、一部のプロパティが正しく更新されない現象が発生します。
罠③:プリンタドライバ(PC3/System Printer)の環境依存
コード内で「”DWG To PDF.pc3″」などのプリンタ名をハードコーディングしている場合、そのPC3ファイルが実行環境の検索パスに存在しない、あるいはドライバのバージョンが異なると、設定適用時に「無効なインプット」としてエラーになります。
—
2. 堅牢な設計(アーキテクチャ)
これらの罠を回避するために、本ツールでは以下の設計思想を採用します。
[メイン処理: ApplyPageSetupToAllLayouts]
│
├── ① カレント図面内の「モデル空間」を確実にスキップ (ModelType プロパティの判定)
│
├── ② 指定された「ページ設定名」が図面内に存在するか検索
│ └── 存在しない場合:
│ 動的に一時的な「PlotConfiguration」を生成し、
│ 安全なデフォルト値(例: Microsoft Print to PDF, A4)を割り当てて適用
│
├── ③ レイアウトの安全なアップデート
│ └── CopyFrom 適用後、各レイアウトの Plot プロパティを強制再生成
│
└── ④ エラーハンドリングとユーザーへの進捗レポート
特に重要なのが、`Layout.ModelType` プロパティによる判定です。名前(`Layout.Name = “Model”`)で判定するローカルな実装は避けてください。言語設定(英語版のAutoCADなど)やユーザーのカスタマイズによって、モデル空間の内部名が異なるリスクを排除するため、必ずオブジェクトのプロパティ(属性)で論理的に判定します。
—
3. プロダクションコード:全レイアウトへのページ設定自動適用
以下のコードは、エラーハンドリング、モデル空間の除外、存在しないページ設定の動的生成、および進捗の可視化を網羅した、実務にそのまま耐えうる実装です。
VBAエディタ(VBE)の標準モジュールに貼り付けて実行してください。
Option Explicit
”’
”’
Public Sub ApplyPageSetupToAllLayouts()
On Error GoTo ErrorHandler
Dim doc As AcadDocument
Set doc = ThisDrawing
‘ — 【設定値】適用したいページ設定の名前を指定 —
Const TARGET_SETUP_NAME As String = “A3_PDF_Output”
Dim plotConfigs As AcadPlotConfigurations
Set plotConfigs = doc.PlotConfigurations
Dim targetConfig As AcadPlotConfiguration
Set targetConfig = FindOrCreatePlotConfiguration(doc, TARGET_SETUP_NAME)
If targetConfig Is Nothing Then
MsgBox “ページ設定の取得または作成に失敗しました。処理を中止します。”, vbCritical, “エラー”
Exit Sub
End If
‘ パフォーマンス向上のため、画面更新と再描画を一時的に抑制
Dim originalRegenMode As Integer
originalRegenMode = doc.GetVariable(“REGENMODE”)
doc.SetVariable “REGENMODE”, 0
Dim lay As AcadLayout
Dim processedCount As Long
processedCount = 0
Debug.Print “=== ページ設定適用処理 開始 ===”
‘ 全レイアウトをループ走査
For Each lay In doc.Layouts
‘ 【防壁1】モデル空間を確実に除外する
If Not lay.ModelType Then
Debug.Print “処理中レイアウト: ” & lay.Name
‘ 【防壁2】ページ設定をレイアウトにディープコピー
‘ CopyFromは、PlotConfigurationのすべての印刷設定を対象レイアウトに複製する
lay.CopyFrom targetConfig
‘ レイアウトの設定変更を確定させるためにRefreshPlotSettingsを呼ぶ
lay.RefreshPlotSettings
processedCount = processedCount + 1
End If
Next lay
‘ 描画設定を元に戻し、図面全体を再ロード
doc.SetVariable “REGENMODE”, originalRegenMode
doc.Regen acAllViewports
MsgBox “処理が完了しました。” & vbCrLf & _
“適用対象レイアウト数: ” & processedCount & ” 件” & vbCrLf & _
“適用設定名: ” & TARGET_SETUP_NAME, vbInformation, “完了”
Exit Sub
ErrorHandler:
‘ 万が一エラーが発生した場合も、システム変数を安全に復帰させる
On Error Resume Next
If Not doc Is Nothing Then
doc.SetVariable “REGENMODE”, 1
doc.Regen acAllViewports
End If
MsgBox “致命的なエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”
End Sub
”’
”’ 存在しない場合は、標準的な設定(Microsoft Print to PDF / A4)で新規作成する。
”’
Private Function FindOrCreatePlotConfiguration(ByRef doc As AcadDocument, ByVal configName As String) As AcadPlotConfiguration
On Error GoTo ErrorHandler
Dim plotConfigs As AcadPlotConfigurations
Set plotConfigs = doc.PlotConfigurations
Dim config As AcadPlotConfiguration
‘ 既存のページ設定を検索
For Each config In plotConfigs
If StrComp(config.Name, configName, vbTextCompare) = 0 Then
Set FindOrCreatePlotConfiguration = config
Exit Function
End If
Next config
‘ — 存在しない場合、フォールバックとして新規作成 —
Debug.Print “警告: 指定されたページ設定 ‘” & configName & “‘ が見つかりません。新規作成します。”
‘ モデル空間用ではなく、ペーパー空間用(False)として作成
Set config = plotConfigs.Add(configName, False)
‘ ————————————————————————-
‘ 【重要】環境に依存しない標準的なシステムプリンタと用紙サイズを割り当てる
‘ 実務に合わせて、”DWG To PDF.pc3″ や社内標準プロッターに変更してください。
‘ ————————————————————————-
config.ConfigName = “Microsoft Print to PDF” ‘ プリンタ名(またはPC3ファイル名)
config.CanonicalMediaName = “ISO_A4_(210.00_x_297.00_MM)” ‘ 用紙サイズ(内部名)
‘ 印刷領域を「レイアウト」に設定
config.PlotType = acLayout
‘ 印刷尺度は「1:1」
config.UseStandardScale = True
config.StandardScale = ac1_1
‘ 印刷スタイルの適用(必要に応じて monochrome.ctb などに設定)
config.StyleSheet = “monochrome.ctb”
‘ 変更を反映
config.RefreshPlotSettings
Set FindOrCreatePlotConfiguration = config
Exit Function
ErrorHandler:
Set FindOrCreatePlotConfiguration = Nothing
Debug.Print “FindOrCreatePlotConfiguration 内でエラー: ” & Err.Description
End Function
—
4. コードの徹底解説:プロの設計思想を解剖する
実務で破綻しないコードにするため、上記のソースコードに組み込んだ高度な設計思想を解説します。
① `ModelType` プロパティによる厳密な境界線
If Not lay.ModelType Then
多くの開発者が `If lay.Name <> “Model”` という文字列比較を行いますが、これは悪手です。
AutoCADのローカライズ版や、ユーザーがカスタマイズした環境では、モデル空間の名前が変更されている(あるいは内部的に別名で保持されている)可能性があります。
`ModelType` プロパティは、そのレイアウトが「モデル空間」である場合に `True` を返すブール値です。これを使用することで、環境に左右されない完璧なフィルタリングが実現します。
② `CopyFrom` メソッドによる設定の「一括注入」
レイアウトごとのプリンタ名、用紙サイズ、尺度などをループ内で一つずつプロパティに代入していくコードをよく見かけますが、これは極めて非効率です。
AutoCAD APIには、ページ設定オブジェクト(`AcadPlotConfiguration`)から設定を丸ごとコピーする `CopyFrom` メソッドが用意されています。
これにより、「設定の定義」と「適用処理」が完全に分離(疎結合化)され、コードの保守性が劇的に向上します。
③ サイレント・フォールバック(動的生成)
指定されたページ設定が図面内に存在しないからといって、即座にエラー終了させてはいけません。
本コードに実装されている `FindOrCreatePlotConfiguration` 関数は、指定された設定名が見つからない場合、自動的に図面内にその名前の `PlotConfiguration` を作成し、デフォルトの印刷パラメータ(例: `Microsoft Print to PDF`)を割り当てて処理を続行させます。
これにより、「テンプレートを入れ忘れた図面」に対しても、システムを落とさずに安全に処理を完了させることができます。
—
5. さらに実務で差がつくアドバンスド・ノウハウ
実用化に向けて、さらに一歩踏み込んだチューニングポイントを伝授します。
CanonicalMediaName(用紙サイズ)の取得方法
コード内で指定している `”ISO_A4_(210.00_x_297.00_MM)”` は、AutoCADが内部的に保持している用紙サイズ名(ローカライズされない一意の名前)です。
画面上の表記「A4」などをそのまま代入するとエラーになります。
使用可能な用紙サイズの内部名リストを取得したい場合は、以下のコードを実行してイミディエイトウィンドウに出力させて確認してください。
‘ 使用可能な用紙サイズ一覧をデバッグ出力するコード片
Dim mediaList As Variant
mediaList = targetConfig.GetCanonicalMediaNames()
Dim i As Long
For i = LBound(mediaList) To UBound(mediaList)
Debug.Print mediaList(i)
Next i
外部図面(複数DWG)への一括バッチ適用への拡張
もし「フォルダ内にある100個のDWGファイルすべてにこの処理を適用したい」という要件がある場合、VBAから ObjectDBX 技術(`AxDbDocument`)を使用することを検討します。
ObjectDBXを使用すれば、AutoCADの画面上で図面を「開く・閉じる」という重い描画処理を完全にバイパスし、バックグラウンドで高速にレイアウト設定を書き換えることが可能です。
ただし、ObjectDBX上では `Regen` や一部の Plot 関連APIに制限があるため、その場合はファイルを `Open` メソッドで最小化(あるいは非表示)状態で開き、本記事のコードを回して `Save` するというハイブリッドなバッチ処理を構築するのが実務上最も安定します。
—
6. まとめ
AutoCAD VBAにおけるレイアウト操作は、一見シンプルですが、モデル空間の除外やデバイス依存の回避など、実務ならではの「泥臭い考慮」が不可欠な領域です。
本記事で紹介した、
- `ModelType` による安全なフィルタリング
- `CopyFrom` による設定の一括適用
- 存在しない設定に対する動的なフォールバック生成
これらのアプローチを取り入れることで、あなたの作成するツールは単なる「マクロ」から、現場の誰もが安心して使える「エンタープライズ製品」へと昇華します。ぜひ、日々の業務効率化ツール開発に役立ててください。
