【実務・中級編】CorelDRAW VBAにおける単位換算の罠:ActiveDocument.UnitとRawData(Internal Units)の相互変換の数理 – CorelDRAW VBA解析バイブル

スポンサーリンク

CorelDRAW VBAを掌握せよ:単位系の罠を突破する「内部単位」設計の鉄則

CorelDRAWの自動化において、多くの開発者が最初の壁にぶつかるのが「座標と単位」の不整合だ。

「UI上で10mmと入力したのに、VBAで取得すると変な数値が返ってくる」「ドキュメントの単位をインチに変更した途端、全ツールが沈黙した」。このような悲劇は、CorelDRAWのオブジェクトモデルにおける「内部単位(Internal Units)」という概念を無視していることに起因する。

本稿では、VBA開発の現場で死なないための、堅牢な単位変換アーキテクチャを伝授する。

1. なぜ `ActiveDocument.Unit` を信用してはいけないのか

CorelDRAWのVBAにおいて、`ActiveDocument.Unit` はあくまで「表示上の単位」に過ぎない。しかし、VBAの内部演算(`Shape.Left`, `Shape.Top` 等)は、すべて「内部単位(Internal Units)」として処理されている。

内部単位の正体:マイクロインチの呪縛

CorelDRAWの内部エンジンは、歴史的経緯から1インチ=720,000内部単位という固定値で座標を管理している。
どんなに環境設定でミリメートルやポイントを選択していようとも、APIが要求し、また吐き出す数値は常にこの内部単位である。

もしあなたが「UIの単位に合わせて計算式を書く」というアプローチを採っているなら、それは「地雷原でタップダンスを踊る」のと同義だ。ドキュメントの設定が変われば、すべて計算が崩壊する。

2. 堅牢な変換ライブラリの設計思想

真のエンジニアは「変換」を個別に行わない。「内部単位を基準(ハブ)とした変換層」を構築する。

  • 入力層: ユーザー入力や外部DBからの値を、一度「内部単位」に正規化する。
  • 処理層: すべての演算を「内部単位」のみで行う。
  • 出力層: 最後に必要に応じて表示単位へ変換する。

この設計にすることで、ドキュメントがどんな単位系であっても、ロジック自体は不変(Immutable)となる。

3. 実装:Production-Readyな変換モジュール

以下のコードは、保守性と再利用性を極限まで高めたクラスモジュール相当の関数群だ。これを標準モジュールに配置し、あなたのツールの中核に据えてほしい。

Option Explicit

‘ CorelDRAWの内部単位定数
Private Const INTERNAL_UNITS_PER_INCH As Double = 720000

‘ ———————————————————
‘ 目的: 指定した値を「内部単位」に正規化する
‘ 備考: 常にこの関数を通してから演算を行うこと
‘ ———————————————————
Public Function ToInternalUnits(val As Double, unit As cdrUnit) As Double
Dim doc As Document
Set doc = ActiveDocument

‘ コンテキストに応じた変換
‘ 内部単位(cdrInch)を基準に換算を行う
ToInternalUnits = doc.ToUnits(val, unit)
End Function

‘ ———————————————————
‘ 目的: 内部単位から任意の単位へ逆変換する
‘ ———————————————————
Public Function FromInternalUnits(internalVal As Double, targetUnit As cdrUnit) As Double
Dim doc As Document
Set doc = ActiveDocument

‘ APIのFromUnitsをラップし、計算の堅牢性を担保
FromInternalUnits = doc.FromUnits(internalVal, targetUnit)
End Function

‘ ———————————————————
‘ 実務での使用例:10mm右に移動させる
‘ ———————————————————
Public Sub MoveShapeBy10mm(shp As Shape)
‘ 1. 10mmを内部単位に変換
Dim moveAmount As Double
moveAmount = ToInternalUnits(10, cdrMillimeter)

‘ 2. 内部単位で演算(ここが一番バグが起きにくい)
shp.LeftX = shp.LeftX + moveAmount
End Sub

4. 開発現場で生き残るための「3つの極意」

① データベース連携時の注意点

DBに座標を保存する際、`ActiveDocument.Unit` を保存してはいけない。必ず「内部単位(Double型)」で保存せよ。 単位を跨いでデータをやり取りしても、内部単位さえ守れば、CorelDRAWのバージョンアップや設定変更の影響を完全に遮断できる。

② `ActiveDocument` の落とし穴

複数ドキュメントを開いている際、`ActiveDocument` はユーザーのフォーカスによって瞬時に切り替わる。「現在処理すべきDocumentオブジェクト」を明示的に変数として保持し、それを引数で渡す設計にすること。グローバルな `ActiveDocument` への依存は、マルチドキュメント環境におけるバグの温床だ。

③ 浮動小数点誤差の処理

`10mm` を変換して戻すと `9.999999998mm` になることがある。これはバイナリ演算の宿命だ。比較を行う際は必ず `Abs(a – b) < 0.0001` のような閾値判定(epsilon)を導入すること。厳密な「イコール判定」は、自動化ツールにおいては死を意味する。 ---

最後に:コードは「対話」である

自動化とは、単に作業を代行させることではない。「CorelDRAWの内部ロジックを、あなたの意図通りに動かすこと」だ。

今回紹介した「内部単位への正規化」というアプローチは、一見遠回りに見えるかもしれない。しかし、この「型」を守ることで、将来的な仕様変更や、クライアントからの「インチ単位で出力してほしい」といった無理難題に対しても、一行もロジックを変えずに対応できるようになる。

これが、伝説的なアーキテクチャを築く者の視点だ。さあ、今すぐコードを書き換えろ。あなたの自動化ツールは、もっと美しく、もっと強固になれるはずだ。

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