CorelDRAW VBAを掌握する極限の知見:単位換算の罠と内部単位の完全統御
こんにちは。チーフアーキテクトの私だ。
日々の業務自動化、ご苦労様である。
CorelDRAW VBAにおける開発で、最も多くの開発者が最初の数週間でハマり、そして巧妙なバグを生み出し続ける魔窟がどこか知っているか?
それは「単位系(Units)」の扱いだ。
画面上のルーラーが「ミリメートル」であろうと「インチ」であろうと、安易に `ActiveDocument.Unit` を頼りにコードを書き進める――。もし君がそんな設計をしているなら、今すぐそのキーボードから手を離してほしい。そのコードは、異なる環境やユーザー設定のもとで必ず破綻する。
今回は、CorelDRAWのオブジェクトモデルにおける「内部単位(Internal Units)」の正体を暴き、環境に依存しない堅牢な自動化ロジックを構築するための極限の知見を授けよう。
—
1. なぜ `ActiveDocument.Unit` を使ってはいけないのか
初心者がやりがちな最悪のアンチパターンを見てみよう。
‘ 【アンチパターン】絶対に真似してはならないコード
Sub BadExample_MoveShape()
Dim s As Shape
Set s = ActiveShape
‘ ユーザーのドキュメント単位系に依存する処理
If ActiveDocument.Unit = cdrMillimeter Then
s.Move 10, 0 ‘ 10mm動かしたい意図
ElseIf ActiveDocument.Unit = cdrInch Then
s.Move 0.3937, 0
End If
End Sub
このコードの何が問題か?
1. 環境依存性: ユーザーがドキュメントの単位を「ポイント」や「キュビット」に変更した瞬間、意図しない挙動を引き起こす。
2. 保守性の崩壊: 処理ごとに単位の条件分岐を書く必要が生じ、コードベースがゴミの山と化す。
3. 浮動小数点誤差: 画面表示用の単位系で計算や比較を行うことで、微小な丸め誤差が蓄積し、DTPの現場で許されない「0.001mmのズレ」を生む。
CorelDRAWのエンジンは、画面の単位が何であれ、内部では「Master Units(内部単位)」という絶対的な基準で全ての座標とサイズを管理している。プロのエンジニアが操るべきは、この内部単位なのだ。
—
2. コア・メカニズム:内部単位(Internal Units)の正体
CorelDRAWの内部世界において、長さの基準は「Inch(インチ)」、厳密にはCorelの歴史的背景に根ざす内部解像度(通常、1インチ=パッチあたりの数値、あるいはCorel内部の基本スケーリング)に基づいている。
VBAにおいて、CorelDRAWはAPIを通じて自動的に「ドキュメント上の単位」を「内部単位」へ、あるいはその逆へと変換するゲッター・セッターを提供している。しかし、それをUIの設定に委ねるから話がおかしくなる。
私たちは、「常に内部単位(通常はインチベース、あるいはプロパティ固有の変換係数)で計算を行い、必要に応じて明示的に変換する」という原則を貫くべきだ。
特に重要なのが、`ActiveDocument.ToUnits` と `ActiveDocument.FromUnits` メソッド、そして `ActiveDocument.Evaluate` の活用である。
—
3. 実践:バグを駆逐する堅牢な単位換算ユーティリティ
実務で使える、ミリメートル等の外部入力を確実に内部単位へ変換し、またその逆を行うためのプロダクションコードを提示する。このモジュールを君のプロジェクトの標準装備としなさい。
Option Explicit
‘ ==============================================================================
‘ モジュール名: modUnitEngine
‘ 概要: ユーザー単位系に依存しない、完全なロジック駆動型単位換算エンジン
‘ ==============================================================================
‘ ミリメートルをCorelDRAWの内部単位(インチベースの内部表現)に変換する
Public Function mmToInternal(ByVal mm As Double) As Double
‘ CorelDRAWはドキュメントの単位に関わらず、内部的にはインチを基準に換算が可能
‘ 1インチ = 25.4 mm
mmToInternal = ActiveDocument.ConvertUnits(mm, cdrMillimeter, cdrInch)
End Function
‘ 内部単位からミリメートルへ逆変換する
Public Function InternalToMm(ByVal internalValue As Double) As Double
InternalToMm = ActiveDocument.ConvertUnits(internalValue, cdrInch, cdrMillimeter)
End Function
‘ 【推奨】データベースや外部CSVから読み込んだ数値を、確実に対象オブジェクトに適用する例
Public Sub ApplyPreciseLayout(s As Shape, targetWidthMm As Double, targetHeightMm As Double)
‘ 1. すべて内部単位に一度換算して保持する
Dim internalW As Double
Dim internalH As Double
internalW = ActiveDocument.ConvertUnits(targetWidthMm, cdrMillimeter, cdrInternalUnits)
internalH = ActiveDocument.ConvertUnits(targetHeightMm, cdrMillimeter, cdrInternalUnits)
‘ 2. アスペクト比固定を一時的に解除して正確に適用
s.SetSize internalW, internalH
End Sub
このコードが堅牢である理由
`ActiveDocument.ConvertUnits(Value, FromUnit, ToUnit)` を用いることで、CorelDRAWのネイティブな換算エンジンをダイレクトに叩くことができる。`cdrInternalUnits` を明示的に指定することで、ユーザーが画面で何を選択していようとも、数学的に厳密な数値をオブジェクトに流し込むことが可能になる。
—
4. ファイル・データベース連携における罠と対策
外部システム(Excel発注書、ERP、クラウドDBなど)と連携する際、単位の扱いはさらにシビアになる。
- 罠: データベースには「純粋な数値(例: `100`)」だけが保存されており、それが「mm」なのか「pt」なのかがコンテキストから漏れている。
- 対策: 外部データを取り込む際、インターフェース層で必ず「単位のメタデータ」を検証し、VBAの入口で強制的にミリメートル等へ正規化した上で、上記の `ConvertUnits` に通すこと。
‘ データベース連携時の安全なインポート処理のスケルトン
Public Sub ImportFromExternalData(dataValue As Double, unitType As String)
Dim internalVal As Double
Select Case UCase(unitType)
Case “MM”
internalVal = ActiveDocument.ConvertUnits(dataValue, cdrMillimeter, cdrInternalUnits)
Case “IN”, “INCH”
internalVal = ActiveDocument.ConvertUnits(dataValue, cdrInch, cdrInternalUnits)
Case “PT”, “POINT”
internalVal = ActiveDocument.ConvertUnits(dataValue, cdrPoint, cdrInternalUnits)
Case Else
Err.Raise 9999, “ImportFromExternalData”, “未定義の単位系です: ” & unitType
End Select
‘ 以降、internalValを用いて形状生成・配置を行う
Dim rect As Shape
Set rect = ActiveLayer.CreateRectangle(0, 0, internalVal, internalVal)
End Sub
—
5. チーフアーキテクトからの総括
単位系を制する者は、CorelDRAW VBAを制する。
画面上の表示(UI)と、メモリ上の演算(Logic)を完全に分離せよ。ユーザーがどのような環境でドキュメントを開こうとも、あなたの書いた自動化スクリプトが寸分の狂いもなくデザインを構築する――それこそが、プロフェッショナルな業務自動化エンジニアの仕事である。
次の現場では、`ActiveDocument.Unit` で条件分岐しているコードを見つけ次第、このアーキテクチャに書き換えて見せるといい。
妥協のないコードで、最高の自動化ライフを。
