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の内部ロジックを、あなたの意図通りに動かすこと」だ。
今回紹介した「内部単位への正規化」というアプローチは、一見遠回りに見えるかもしれない。しかし、この「型」を守ることで、将来的な仕様変更や、クライアントからの「インチ単位で出力してほしい」といった無理難題に対しても、一行もロジックを変えずに対応できるようになる。
これが、伝説的なアーキテクチャを築く者の視点だ。さあ、今すぐコードを書き換えろ。あなたの自動化ツールは、もっと美しく、もっと強固になれるはずだ。
