ようこそ、AutoCAD自動化の深淵へ。
「マクロの記録」ボタンを押すだけの生活から卒業し、自らの手でAutoCADを意のままに操るエンジニアの第一歩を踏み出す君を歓迎するよ。
今日は、AutoCAD VBAの初学者が必ずぶつかる「図面範囲(Limits)の最適化」というテーマを攻略する。納品図面を開いた瞬間に、ズームがとんでもない場所に飛んでいて「どこに図面があるんだ?」と焦ったことはないかな?
あれは、Limits(図面境界)が適切に管理されていないから起こる現象だ。これを自動化する技術は、単なる便利ツールではなく、「設計品質の標準化」というプロの領域への入り口だ。さあ、一緒に解き明かしていこう。
—
1. なぜ「Limits」を自動調整する必要があるのか?
AutoCADにおける`Limits`は、いわば「キャンバスのサイズ」だ。
これを適切に設定しないと、以下の不具合が起きる。
- ズーム全範囲(Zoom Extents)の機能不全: 図面範囲外にゴミデータがあると、全体が表示されない。
- 印刷プレビューの崩壊: 印刷範囲を「図面範囲」で指定している場合、レイアウトがズレる。
- 作図精度の低下: グリッド表示が機能しなくなり、設計の「基準」が失われる。
オブジェクトの最大外接矩形を計算し、そこにマージン(余白)を加えてLimitsを再設定する。これが、できるエンジニアのたしなみだ。
—
2. 実装のロジック:座標の海を探索する
コードを書く前に、頭の中で設計図を描こう。
1. モデル空間の全オブジェクトをスキャンする。
2. 各オブジェクトの「バウンディングボックス(最小と最大の座標)」を取得する。
3. 全オブジェクトの最小X,Yと最大X,Yを比較し、真の全体境界を割り出す。
4. その境界に余裕(オフセット)を足して、`Limits`を更新する。
禁断の注意点:`GetBoundingBox`の罠
多くの初心者がここで躓く。`GetBoundingBox`は、全てのオブジェクト(例えばブロック参照など)に対して常に成功するわけではない。また、座標値が配列で返ってくることを理解していないと、エラーの温床になる。
—
3. 実装コード:Limits最適化プログラム
このコードは、標準モジュールにそのまま貼り付けて実行できるように設計した。
Option Explicit
‘ 図面内の全オブジェクトを解析し、Limitsを自動設定する
Public Sub FitLimitsToObjects()
Dim obj As AcadEntity
Dim minPt As Variant, maxPt As Variant
Dim minX As Double, minY As Double
Dim maxX As Double, maxY As Double
Dim isFirst As Boolean
‘ 初期値:極端な値を設定して比較の準備をする
minX = 1E+20: minY = 1E+20
maxX = -1E+20: maxY = -1E+20
isFirst = True
‘ モデル空間の全オブジェクトをループ
For Each obj In ThisDrawing.ModelSpace
‘ ブロック参照や線分など、バウンディングボックスを持つものだけを処理
On Error Resume Next ‘ エラー回避(バウンディングボックスを持たないオブジェクト対策)
obj.GetBoundingBox minPt, maxPt
If Err.Number = 0 Then
‘ 最小値/最大値を更新
If minPt(0) < minX Then minX = minPt(0)
If minPt(1) < minY Then minY = minPt(1)
If maxPt(0) > maxX Then maxX = maxPt(0)
If maxPt(1) > maxY Then maxY = maxY = maxPt(1)
isFirst = False
End If
On Error GoTo 0
Next obj
‘ オブジェクトが見つからなかった場合の処理
If isFirst Then
MsgBox “解析対象のオブジェクトが見つかりません。”, vbExclamation
Exit Sub
End If
‘ 余裕(マージン)を計算(例:全体サイズの5%)
Dim margin As Double
margin = (maxX – minX) 0.05
‘ システム変数 Limits を更新
Dim limitMin(0 To 1) As Double
Dim limitMax(0 To 1) As Double
limitMin(0) = minX – margin: limitMin(1) = minY – margin
limitMax(0) = maxX + margin: limitMax(1) = maxY + margin
ThisDrawing.Limits(0) = limitMin
ThisDrawing.Limits(1) = limitMax
‘ 再描画して変更を反映
ThisDrawing.Regen acActiveViewport
MsgBox “Limitsをオブジェクト境界に合わせて最適化しました。”
End Sub
—
4. このコードを使いこなすためのヒント
なぜ `On Error Resume Next` を使うのか?
AutoCADのオブジェクトの中には、バウンディングボックスの概念を持たないもの(例えば非表示の属性定義や、特殊なレイヤー設定など)がある。これらに`GetBoundingBox`を適用しようとするとVBAはエラーを吐いて停止する。
「エラーを恐れず、適切に無視する(あるいはログを記録する)」のは、現場で生き残るエンジニアの必須スキルだ。
パフォーマンスの極意
図面が数万オブジェクト規模になると、`For Each`ループは重くなることがある。その場合は、`SelectionSet`(選択セット)を使って、必要な画層やオブジェクトタイプだけをフィルタリングして抽出するように改良してみよう。
—
最後に:エンジニアとしての成長のために
このスクリプトは、あくまで「基礎」だ。ここから君は、以下のように拡張できる。
- ペーパー空間のレイアウトタブにも対応させる。
- 特定の画層(「補助線」など)を無視するようにフィルタを追加する。
- Limitsだけでなく、Zoom Extentsも同時に実行する。
AutoCAD VBAは、君が「面倒だ」と感じた作業を、忠実な執事のように肩代わりしてくれる強力な武器だ。まずは今日、このコードを自分の環境で動かし、その手応えを感じてほしい。
分からないことがあれば、いつでもまた聞きに来なさい。君の自動化ライフを、心から応援しているよ。
