【実務・中級編】Visio固有の単位系に悩まない:VisioInternalUnitsと実寸・ポイント値の相互変換マクロ – Visio VBA解析バイブル

スポンサーリンク

Visio VBAの闇を制す:Internal Unitsの呪縛から解放される「絶対座標変換」の極意

Visioの自動化において、多くのエンジニアが最初に直面し、そして多くの者が「なんとなくの勘」で誤魔化し続けている地雷がある。それが「Internal Units(内部単位)」の壁だ。

「なぜか座標が数ピクセルずれる」「センチメートル指定したはずなのに図形がとんでもない場所に飛ぶ」。この手のバグに悩まされているなら、あなたのコードはVisioの設計思想を根本から誤解している。

今日は、Visioの描画エンジンと真っ向から対話し、座標計算を「理論的確実性」のもとに置くためのエンジニアリング手法を伝授する。

1. なぜ「Internal Units」を理解しなければならないのか

Visio内部において、すべての数値は「インチ(Inches)」として保持されている。どんなにUI上で「ミリメートル」や「メートル」を設定していても、VBAから直接座標を操作する際、Visioは容赦なくこの内部インチ単位で値を要求してくる。

初心者はここで `10mm / 25.4` といった計算をその場しのぎでコードに埋め込む。だが、これではドキュメント設定や図面の縮尺(Drawing Scale)が変わった瞬間、すべてが崩壊する。

真のプロフェッショナルは、計算を「生の数値」に依存させない。 Visioが提供する `Application.ConvertResult` メソッドを正しく使いこなし、単位変換を抽象化するのだ。

2. 堅牢な単位変換モジュール:`UnitConverter` クラスの実装

場当たり的な計算をコード中に散りばめるのは悪手だ。変換ロジックは一箇所に集約せよ。以下に、メンテナンス性と再利用性を極限まで高めたクラスモジュール(または標準モジュール)のテンプレートを示す。

‘ @Module: UnitConverter
‘ @Description: Visio内部単位と実寸の相互変換を司る堅牢なロジック
Option Explicit

‘ 単位定数(可読性の向上)
Public Const UNIT_MM As String = “mm”
Public Const UNIT_INCH As String = “in”
Public Const UNIT_PT As String = “pt”

”’

”’ 指定した値をVisio内部単位(Inches)に変換する
”’

Public Function ToInternal(ByVal value As Double, Optional ByVal unit As String = UNIT_MM) As Double
‘ ConvertResultは、単位系を跨いだ複雑な計算をVisioエンジンに委ねるための唯一の正解
‘ 内部単位への変換は、第4引数に “in” を指定する
ToInternal = Application.ConvertResult(value, unit, “in”)
End Function

”’

”’ Visio内部単位から指定単位へ変換する
”’

Public Function FromInternal(ByVal internalValue As Double, Optional ByVal targetUnit As String = UNIT_MM) As Double
FromInternal = Application.ConvertResult(internalValue, “in”, targetUnit)
End Function

3. 実践:座標配置のバグを排除する思考法

図形を配置する際、多くの開発者が `Shape.Cells(“PinX”).Formula = “50mm”` のように文字列で設定しようとする。これは遅いし、何よりVisioの解析エンジンを無駄に走らせるためパフォーマンス上の罪だ。

常に `FormulaU` または `ResultIU` を使い、内部単位を直接書き込むのがプロの流儀である。

Sub ArrangeShapeExample()
Dim shp As Visio.Shape
Set shp = ActivePage.DrawRectangle(0, 0, 1, 1) ‘ 適当な位置に作成

‘ 50mm x 30mm の位置に配置したい場合
‘ 変換モジュールを通すことで、単位設定に依存しない堅牢なコードになる
Dim targetX As Double: targetX = UnitConverter.ToInternal(50, UNIT_MM)
Dim targetY As Double: targetY = UnitConverter.ToInternal(30, UNIT_MM)

‘ ResultIUプロパティに直接内部単位を代入することで、
‘ 解析コストを最小化し、ミリ単位のズレを完全に排除する
shp.Cells(“PinX”).ResultIU = targetX
shp.Cells(“PinY”).ResultIU = targetY
End Sub

4. 開発現場で生き残るための「鉄則」

① 縮尺(Drawing Scale)を常に意識せよ

図面設定の「縮尺」は、図形配置の結果に直接影響する。`Page.PageSheet` にアクセスし、`DrawingScale` や `PageScale` を取得して計算に組み込む必要があるケースは多い。特に図面をまたぐコピペ作業を行う際は、「単位そのもの」ではなく「論理座標」で考える癖をつけること。

② データベース連携時は「数値」で保持せよ

外部DBから座標を取得する場合、文字列(例: “50mm”)で保存するのは論外だ。必ず「内部単位(インチ)」または「SI単位系(ミリメートル)」に正規化して保存せよ。DBには `Double` 型で数値を格納し、Visio側で必要に応じて変換する。これがデータ整合性を守る唯一の道だ。

③ ユーザー操作との乖離を埋める

ユーザーがUI上で「10mm」と入力した値と、VBAで処理する「10mm」が食い違う場合、それは大抵 `ConvertResult` の引数ミスか、ページ設定の精度設定の問題だ。デバッグ時は `Debug.Print Application.ConvertResult(10, “mm”, “in”)` をイミディエイトウィンドウで叩き、期待値と一致するかを確認する習慣をつけよ。

最後に:なぜこの設計なのか

ソフトウェア開発において「動けばいい」というコードは、数ヶ月後の自分への負債だ。Visioは非常に古く、クセの強いAPIを持っている。だからこそ、「単位変換のような泥臭い処理を、いかにエレガントに隠蔽するか」が、アーキテクトとしての腕の見せ所となる。

このコードをコピー&ペーストするだけでなく、なぜ `ResultIU` を使うのか、なぜ `ConvertResult` を介するのか、その背景にある「Visioの内部構造」を想像してほしい。そうすれば、あなたの書く自動化ツールは、ただのスクリプトから「信頼できる業務基盤」へと進化するはずだ。

次は、この座標系を基盤とした「レイアウト最適化エンジン」の実装について語るとしよう。準備はいいか?

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