【入門編】【実務中級者向け】保存時の「自動ズーム」を特定の注釈エリアに限定する:検図者が最初に見るべき場所を固定してセーブ – AutoCAD VBA解析バイブル

スポンサーリンク
スポンサーリンク

図面は「データ」ではなく「メッセージ」である。

検図者の視線を操る、AutoCAD VBAによる「視覚的申し送り」の極意

こんにちは。現場の自動化を支えるアーキテクトです。

AutoCADを使っていると、「ファイルを保存して渡したのに、相手から『どこを見ればいいの?』と聞かれた」なんて経験はありませんか?
図面を開いたとき、画面には広大な座標系が広がっています。検図者やクライアントがファイルを開いた瞬間、「今、どこに注目すべきか」を視覚的に提示できているか。 これは、単なる操作の差ではなく、エンジニアとしての「情報の渡し方」の質を決める重要な要素です。

今日は、マクロの記録から一歩踏み出し、「図面内の特定のマークを自動で見つけ出し、そこを画面いっぱいに表示(ズーム)した状態で保存する」という、実務に直結する高度なテクニックを伝授します。

これをマスターすれば、あなたの作成する図面は「ただのデータ」から「親切なメッセージ」へと進化します。

1. 戦略を立てる:どうやって「注釈」を見つけるか?

いきなりコードを書き始めるのは素人の仕事です。プロのエンジニアは、まず「ロジック(論理)」を組み立てます。

今回のゴールは、「特定の名前(例:`REV_MARK`)を持つブロック」を探し、その範囲をズームして保存することです。

実装のステップ

1. 探索: モデル空間内の全てのオブジェクトをスキャンし、特定の名前を持つブロックを探す。
2. 計算: 見つかったマークの「左下(最小座標)」と「右上(最大座標)」を特定する(これを境界ボックス/Bounding Boxと呼びます)。
3. 制御: 算出した範囲を使って、図面の表示領域(Viewport)をズームする。
4. 確定: その表示状態を維持したまま、図面を保存する。

ここで重要なのは、「マークが複数あった場合、それらすべてを囲むようにズームする」という配慮です。これこそが、中級者への入り口です。

2. 実装:魂を込めたコード例

それでは、実際に動作するコードを見ていきましょう。このコードは、初心者の方でも読みやすいよう、丁寧にコメントを添えています。

Option Explicit

''' <summary>
''' 特定のブロック(変更箇所マーク)を検索し、
''' その範囲をズームしてから図面を保存するメインルーチン
''' </summary>
Sub SaveWithFocusOnMarks()
    Dim acadDoc As AcadDocument
    Set acadDoc = ThisDrawing
    
    Dim objEntity As AcadEntity
    Dim targetBlockName As String
    Dim foundCount As Integer
    
    ' --- 設定エリア ---
    ' 検索したいブロックの名前を指定してください
    targetBlockName = "REV_MARK"
    ' ------------------
    
    foundCount = 0
    
    ' 境界ボックス(ズーム範囲)を保持するための変数
    Dim minX As Double, minY As Double, maxX As Double, maxY As Double
    Dim firstFound As Boolean
    firstFound = True

    On Error GoTo ErrorHandler
    
    ' 1. モデル空間内の全オブジェクトを走査
    ' ※ 大規模図面ではレイヤーでフィルタリングするのがプロの技ですが、
    '    今回は基本を学ぶため、全探索を行います。
    For Each objEntity In acadDoc.ModelSpace
        
        ' オブジェクトが「ブロック参照」かつ「名前が一致」するか判定
        If TypeOf objEntity Is AcadBlockReference Then
            If objEntity.Name = targetBlockName Then
                
                ' 2. 境界ボックス(表示範囲)の計算
                ' ブロックの挿入点とスケールから、その範囲を特定します
                Dim insPt As Variant
                insPt = objEntity.InsertionPoint
                
                ' ここでは簡易的に、ブロックの挿入点を基準に計算します。
                ' 本来はブロックのサイズ(BoundingBox)を取得するのが理想的です。
                ' 今回は「マークの周囲を囲む」ため、挿入点を中心とした矩形を作ります。
                
                ' マークの「中心」を基準に、上下左右の広がりを計算(例:100ユニット分)
                Dim offset As Double
                offset = 50 
                
                If firstFound Then
                    minX = insPt(0) - offset: maxX = insPt(0) + offset
                    minY = insPt(1) - offset: maxY = insPt(1) + offset
                    firstFound = False
                Else
                    ' 既に見つかった範囲を拡張していく(全マークを囲むため)
                    If insPt(0) - offset < minX Then minX = insPt(0) - offset
                    If insPt(1) - offset < minY Then minY = insPt(1) - offset
                    If insPt(0) + offset > maxX Then maxX = insPt(0) + offset
                    If insPt(1) + offset > maxY Then maxY = insPt(1) + offset
                End If
                
                foundCount = foundCount + 1
            End If
        End If
    Next objEntity

    ' 3. ズームと保存の実行
    If foundCount > 0 Then
        ' ズーム範囲を指定するための配列を作成
        Dim zoomWindow As Variant
        zoomWindow = Array(Array(minX, minY), Array(maxX, maxY))
        
        ' AutoCADのコマンドを使用してズームを実行
        ' VBAの標準メソッドよりも、SendCommandの方が確実な場合があります。
        acadDoc.SendCommand "-ZOOM" & vbCr & "W" & vbCr & minX & "," & minY & vbCr & maxX & "," & maxY & vbCr
        
        ' 保存の実行
        acadDoc.Save
        MsgBox foundCount & " 個のマークが見つかりました。範囲をズームして保存しました。", vbInformation, "完了"
    Else
        MsgBox "指定されたマーク(" & targetBlockName & ")が見つかりませんでした。そのまま保存します。", vbExclamation, "警告"
        acadDoc.Save
    End If

    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical, "エラー"
End Sub

3. コードの深淵:プロが教える「ここが重要」

このコードをただコピペするだけでは、あなたはまだ「マクロ使い」です。このコードの裏側にある「設計思想」を理解してこそ、真のエンジニアです。

① `SendCommand` を使う理由

AutoCAD VBAには、表示領域を制御する `View` オブジェクトがありますが、実は `SendCommand` を使って直接コマンド(`-ZOOM`)を叩くほうが、直感的で「図面として正しい表示」を得やすい場面が多いのです。これは、AutoCADの内部的な描画更新と同期させやすいためです。

② 境界ボックスの拡張ロジック

コード内の `If … Then … Else` の部分は、「最小値の更新」と「最大値の更新」を行っています。

  • 新しい点が見つかるたびに、「今までの最小値より小さければ更新」「最大値より大きければ更新」を繰り返す。
  • これにより、複数のマークが図面のあちこちに散らばっていても、「すべてのマークを一つの窓の中に収める」ことが可能になります。

③ オブジェクトのライフサイクルとパフォーマンス

今回のコードでは `For Each objEntity In acadDoc.ModelSpace` を使っています。
もし図面の中に10万個の線があったらどうなるでしょうか? 毎回全探索するのは非常に重い処理になります。
「実務での極意」を教えましょう。
> 「特定のレイヤーにマークを置くルール」を運用し、コード側では「そのレイヤーのオブジェクトだけを対象にする」ようにフィルタリングしてください。これだけで、処理速度は劇的に向上します。

4. 陥りやすいエラーと対策

初心者がこの手の開発で必ず躓くポイントが2つあります。

1. ブロックの名前間違い:
`targetBlockName = “REV_MARK”` と書いていても、図面上のブロック名が `rev_mark`(小文字)だったり、属性が含まれていて名前が異なっていたりすると、一つもヒットしません。

  • 対策: `StrComp(objEntity.Name, targetBlockName, vbTextCompare) = 0` を使って、大文字小文字を区別せずに比較するようにしましょう。

2. 座標系の混乱:
AutoCADには「世界座標系(WCS)」と「ユーザー座標系(UCS)」があります。ズームする座標がズレる原因の多くは、UCSが回転していることです。

  • 対策: ズーム操作を行う前に、`acadDoc.UCS` を `WCS` にリセットする処理を入れると、非常に堅牢なマクロになります。

最後に:自動化の先にあるもの

自動化の目的は「楽をすること」だけではありません。「ミスを減らし、価値の高い仕事に集中すること」です。

今回紹介した「視覚的な申し送り」ができる図面は、受け取った相手のストレスを劇的に減らします。その積み重ねが、あなたの信頼を築き、エンジニアとしての市場価値を高めていくのです。

「ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ。」

さあ、次は自分なりの「独自のマーク」を作って、このコードをカスタマイズしてみてください。応援しています!

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