【入門編】【中級者向け】ページ設定の「縮尺」を自動計算し、実寸と図面上の寸法の乖離を修正する監査ツール – Visio VBA解析バイブル

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

【設計品質を極める】Visio VBA監査ツール:縮尺の不整合を自動検知せよ

「マクロの記録」ボタンを押し、適当に生成されたコードをコピペして動かす。
もしあなたが今、そのフェーズにいるのなら、まずは自分を褒めてあげてください。それはエンジニアとしての第一歩です。

しかし、プロフェッショナルな設計現場において、その手法は「時限爆弾」を抱え込むことと同義です。

特にVisioのような図面作成ツールでは、「ページ設定の縮尺(Scale)」と「シェイプの実際の寸法」が、ユーザーの不注意によって乖離してしまうことが多々あります。1/10の縮尺で作っているはずの図面の中に、なぜか実寸(1/1)で描かれたシェイプが混入している……。これは製造現場や建設現場では致命的なミスに繋がります。

今日は、そんな「図面の嘘」を暴き、設計品質を劇的に向上させる「縮尺監査ツール」の作り方を伝授します。これをマスターすれば、あなたは単なる「マクロ使い」から、プロフェッショナルな「自動化エンジニア」へと昇華するでしょう。

1. 核心:Visioにおける「寸法」の二重構造を理解する

コードを書く前に、Visioの内部構造という「物理法則」を理解しましょう。ここを間違えると、どんなに優れたアルゴリズムも無意味になります。

Visioには、以下の2つの「寸法」が存在します。

1. 描画寸法 (Drawing Dimension):
画面上で、あるいは紙の上で「何インチ(またはmm)の大きさか」という物理的なサイズ。
2. 実寸 (Real-World Dimension):
縮尺を考慮した、設計対象物としての本来のサイズ。

黄金の数式

この関係性は、以下の数式で定義されます。

$$\text{実寸} = \frac{\text{描画寸法}}{\text{ページの縮尺(Scale)}}$$

例えば、ページの縮尺が `1:10`(`Scale = 0.1`)の場合、画面上で `10mm` のシェイプは、実寸では `100mm` となります。

監査ツールの目的は、この計算が「設計意図(例えば、すべての部品はキリの良い数字であるべき)」と矛盾していないかをチェックすることにあります。

2. 実装:縮尺不整合を検知する監査スクリプト

それでは、実際のコードを見ていきましょう。このスクリプトは、ページ内の全シェイプを走査し、実寸が「不自然な端数」を持っている場合に、警告メッセージとともにそのシェイプをハイライトします。

Option Explicit

''' <summary>
''' ページの縮尺設定に基づき、シェイプの実寸が設計意図(キリの良い数字)から
''' 乖離していないかを監査するツール
''' </summary>
Sub AuditScaleConsistency()
    Dim vPage As Visio.Page
    Dim vShape As Visio.Shape
    Dim dScale As Double
    Dim dRealWidth As Double
    Dim dRealHeight As Double
    Dim dTolerance As Double
    Dim errorCount As Integer
    
    ' --- 設定エリア ---
    ' 許容誤差(単位:インチ。0.001インチ程度の微小な誤差を許容)
    dTolerance = 0.001
    ' ------------------

    Set vPage = ActivePage
    dScale = vPage.Scale
    errorCount = 0

    ' 縮尺が0(設定ミス)の場合は終了
    If dScale <= 0 Then
        MsgBox "ページの縮尺が正しく設定されていません。", vbCritical
        Exit Sub
    End If

    ' 画面更新を停止してパフォーマンスを向上(大量のシェイプがある場合)
    Application.ScreenUpdating = False

    ' ページ内の全シェイプをループ
    For Each vShape In vPage.Shapes
        ' グループ内のシェイプや、非表示のシェイプをスキップしたい場合は条件を追加
        If Not vShape.SkipDrawing Then
            
            ' 1. 描画寸法を取得(ResultIUは内部単位。精度が最も高い)
            ' 2. 縮尺で割って「実寸」を算出
            dRealWidth = vShape.Cells("Width").ResultIU / dScale
            dRealHeight = vShape.Cells("Height").ResultIU / dScale
            
            ' 変換:内部単位(IU)から、計算しやすい「インチ」に変換
            ' (Visioの内部単位は 1/72 インチ)
            dRealWidth = (vShape.Cells("Width").ResultIU * 0.0138888888888889) / dScale
            dRealHeight = (vShape.Cells("Height").ResultIU * 0.0138888888888889) / dScale

            ' --- 監査ロジック ---
            ' ここでは例として「実寸が整数(または0.5単位)でない場合は異常」とみなす
            ' 設計ルールに合わせてここをカスタマイズするのがプロの仕事です
            If Not IsRoundNumber(dRealWidth, dTolerance) Or _
               Not IsRoundNumber(dRealHeight, dTolerance) Then
                
                ' 不整合が見つかった場合、シェイプの色を赤に変えて目立たせる
                vShape.Cells("FillForegnd").Formula = "RGB(255, 0, 0)"
                errorCount = errorCount + 1
            End If
        End If
    Next vShape

    Application.ScreenUpdating = True

    ' 結果報告
    If errorCount > 0 Then
        MsgBox "監査完了: " & errorCount & " 個のシェイプに縮尺の不整合(端数)が見つかりました。" & vbCrLf & _
               "該当シェイプを赤色にハイライトしています。", vbExclamation
    Else
        MsgBox "監査完了: 不整合は見つかりませんでした。設計品質は良好です。", vbInformation
    End If
End Sub

''' <summary>
''' 数値が設計意図に基づいた「キリの良い数字」かどうかを判定するヘルパー関数
''' </summary>
Private Function IsRoundNumber(ByVal val As Double, ByVal tolerance As Double) As Boolean
    ' ここでは「0.5単位(0.5, 1.0, 1.5...)」でキリが良いと定義
    Dim roundedVal As Double
    roundedVal = Round(val * 2) / 2
    
    ' 元の値と、丸めた値の差が許容誤差以内ならTrue
    If Abs(val - roundedVal) <= tolerance Then
        IsRoundNumber = True
    Else
        IsRoundNumber = False
    End If
End Function

3. プロの視点:なぜこのコードは「強い」のか?

このコードには、初学者が陥りがちな罠を回避するための「設計思想」が3つ組み込まれています。

① `ResultIU` の活用

多くの人は `vShape.Width` をそのまま使おうとします。しかし、これは「現在の表示単位(mmやインチ)」に依存してしまい、計算誤差を生みます。
プロは `ResultIU` (Internal Units) を使います。Visioの内部で管理されている最も純粋な数値(1/72インチ単位)を直接操作することで、浮動小数点による計算誤差を最小限に抑え、極めて高い精度を担保します。

② 「誤差(Tolerance)」の概念

コンピュータの世界では、`0.1 + 0.2` が厳密に `0.3` にならないことがあります。
`If val = 1.0 Then` のような比較は、エンジニアリングにおいては「禁忌」です。必ず `Abs(a – b) <= tolerance` という形で、「ある程度の誤差は許容する」という書き方をしてください。これが、現場で動く堅牢なコードの条件です。

③ 計算の分離(Separation of Concerns)

「キリの良い数字か?」という判定ロジックを `IsRoundNumber` という別関数に切り出しています。
これにより、「実寸が10mm単位であるべき」というルールに変更したい場合、メインのループ処理を汚すことなく、判定関数の中身だけを書き換えれば済むようになっています。これは保守性という、自動化エンジニアにとって最も重要な資質です。

4. 次のステップへ:ここをクリアすれば、基本はバッチリ!

このスクリプトを動かしてみて、もし「赤く染まったシェイプ」が出現したら、それはあなたの設計プロセスが進化するためのギフトです。

「なぜこのシェイプは端数になったのか?」「縮尺の設定を間違えたのか? それともシェイプをマウスで適当に引き伸ばしてしまったのか?」

その原因を突き止めることこそが、エンジニアリングの本質です。

今日学んだことのまとめ:

  • 縮尺の数式を理解し、描画寸法と実寸を区別する。
  • 精度を追求するために `ResultIU` を使いこなす。
  • 比較には必ず `Tolerance`(許容誤差) を導入する。

これらを意識するだけで、あなたの書くVBAは「ただ動くもの」から「信頼されるツール」へと変わります。さあ、次はもっと複雑な、レイヤー操作やデータリンクの自動化に挑戦してみましょう。道は続いていますよ!

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