ベクターグラフィックスの深淵へようこそ。私は、数多のレガシーシステムを解体し、自動化という名の秩序を構築してきた。
CorelDRAWは、単なるドローソフトではない。それは「座標と属性の巨大なデータベース」だ。しかし、多くのデザイナーやエンジニアは、その中に埋もれた「テキストデータ」という資産を、手動のコピペという原始的な労働で浪費している。
今回は、単一のCDRファイルから全テキストフレームを抽出し、外部ファイルへ出力するスクリプトを構築する。一見、初心者向けのテーマに見えるだろう。だが、シニアエンジニアならば理解しているはずだ。真の課題は「抽出」そのものではなく、「オブジェクトの再帰的探索」と「メモリの完全な統治」にあることを。
—
1. CorelDRAW VBAにおける「テキスト」の正体
CorelDRAWのオブジェクトモデルにおいて、テキストは`Shape`オブジェクトの一形態に過ぎない。しかし、その実体はレイヤー、グループ、あるいは「パワークリップ(PowerClip)」という名のコンテナの中に深くネスト(入れ子)されている。
初心者が陥る罠は、`ActivePage.Shapes`を単純にループで回すことだ。これではグループ化されたテキストを見落とす。プロフェッショナルは、`FindShapes`メソッド、あるいは再帰アルゴリズムを用いて、ドキュメントの全階層を走査(トラバース)しなければならない。
2. アーキテクチャの設計指針
本スクリプトでは、以下の3点を絶対的な規律とする。
1. プロセスの隠蔽と高速化: `Optimization`プロパティを制御し、画面描画のオーバーヘッドをゼロにする。
2. ストリームによるI/O管理: VBA標準の`Print #`ステートメントは、現代の多言語環境(Unicode)においては脆弱だ。今回は、UTF-8出力を保証するために`ADODB.Stream`を採用する。
3. オブジェクトのライフサイクル管理: 処理終了後、すべてのオブジェクト参照を明示的に解放し、CorelDRAWのゾンビプロセス化を防ぐ。
—
3. 極限の抽出スクリプト:TextDataExtractor
このコードは、ドキュメント内のすべてのテキスト(アーティスティックテキストおよびパラグラフテキスト)を捕捉し、指定したパスにテキストファイルとして一括出力する。
‘
‘ Module: TextDataExtractor
‘ Purpose: CorelDRAWドキュメント内の全テキストを一括抽出し、UTF-8で出力する
‘ Author: Legendary Chief Architect
‘
Option Explicit
Public Sub ExportAllTextFrames()
Dim doc As Document
Set doc = ActiveDocument
‘ ドキュメントが開かれていない場合のガードコード
If doc Is Nothing Then
MsgBox “対象となるドキュメントが存在しません。”, vbCritical
Exit Sub
End If
‘ 高速化のための環境設定
On Error GoTo ErrorHandler
Optimization = True ‘ 描画更新の停止
EventsEnabled = False ‘ イベント抑止
ActiveDocument.BeginCommandGroup “ExportText”
‘ 抽出プロセス
Dim textShapes As ShapeRange
‘ FindShapesの第1引数は名前、第2引数はType。cdrTextShapeを指定することで
‘ ネストされたグループ内も含め、すべてのテキストオブジェクトを捕捉する。
Set textShapes = doc.Pages.All.FindShapes(Type:=cdrTextShape)
If textShapes.Count = 0 Then
MsgBox “テキストオブジェクトが見つかりませんでした。”, vbInformation
GoTo Finalize
End If
‘ 出力パスの構築(ドキュメントと同じディレクトリに保存)
Dim exportPath As String
exportPath = doc.FilePath & doc.FileName & “_ExtractedText.txt”
‘ ADODB.StreamによるUTF-8書き出し
‘ ※参照設定: Microsoft ActiveX Data Objects x.x Library が必要だが、
‘ ここでは実行時バインディング(Late Binding)を採用し、環境依存を排除する。
Dim stream As Object
Set stream = CreateObject(“ADODB.Stream”)
With stream
.Type = 2 ‘ adTypeText
.Charset = “UTF-8”
.Open
Dim sh As Shape
For Each sh In textShapes
‘ Storyオブジェクトからプレーンテキストを抽出
‘ sh.Text.Story.Text は全文字、sh.Text.Story.Lines(n) で行単位の制御も可能
.WriteText “ID: ” & sh.StaticID & ” | Layer: ” & sh.Layer.Name & vbCrLf
.WriteText “Content: ” & sh.Text.Story.Text & vbCrLf
.WriteText “————————————————” & vbCrLf
Next sh
.SaveToFile exportPath, 2 ‘ adSaveCreateOverWrite
.Close
End With
MsgBox “抽出完了: ” & exportPath, vbInformation
Finalize:
‘ 正常終了時のクリーンアップ
CleanUp
Exit Sub
ErrorHandler:
MsgBox “エラー発生: ” & Err.Description, vbCritical
Resume Finalize
End Sub
Private Sub CleanUp()
‘ オブジェクトの解放と設定の復元
ActiveDocument.EndCommandGroup
EventsEnabled = True
Optimization = False
Application.Refresh
‘ 明示的なガベージコレクションの示唆
‘ VBAは参照カウンタ方式だが、大規模な場合はNothing代入が鉄則
End Sub
—
4. シニアエンジニアが注目すべき「知見」
FindShapes メソッドの戦略的優位性
`For Each`文で`Shapes`コレクションを回すのは、初心者の手法だ。CorelDRAWの`FindShapes`は、内部的に最適化された検索アルゴリズムを使用しており、グループ、シンボル、パワークリップの中まで再帰的に潜り込む。これにより、エンジニアが複雑な再帰関数を自作する手間を省き、かつバグの混入(無限ループやスタックオーバーフロー)を回避できる。
ADODB.Stream による「文字化け」の封殺
VBA標準の`Open “path” For Output As #1`は、システムのロケール(日本ではShift-JIS)に依存する。現代の翻訳ワークフローにおいて、Shift-JISはもはや負債でしかない。`ADODB.Stream`を用いることで、BOM付きUTF-8を確実に生成し、PythonやNode.jsといった後続のデータ処理パイプラインへ安全にバトンを渡すことができる。
ライフサイクルとパフォーマンス
`Optimization = True`を忘れることは、プロとしての死を意味する。数千のテキストオブジェクトを処理する場合、これ一行で処理速度は数十倍変わる。また、`BeginCommandGroup`を使用しているのは、万が一の際に「元に戻す(Undo)」を一回で済ませるためだ。これはユーザー体験(UX)への配慮である。
—
5. 結びに代えて:システム間連携の礎として
このスクリプトは、単なるテキスト抽出ツールではない。ここから正規表現による校正チェック、DeepL API等を利用した自動翻訳、あるいはデータベースとの同期システムへと拡張するための「起点」である。
レガシーなCorelDRAWという環境において、いかにモダンなデータ設計を持ち込めるか。それが、我々シニアエンジニアに課せられた使命である。
コードの背後にある「なぜそのメソッドを選んだのか」という思想を読み取ってほしい。それが、あなたを単なる「コーダー」から「アーキテクト」へと引き上げる唯一の道なのだから。
