【入門編】【実務中級者向け】図面を開く際のレイアウト・ビューポート状態の自動復元 – AutoCAD VBA解析バイブル

スポンサーリンク

こんにちは!いつも設計実務やCADカスタマイズの効率化、お疲れ様です。優しく知的な先輩エンジニアの「Show」です。

マクロの記録から一歩踏み出し、「自分の手でAutoCADを完全にコントロールしたい」と思い始めたあなたへ。その意気込み、本当に素晴らしいですね!ここをクリアすれば、AutoCAD VBAの基本はバッチリ掴めますよ。

今回のテーマは、実務で絶大な効果を発揮する「図面を開いた際のレイアウト・ビューポート状態の自動復元」です。

「図面を開くたびに、毎回ペーパー空間に切り替えて、特定のビューポートをダブルクリックしてアクティブにして拡大する……」
こんな毎日繰り返す数秒の手間を、VBAの力で完全に自動化してみましょう。AutoCADのオブジェクトモデル(階層構造)の本質を理解しながら、プロとして通用する堅牢なコードを身につけていってくださいね。

—

1. AutoCADの「空間」と「ビューポート」の構造を脳内に描こう

コードを書く前に、まずはAutoCADの内部で「レイアウト」と「ビューポート」がどのように繋がっているか、イメージ図で整理しておきましょう。ここが整理できていないと、VBAコードが迷子になってしまいます。

[ ThisDrawing (アクティブな図面) ]
│
├─ [ Layouts (レイアウトの集合) ]
│ └─ “レイアウト1” や “Model” (ActiveLayout で切り替え)
│
└─ [ ActiveSpace (現在の空間状態) ]
├─ acModelSpace (モデル空間)
└─ acPaperSpace (ペーパー空間)
│
└─ [ MSpace (プロパティ) ]
├─ True : ペーパー空間内のビューポートに入り込んでいる状態
└─ False : ペーパー空間自体を触っている状態

初学者が最も混乱する「2つのビューポート」

AutoCADには、実は2種類のビューポートが存在します。ここを混同しないことが、脱・初心者への最大の関門です。

1. モデル空間のビューポート (`Viewport` オブジェクト)
画面を2分割、4分割してモデリングするためのものです。
2. ペーパー空間のビューポート (`PViewport` オブジェクト)
図枠(ペーパー空間)の中に配置する、モデル空間を覗くための「窓」です。

今回自動制御したいのは、実務で頻出する 2. ペーパー空間のビューポート(フローティング ビューポート) です。

—

2. 【実践コード】レイアウトとビューポートを自動復元するVBAマクロ

それでは、実際のコードを見てみましょう。
このコードは、指定したレイアウト(例: `”Layout1″`)に切り替え、その中にある「特定のビューポート」を自動的にアクティブにし、作業しやすい状態に画面を更新します。

標準モジュールに貼り付けて実行してみてください。

Option Explicit

”’

”’ 指定したレイアウトに切り替え、ターゲットとなるビューポートをアクティブにします。
”’

Public Sub RestoreLayoutAndViewport()
Dim doc As AcadDocument
Set doc = ThisDrawing ‘ 現在アクティブな図面オブジェクトを取得

‘ エラーハンドリング:何らかの理由で処理が失敗してもAutoCADをフリーズさせない
On Error GoTo ErrorHandler

‘ — 設定値(実務に合わせてここを書き換えてください) —
Dim targetLayoutName As String
targetLayoutName = “Layout1” ‘ 復元したいレイアウト名

Dim targetViewportNo As Integer
targetViewportNo = 2 ‘ アクティブにしたいビューポートのインデックス番号 (※1)
‘ ——————————————————

‘ 1. 指定されたレイアウトが存在するかチェックし、切り替える
Dim lay As AcadLayout
Dim isLayoutFound As Boolean
isLayoutFound = False

For Each lay In doc.Layouts
If UCase(lay.Name) = UCase(targetLayoutName) Then
doc.ActiveLayout = lay ‘ レイアウトを切り替える
isLayoutFound = True
Exit For
End If
Next lay

If Not isLayoutFound Then
MsgBox “指定されたレイアウト「” & targetLayoutName & “」が見つかりません。”, vbExclamation, “エラー”
Exit Sub
End If

‘ モデル空間が指定された場合は、ビューポート制御は不要なので終了
If UCase(targetLayoutName) = “MODEL” Then
Exit Sub
End If

‘ 2. ペーパー空間に確実に切り替える
doc.ActiveSpace = acPaperSpace

‘ 3. ペーパー空間自体の「ビューポート(全体)」ではなく、
‘ 中に配置された「フローティングビューポート」をアクティブにする
‘ ※MSpaceをTrueにすることで、ビューポートの「ダブルクリック」をエミュレートします。
doc.MSpace = True

‘ 4. 対象のビューポートをアクティブにする
‘ AutoCAD内部の PViewport コレクションを走査します。
Dim pViewport As AcadPViewport
Dim isViewportFound As Boolean
isViewportFound = False

‘ ペーパー空間内の図形(Entity)の中から、ビューポートを探し出します
Dim entity As AcadEntity
Dim vpCounter As Integer
vpCounter = 1 ‘ ビューポートのカウンタ(ペーパー空間自体が1番になります)

For Each entity In doc.PaperSpace
‘ 図形がビューポートオブジェクトであるか判定
If TypeOf entity Is AcadPViewport Then
Set pViewport = entity

‘ ビューポートが有効(オン)になっているか確認
If pViewport.ViewportOn = True Then
‘ カウンタを進める
vpCounter = vpCounter + 1

‘ ターゲットの番号と一致したら、それをアクティブにする
If vpCounter = targetViewportNo Then
‘ ActiveViewportに設定(ここがミソです)
doc.ActivePViewport = pViewport
isViewportFound = True
Exit For
End If
End If
End If
Next entity

‘ 5. 画面を再描画して、変更を視覚的に反映する
If isViewportFound Then
doc.Regen acAllViewports
‘ ステータスバーに完了通知を表示
doc.Utility.Prompt vbCrLf & “>> [復元完了] レイアウト: ” & targetLayoutName & ” / ビューポート: ” & targetViewportNo & ” をアクティブにしました。”
Else
‘ ビューポートが見つからなかった場合は、ペーパー空間全体のフォーカスに戻す
doc.MSpace = False
MsgBox “指定されたビューポート番号 [” & targetViewportNo & “] が見つかりませんでした。ペーパー空間を表示します。”, vbInformation
End If

Exit Sub

ErrorHandler:
‘ 安全のためのエラー処理
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “システムエラー”
‘ エラーが起きてもMSpaceの状態を安全に復帰させる
Resume Next
End Sub

—

3. コードの徹底解説:なぜこの順序で処理するのか?

このコードには、AutoCADをAPI経由で操作するための「絶対的なお作法」が詰まっています。ポイントを絞って解説しますね。

① `doc.ActiveLayout = lay` のタイミング

VBAでは、表示されていないレイアウト(非アクティブなレイアウト)の中にあるビューポートを直接アクティブにすることはできません。必ず、「まずレイアウトを切り替えてから、その中のビューポートを触る」という手番を踏む必要があります。

② `doc.MSpace = True` の魔法

これが最も重要なプロパティです。
手動操作でいうところの、「ペーパー空間に配置されたビューポート枠の中をダブルクリックして、モデル空間の図面をいじれる状態にする」という動作をプログラム化したものです。
これを `True` に設定しないと、ビューポートをアクティブ化しようとした際に「メソッドが失敗しました」というエラーで落とされてしまいます。

③ なぜビューポート番号が「2」から始まるのか?(※1 の解説)

「一番最初のビューポートをアクティブにしたいから、`targetViewportNo = 1` にしよう!」と考えがちですが、ここに罠があります。
AutoCADのペーパー空間においては、「ペーパー空間全体(図枠全体を写している画面)」自体が内部的に1番目のビューポート(ID=1)として定義されています。
そのため、配置したフローティングビューポート(窓)は、必ず2番(ID=2)以降になります。

—

4. プロフェッショナルへの道:陥りやすい3つの罠と回避策

実務でこのコードをアドインとして組み込む際、誰もが一度は頭を抱える「プロの落とし穴」を共有します。ここを先回りして知っておくことで、あなたのコードの堅牢性は劇的に向上します。

罠1:図面を開いた直後に実行するとエラーになる?

「図面が開かれたイベント(`AcadDocument_Activate` など)」をトリガーにしてこのマクロを自動実行しようとすると、AutoCADの内部初期化(グラフィックのレンダリングなど)が完了する前にコードが走ってしまい、エラーになることがあります。

  • 回避策:

図面オープンイベント直後には `DoEvents` を挟んでOS側に制御を一度返すか、`Application.OnTime`(あるいはタイマー処理)を利用して数ミリ秒のディレイ(待ち時間)を作ってから実行すると、非常に安定します。

罠2:ビューポートが「非アクティブ(オフ)」になっている

ビューポートのプロパティで「オブジェクトがオン」になっていない(非表示・非アクティブな窓)場合、`ActivePViewport` に代入しようとするとエラーになります。

  • コード内の対策:

上記のコードでは、`If pViewport.ViewportOn = True Then` という判定を入れることで、非アクティブな幽霊ビューポートを安全にスルーしています。

罠3:`Regen`(再描画)を忘れる

VBAでビューポートをアクティブに切り替えた直後、画面上では切り替わっていないように見えることがあります。これはAutoCADのグラフィックキャッシュが更新されていないためです。
必ず処理の最後に `doc.Regen acAllViewports` を実行し、ビデオメモリを強制的にリフレッシュさせましょう。

—

5. まとめ:「手動の繰り返し」を撲滅しよう

お疲れ様でした!
今回学んだコードは、単に「画面を切り替える」という動作を超えて、「AutoCADの階層構造を理解し、お作法に従って安全にオブジェクトを制御する」という、VBAマスターへの登竜門となる技術です。

このマクロを応用すれば、

  • 「特定の図面を開いたら、自動的に特定の客先提出用レイアウトに切り替える」
  • 「図面内のすべてのビューポートの尺度(カスタムスケール)を自動でチェック・統一する」

といった、さらに高度な自動化への道が開けます。

少しずつコードを書き換えて、あなたの職場の図面に合わせた最適な挙動にカスタマイズしてみてくださいね。「ここがうまく動かない」「こういう挙動に変えてみたい」といった疑問があれば、いつでも頼りにしてください。

一歩ずつ、確実にスキルアップしていきましょう。あなたなら絶対にマスターできますよ!

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