CorelDRAW VBAを掌握する極限の知見:単位換算の罠と内部単位(Internal Units)の完全制御
CorelDRAW VBAの開発において、多くのエンジニアが最初に直面し、そして知らず知らずのうちに致命的なバグを埋め込んでしまう領域がある。それが「単位系(Units)」のハンドリングだ。
画面上のルーラーがミリメートル(mm)になっていれば `10` は 10mm だと思い込み、別の環境(例えば印刷業界向けのインチ・ポイント環境)でそのコードを走らせた瞬間、図形は意図せぬミクロの点へと縮小するか、あるいはキャンバスを突き破る巨獣と化す。
この現象の根底にあるのは、CorelDRAWのオブジェクトモデルが持つ「UI上の単位系」と「内部演算単位(Internal Units)」の完全な乖離である。
今回は、シニアエンジニアおよび社内システムアーキテクトに向けて、この単位換算の罠を完全にハックし、環境依存性を排除した堅牢なVBAコードを構築するための極限の知見を公開する。
—
1. 内部単位(Internal Units)の正体
CorelDRAWの内部エンジンは、ユーザーが画面上で何を選択していようとも、すべての座標とサイズを「DLU(Draw Length Units)」と呼ばれる独自の内部単位で保持・計算している。
- 1 インチ = 25.4 ミリメートル = 72 ポイント = 25400 DLU
つまり、CorelDRAWの内部的な最小分解能は `1/25400 インチ`(約 0.001mm)であり、すべてのオブジェクトの位置(`CenterX`, `CenterY` など)やサイズ(`Width`, `Height`)は、この DLU という名の長整数(Long)に近い浮動小数点数(Double)としてメモリ上に存在している。
ここで問題になるのが、`ActiveDocument.Unit` プロパティである。
‘ ──【アンチパターン】UIの単位に依存した破滅的なコード──
Sub DangerousResize()
Dim shp As Shape
Set shp = ActiveShape
If shp Is Nothing Then Exit Sub
‘ ActiveDocument.Unitが「mm」なら上手くいくが、
‘ ユーザーが「インチ」や「ピクセル」に変更していると予期せぬサイズになる
shp.Size 100, 50
End Sub
上記のコードは、ユーザーがアプリケーションのUI設定を変更しただけで意図しない挙動を示す。プロフェッショナルな自動化スクリプトにおいて、ユーザーのUI設定に依存するロジックは「悪」である。
—
2. 厳密な単位換算の数学的アプローチ
VBAコード内で常にミリメートル、あるいはインチといった絶対的な物理単位で座標計算を行いたい場合、UIの設定値 (`ActiveDocument.Unit`) を参照してはならない。
CorelDRAW VBAには、任意の単位系と内部単位(DLU)を相互変換するための静的メソッドや、定数係数が存在する。これを利用し、「すべての入力値り、または計算値を一度内部単位に正規化(Normalize)」し、処理後に必要に応じた単位へ射影するというアーキテクチャを採用する。
単位変換係数マトリックス
CorelDRAWの `cdrUnit` 列挙体に対応する、DLUへの換算係数(1単位あたりに含まれるDLU)を把握しておく必要がある。
| 単位 (cdrUnit) | 定数名 | 1単位あたりのDLU値 |
| :— | :— | :— |
| インチ | `cdrInch` | `25400` |
| ミリメートル | `cdrMillimeter` | `25400 / 25.4` (= 1000) |
| センチメートル | `cdrCentimeter` | `25400 / 2.54` (= 10000) |
| ポイント | `cdrPoint` | `25400 / 72` |
| ピクセル | `cdrPixel` | ドキュメントの解像度に依存 |
—
3. 実装:環境依存を完全に排除する単位変換ユーティリティ
実務の現場で即座に使える、極限まで最適化された単位変換モジュールの設計図を提示する。このコードでは、UIの設定(`ActiveDocument.Unit`)を一切汚染せず、純粋な数学的係数のみで計算を完結させる。
Option Explicit
‘ ==============================================================================
‘ Module: 単位換算・幾何学演算コアエンジン
‘ Architecture: 完全に独立した内部単位(DLU)ベースの座標・サイズ変換
‘ ==============================================================================
‘ CorelDRAWの内部単位ベース係数(基準: 1 inch = 25400 DLU)
Private Const DLU_PER_INCH As Double = 25400#
Private Const DLU_PER_MM As Double = 1000#
Private Const DLU_PER_POINT As Double = 352.777777777778 ‘# 25400 / 72
Private Const DLU_PER_CM As Double = 10000#
‘ 任意の単位系から内部単位(DLU)へ変換
Public Function ToInternalUnits(ByVal Value As Double, ByVal Unit As cdrUnit) As Double
Select Case Unit
Case cdrInch
ToInternalUnits = Value DLU_PER_INCH
Case cdrMillimeter
ToInternalUnits = Value DLU_PER_MM
Case cdrCentimeter
ToInternalUnits = Value DLU_PER_CM
Case cdrPoint
ToInternalUnits = Value DLU_PER_POINT
Case Else
‘ その他の単位系(ピクセル等)はドキュメントコンテキストを強制適用
ToInternalUnits = ActiveDocument.ConvertUnits(Value, Unit, cdrFormatInternal)
End Select
End Function
‘ 内部単位(DLU)から任意の単位系へ変換
Public Function FromInternalUnits(ByVal InternalValue As Double, ByVal Unit As cdrUnit) As Double
Select Case Unit
Case cdrInch
FromInternalUnits = InternalValue / DLU_PER_INCH
Case cdrMillimeter
FromInternalUnits = InternalValue / DLU_PER_MM
Case cdrCentimeter
FromInternalUnits = InternalValue / DLU_PER_CM
Case cdrPoint
FromInternalUnits = InternalValue / DLU_PER_POINT
Case Else
FromInternalUnits = ActiveDocument.ConvertUnits(InternalValue, cdrFormatInternal, Unit)
End Select
End Function
—
4. シニアエンジニアのための実践的応用:精密レイアウト配置マクロ
上記のユーティリティを活用し、「ユーザーの画面設定が何であれ、厳密に指定したミリメートル単位で図形をグリッド状に精密配置する」システムの核心コードを示す。
ここではメモリ最適化の観点から、オブジェクトのライフサイクル管理(特に `ShapeRange` や参照変数の適切な解放)も徹底している。
Sub PrecisionGridPlacement()
‘ 描画・画面更新の完全停止によるパフォーマンス爆発的向上
Application.Optimization = True
ActiveDocument.BeginCommandGroup “Precision Grid Placement”
Dim targetDoc As Document
Set targetDoc = ActiveDocument
‘ エラーハンドリング時のメモリリークを防ぐための構造化
On Error GoTo ErrorHandler
‘ ── パラメータ定義(常に物理ミリメートルで指定) ──
Const CELL_WIDTH_MM As Double = 50#
Const CELL_HEIGHT_MM As Double = 30#
Const MARGIN_MM As Double = 5#
Dim wDLU As Double, hDLU As Double, mDLU As Double
wDLU = ToInternalUnits(CELL_WIDTH_MM, cdrMillimeter)
hDLU = ToInternalUnits(CELL_HEIGHT_MM, cdrMillimeter)
mDLU = ToInternalUnits(MARGIN_MM, cdrMillimeter)
Dim i As Long, j As Long
Dim rectShp As Shape
For i = 0 To 2
For j = 0 To 3
‘ 内部単位(DLU)ベースで正確無比な座標計算
Dim posX As Double, posY As Double
posX = mDLU + (i (wDLU + mDLU))
posY = -(mDLU + (j (hDLU + mDLU))) ‘ CorelDRAWのY軸は上が正
‘ 矩形描画
Set rectShp = targetDoc.ActiveLayer.CreateRectangle(posX, posY, posX + wDLU, posY – hDLU)
‘ プロパティ設定
rectShp.Outline.Width = ToInternalUnits(0.5, cdrMillimeter) ‘ 0.5mmの枠線
rectShp.Fill.UniformColor.RGBAssign 240, 240, 240
Next j
Next i
CleanUp:
‘ トランザクションの終了とUIの復元
ActiveDocument.EndCommandGroup
Application.Optimization = False
Application.Refresh
Exit Sub
ErrorHandler:
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “System Error”
Resume CleanUp
End Sub
—
5. レガシー環境とシステム間連携における知見
外部のERPシステムやCAD、あるいはWebからのJSON/XMLデータ(例:寸法データがすべて「ミリメートル」や「メートル」で飛んでくる環境)とCorelDRAWを連携させる際、前述の「UI設定の罠」を踏み抜くと、顧客提出用の大判印刷物で数ミリのズレ(致命的な不良)を引き起こす。
1. 外部データのインジェクション時は、必ず `cdrFormatInternal` または固定係数(`1000#`)を介してDLU化せよ。
2. CorelDRAWの `ActiveDocument.Unit` は変更しないこと。 ユーザーが作業している環境のUI設定をマクロが勝手に書き換えるのは、UXの観点から最悪のアンチパターンである。単位の変換はあくまで「メモリ上の数値計算レイヤー」で完結させよ。
3. 浮動小数点の誤差への配慮: VBAの `Double` 型はIEEE 754準拠の倍精度浮動小数点数である。DLUという巨大な整数に近い数値を扱う場合、微小な丸め誤差(例: `4.9999999999999` mm)が発生しうる。厳密な幾何学判定やスナップ処理を行う際は、許容誤差(イプシロン、例: `0.0001`)を考慮した比較ロジックを挟むこと。
—
結び
CorelDRAW VBAにおいて、単位を制する者はドキュメント自動化の全権を制する。
画面上の表示に惑わされず、内部単位(DLU)という絶対的な物理座標軸をコードの手中に収めたとき、あなたの自動化スクリプトは、どのような環境・どのようなユーザー設定であっても、寸分の狂いもない正確性を発揮するだろう。
妥協なきアーキテクチャで、真に堅牢なシステムを構築せよ。
