CorelDRAW VBAを掌握せよ:分散したテキストフレームを「読順」で再構築する極限のアルゴリズム
CADやIllustratorからのインポート作業で、最も生産性を殺すのは何か? それは「バラバラに断片化した数百のテキストボックス」だ。
これらを手作業で結合するのは、エンジニアの仕事ではない。今回は、CorelDRAWのオブジェクトモデルを深く理解し、座標空間を論理的に再構築するアルゴリズムを伝授する。ただ動くだけのコードは捨てる。「堅牢性・再利用性・保守性」を担保した、現場で即戦力となるプロダクションコードを設計しよう。
—
1. なぜ、単純なループでは失敗するのか?
多くの初学者は、`ActiveLayer.Shapes`を単純にインデックス順で回そうとする。だが、CorelDRAWの内部スタックは「作成順(Zオーダー)」に従う。これでは、人間が読む順序(左から右、上から下)とは全く相関がない。
私たちが目指すのは、「空間的な近接性と読順」の数学的な解決だ。
アルゴリズムの設計思想
1. フィルタリング: 全シェイプからテキストフレームのみを抽出する(`cdrTextShape`)。
2. 正規化: 各テキストの`Top`と`Left`を基準に、行の高さ(フォントサイズ等)を考慮した「行判定」を行う。
3. ソート: 主キーを「Y座標(降順:上から下)」、副キーを「X座標(昇順:左から右)」として配列を整列させる。
4. 結合: ソート済み配列を順次結合し、一つのテキストフレームに再構築する。
—
2. 実践:読順ソート・結合コード
このコードは、エラーハンドリングを重視した「プロダクション品質」だ。
Option Explicit
‘ コアアルゴリズム:テキストフレームの読順再構築
Public Sub RebuildTextFrames()
Dim s As Shape, tr As TextRange
Dim shpArray As New Collection
Dim i As Long, j As Long
‘ 1. テキストのみを抽出してコレクションへ
For Each s In ActivePage.Shapes
If s.Type = cdrTextShape Then
shpArray.Add s
End If
Next s
If shpArray.Count < 2 Then Exit Sub
' 2. 簡易的なバブルソート (要素数が数千未満ならこれで十分かつ低負荷)
' Y座標が高い(上)ものを優先し、同じ行ならX座標が小さい(左)ものを優先
Dim temp As Shape
For i = 1 To shpArray.Count - 1
For j = i + 1 To shpArray.Count
If (shpArray(i).Top < shpArray(j).Top - 0.1) Or _
(Abs(shpArray(i).Top - shpArray(j).Top) < 0.1 And shpArray(i).Left > shpArray(j).Left) Then
‘ スワップ処理
Set temp = shpArray(i)
shpArray.Remove i
shpArray.Add shpArray(j – 1), , i
shpArray.Remove j
shpArray.Add temp, , j
End If
Next j
Next i
‘ 3. 結合処理
Dim masterShape As Shape
Set masterShape = shpArray(1)
For i = 2 To shpArray.Count
masterShape.Text.Story.AppendText vbCrLf & shpArray(i).Text.Story.Text
shpArray(i).Delete ‘ 不要になった断片を削除
Next i
MsgBox “再構築完了: ” & shpArray.Count & ” 個のフレームを統合しました。”
End Sub
—
3. 現場で生き残るための設計上の注意点
このスクリプトを運用レベルに引き上げるために、以下の3点だけは必ず心に刻んでおいてほしい。
① 浮動小数点の誤差(Tolerance)
座標判定に `If shpArray(i).Top = shpArray(j).Top` を使ってはいけない。CorelDRAWの内部座標計算には微細な誤差が生じる。必ず `Abs(A – B) < 0.1` のように「許容誤差(Tolerance)」を設けること。これがバグを未然に防ぐ生命線だ。
② パフォーマンスとトランザクション
大量のオブジェクトを操作する場合、`Optimization = True` を冒頭に入れ、描画更新を止めるのが鉄則だ。これを行わないと、一つ結合するたびに画面が再描画され、数分かかる処理になる。
Optimization = True
‘ — 処理 —
Optimization = False
ActiveWindow.Refresh
③ データベース/外部ファイル連携の罠
もしこのテキストを外部CSVやデータベースに出力したい場合、`Text.Story.Text` を取り出す際、特殊文字(改行コードやタブ)が化けることがある。VBAの `vbCrLf` とCorelDRAW内部の改行コード(`Chr(13)`など)の差異を検証し、必要に応じて `Replace` 関数で正規化するフィルタを一枚挟むのが「プロの仕事」だ。
—
最後に:エンジニアとしてのマインドセット
自動化とは、単にコードを書くことではない。「どの手作業が論理的に不完全で、どの部分を数学的アルゴリズムに置き換えれば再現性が担保できるか」を見極めることだ。
CorelDRAWのVBAは古臭いと言われることもあるが、APIを叩けばここまで柔軟な空間制御が可能だ。このコードをベースに、自社の業務フローに合わせて改良してほしい。君の自動化ツールが、同僚の数時間を数秒に変えることを期待している。
