混沌としたベクターデータの浄化:CorelDRAW VBAによる「テキスト断片」の完全統合術
CAD図面からのDXFインポート、あるいはPDF変換を経たデータ。それらがもたらす悪夢は常に同じだ。本来は一連の文章であるはずのテキストが、改行やフォント属性の差異によって数千個の「断片化されたオブジェクト」へと解体されている。
この惨状を前に、手作業で統合を試みるのはエンジニアのすることではない。我々はCorelDRAWの内部構造を掌握し、メモリを制御し、アルゴリズムによって秩序を取り戻す。
今回は、座標ソートに基づき、バラバラのテキストフレームを論理的な読順で再構築する「データ浄化スクリプト」の極意を伝授する。
—
1. 空間認識とソートアルゴリズムの罠
テキストの読順(左から右、上から下)を決定するには、単なる座標比較では不十分だ。特にCADデータは、微妙なY座標のズレが隣接行の判定を狂わせる。
ここで重要なのは、「許容範囲(Tolerance)」を設けた二段階ソートである。
1. 第一階層: Y座標でグループ化(一定の誤差内は同一行とみなす)
2. 第二階層: 各グループ内でX座標順にソート
このロジックを実装することで、見た目上の自然な読順を抽出可能になる。
—
2. 実装:テキスト統合の極致
以下に、メモリ効率と実行速度を意識した、プロダクションコードの骨子を示す。
‘ 伝説的なデータ浄化スクリプト: 選択中のテキストを読順に統合する
Sub ConsolidateTextFrames()
Dim s As Shape, sr As ShapeRange
Dim i As Long, j As Long
Dim textArray() As Shape
Dim combinedText As String
‘ 最適化: 画面更新を停止し、処理速度を向上させる
Optimization = True
EventsEnabled = False
Set sr = ActiveSelectionRange
If sr.Count < 2 Then Exit Sub
' 1. オブジェクトを配列に格納(コレクションより配列が高速)
ReDim textArray(1 To sr.Count)
For i = 1 To sr.Count
Set textArray(i) = sr(i)
Next i
' 2. 座標によるバブルソート(※小規模なら十分。数千個ならクイックソートへ換装せよ)
' 実務上の極意: Y座標の許容誤差(行とみなす範囲)を適宜設定
Dim temp As Shape
For i = 1 To UBound(textArray) - 1
For j = i + 1 To UBound(textArray)
' 上から下、左から右への並び替え
If (textArray(i).TopY < textArray(j).TopY - 0.1) Or _
(Abs(textArray(i).TopY - textArray(j).TopY) < 0.1 And textArray(i).LeftX > textArray(j).LeftX) Then
Set temp = textArray(i)
Set textArray(i) = textArray(j)
Set textArray(j) = temp
End If
Next j
Next i
‘ 3. テキスト抽出と結合
For i = 1 To UBound(textArray)
combinedText = combinedText & textArray(i).Text.Story.Text & vbCrLf
‘ 不要になった断片を削除
textArray(i).Delete
Next i
‘ 4. 新規テキストフレームの生成
Dim shp As Shape
Set shp = ActiveLayer.CreateParagraphText(0, 0, 10, 10, combinedText)
‘ 5. メモリ解放の徹底
Set sr = Nothing
Optimization = False
EventsEnabled = True
ActiveWindow.Refresh
End Sub
—
3. シニアエンジニアが押さえるべき「メモリと安定性」の知見
1. `Optimization` と `EventsEnabled` の真実
CorelDRAWのVBAにおいて、この2つのフラグを操作しないのは素人である。特に `Optimization = True` は、描画の再計算を抑制し、処理時間を1/100以下に短縮する。これを忘れると、数千個のオブジェクト削除のたびにGPUが悲鳴を上げ、最悪の場合はハングアップする。
2. オブジェクトの明示的破棄
VBAのガベージコレクションを信用してはならない。特に `ShapeRange` や `Text` オブジェクトは、スコープを抜けてもメモリ上に残滓を残すことが多い。`Set obj = Nothing` をループの最後で行う癖をつけること。これは大規模なCADデータ処理におけるメモリリークを防ぐ唯一の防波堤だ。
3. Windows APIによる拡張
もし、数万個規模のオブジェクトを扱う必要があるなら、標準のVBAソートでは限界が来る。その場合は、`kernel32.dll` の `RtlMoveMemory` を呼び出し、メモリポインタを直接操作してソートアルゴリズムをC言語並みの速度で実装する道もある。しかし、それは「最後の手段」だ。保守性を考慮すれば、まずは上記のようなアルゴリズムの最適化で勝負すべきである。
—
結びに:技術は「道具」であれ
自動化とは単なる省力化ではない。「人間の認知能力を超えたデータ処理を、エラーなく完遂させること」だ。
今回のスクリプトをテンプレートとして、貴殿の現場にある「負の遺産」を整理してほしい。コードは語る。書いた者の技術水準を、そして、その者がどれだけ「システム」というものを敬愛しているかを。
健闘を祈る。
