デザインの現場において、数百ページに及ぶカタログや、無数のキャッチコピーが散りばめられたポスター群から「テキストだけ」を抜き出す作業——。これを手作業で行っているとしたら、それはクリエイティブな時間に対する冒涜です。
こんにちは。業務自動化の深淵まで導くアーキテクトだ。
今日はCorelDRAW VBAを使い、デザインデータ内に点在するテキストフレームを根こそぎ抽出し、外部ファイルへ書き出す「実戦的」なスクリプトを伝授しよう。
初心者が陥りがちな「ただ動くだけのコード」と、プロが書く「堅牢で保守性の高いコード」の決定的な違いを、その目に焼き付けてほしい。
—
1. なぜ「FindShapes」を使いこなすべきなのか
CorelDRAWのドキュメント構造は、レイヤー、グループ、パワークリップ(マスク)が複雑に重なり合ったツリー構造だ。初心者はよく「全シェイプを再帰的にループで回す」という非効率な罠にハマるが、それは処理速度を著しく低下させる。
我々プロが選ぶのは、`Page.FindShapes` メソッドだ。
このメソッドは、指定した条件(今回はテキストシェイプ)に合致するオブジェクトを、階層構造を無視して一括で「ShapeRange」として引っこ抜いてくれる。この一行が、コードの可読性と実行速度を劇的に変える。
2. 堅牢な設計:外部出力における「文字化け」の防壁
テキスト抽出において最も恐ろしいのは、特殊文字や多言語(翻訳データなど)を扱う際の文字化けだ。
VBA標準の `Print #` ステートメントは、Shift-JISなどのローカルエンコードに依存するため、現代のグローバルなワークフローではリスクが高い。
今回は、実務での再利用性を考慮し、UTF-8での書き出しを可能にする `ADODB.Stream` を採用した設計にする。これが「プロダクションコード」のスタンダードだ。
—
3. 極限のプロダクションコード:全テキスト抽出スクリプト
このコードは、アクティブなドキュメントの全ページを走査し、テキスト情報をクリーンに抽出してデスクトップに保存する。
‘
‘ Module: TextExporter
‘ Description: ドキュメント内の全テキストを一括抽出し、UTF-8形式で書き出す
‘
Option Explicit
Public Sub ExportAllTextFrames()
Dim doc As Document
Set doc = ActiveDocument
‘ ドキュメントが開かれていない場合のガード
If doc Is Nothing Then
MsgBox “対象となるドキュメントが開かれていません。”, vbCritical
Exit Sub
End If
‘ パフォーマンス最適化:描画更新を停止
Optimization = True
EventsEnabled = False
Dim exportPath As String
exportPath = CreateObject(“WScript.Shell”).SpecialFolders(“Desktop”) & “\ExtractedText_” & Format(Now, “yyyymmdd_hhnnss”) & “.txt”
‘ ADODB.Streamによる高信頼性ファイルI/Oの構築
Dim stream As Object
Set stream = CreateObject(“ADODB.Stream”)
With stream
.Type = 2 ‘ adTypeText
.Charset = “UTF-8”
.Open
End With
Dim pg As Page
Dim shs As Shapes
Dim sh As Shape
Dim textRange As ShapeRange
‘ 全ページをループ
For Each pg In doc.Pages
‘ ページ内の「テキストシェイプ」のみを高速に一括取得
‘ Type:=cdrTextShape により、矩形や曲線を除外
Set textRange = pg.FindShapes(Type:=cdrTextShape)
If textRange.Count > 0 Then
stream.WriteText “— Page: ” & pg.Index & ” —” & vbCrLf
‘ 抽出したテキストを書き込み
For Each sh In textRange
‘ 空のテキストフレームを除外するガードロジック
If Len(Trim(sh.Text.Story.Text)) > 0 Then
stream.WriteText “[” & sh.Name & “] ” & sh.Text.Story.Text & vbCrLf
End If
Next sh
stream.WriteText vbCrLf
End If
Next pg
‘ ファイル保存と後処理
stream.SaveToFile exportPath, 2 ‘ adSaveCreateOverWrite
stream.Close
‘ 最適化設定の解除
Optimization = False
EventsEnabled = True
MsgBox “抽出が完了しました。デスクトップを確認してください。” & vbCrLf & “保存先: ” & exportPath, vbInformation
Set stream = Nothing
End Sub
—
4. アーキテクトによるコード解説
① `Optimization = True` の魔力
CorelDRAW VBAで大量のオブジェクトを操作する場合、画面の再描画を止めなければならない。これを行わないと、一文字抽出するたびにCorelDRAWが画面を更新しようとし、処理時間が数倍から数十倍に膨れ上がる。
② `FindShapes` の精度
`pg.FindShapes(Type:=cdrTextShape)` は、グループ化された中にあるテキストや、複雑なレイヤーに隠れたテキストも逃さない。自分で再帰関数(関数の中で自分を呼ぶ処理)を書く必要がないため、バグの混入を防げる。
③ なぜ `sh.Text.Story.Text` なのか?
CorelDRAWのテキストオブジェクトには、プロパティが重層的に存在する。`Story` オブジェクトにアクセスすることで、改行コードを含む「生の文字列全体」を最も正確に取得できるからだ。
5. 実務運用のためのアドバイス
このスクリプトをベースに、さらに業務を拡張するなら以下の視点を持ってほしい。
1. データベース連携: `stream.WriteText` の部分を、SQLの `INSERT` 文生成に書き換えれば、そのまま校正管理システムや翻訳DBへの流し込みが可能になる。
2. 座標情報の付与: `sh.LeftX` や `sh.TopY` を同時に出力すれば、翻訳後のテキストを「元の位置」に自動で戻すスクリプトへの布石となる。
3. 例外処理: 特殊なシンボルフォントや、アウトライン化されたテキストは抽出できない。これらを検知してログを出す機能を追加すれば、完全なプロダクトレベルのツールへと昇華するだろう。
結論
初心者は「動くこと」に満足するが、我々エンジニアは「止まらないこと」「保守しやすいこと」に命をかける。
今回紹介した `FindShapes` と `ADODB.Stream` の組み合わせは、CorelDRAWオートメーションにおける一つの「正解」だ。
このコードをただコピペするのではなく、なぜこの設計にしたのかという思想を汲み取ってほしい。それが、君を「単なるオペレーター」から「自動化のアーキテクト」へと引き上げる唯一の道だ。
