CorelDRAW VBAの深淵:テキストオブジェクト走査における「メモリ管理と最適化」の極意
CorelDRAWの自動化において、テキストオブジェクトの走査は最も基本的でありながら、同時に最も「メモリリーク」を誘発しやすい罠だ。
多くの初学者は `ActivePage.Shapes.FindShapes` を安易にループさせ、その過程でオブジェクトを生成・破棄し続ける。だが、数千のオブジェクトが配置された複雑なプリプレスデータでそれをやれば、VBAのガベージコレクションは追いつかず、CorelDRAW自体がフリーズする。
今回は、単にフォント名を出力するだけのコードではなく、大規模環境にも耐えうる「メモリとパフォーマンスを意識した」走査ロジックを伝授する。
—
1. オブジェクト走査のボトルネックを排除せよ
CorelDRAW VBAにおいて、`Shape`オブジェクトへのアクセスは、背後でCOMのラッパーを生成している。ループ内で無造作に `Shape` 型の変数を宣言して代入し続けることは、メモリスタックの肥大化を意味する。
以下のコードは、`ActivePage` を基点に、再帰的に構造を解析し、フォント情報を抽出するプロフェッショナルなアプローチだ。
‘ 伝説のアーキテクトによる、最適化されたフォントスキャナ
Public Sub ExportUsedFonts()
Dim s As Shape
Dim fontDict As Object
Set fontDict = CreateObject(“Scripting.Dictionary”)
‘ 処理の開始:画面描画を停止し、パフォーマンスを最大化する
Optimization = True
EventsEnabled = False
‘ 再帰的にドキュメント全体を走査
Call ScanShapes(ActivePage.Shapes, fontDict)
‘ 結果を出力
Debug.Print “— 使用フォント一覧 —”
Dim key As Variant
For Each key In fontDict.Keys
Debug.Print key
Next key
‘ 終了処理:メモリ解放の重要性
Optimization = False
EventsEnabled = True
Set fontDict = Nothing
Debug.Print “解析完了。”
End Sub
Private Sub ScanShapes(shapes As Shapes, ByRef dict As Object)
Dim s As Shape
For Each s In shapes
‘ グループ化されている場合は再帰的に掘り下げる
If s.Type = cdrGroupShape Then
Call ScanShapes(s.Shapes, dict)
ElseIf s.Type = cdrTextShape Then
‘ Text.Story.Fonts プロパティでフォント情報を取得
‘ ここでオブジェクトのコピーを作らず、プロパティを直接参照する
Dim f As Font
For Each f In s.Text.Story.Fonts
If Not dict.Exists(f.Name) Then
dict.Add f.Name, 1
End If
Next f
End If
Next s
End Sub
—
2. なぜ「Optimization = True」が必要なのか
このコードの肝は、冒頭の `Optimization = True` である。
CorelDRAWのVBAエンジンは、オブジェクトが変更されるたびに画面の再描画を試みる。数千のテキストオブジェクトを走査する際、この再描画処理はCPUリソースを著しく消耗させる。`Optimization` フラグを立てることは、いわば「CorelDRAWの心臓部を一時停止」させ、解析処理に全リソースを集中させる行為だ。
3. メモリ管理とCOMオブジェクトのライフサイクル
VBAには明示的なデストラクタがない。そのため、`Set object = Nothing` を怠るエンジニアは「死んだコード」を書いているに等しい。
特に `Scripting.Dictionary` のようなCOMオブジェクトを使用する場合、走査が終わった後に必ず明示的に解放せよ。また、大規模データを取り扱う場合は、`DoEvents` をループ内に適切に配置し、Windows側のイベントキューをクリアすることで、アプリケーションの「応答なし」を防ぐ必要がある。
4. 現場のシニアエンジニアへ送るアドバイス
実務において、このスクリプトを拡張する際は以下の点に注意せよ。
- フォントの正規化: 同一フォントでも、ウェイト違いで別名として扱われる場合がある。`f.Name` だけでなく、`f.FamilyName` をキーに含めることで、プリプレス段階のミスをより高精度に検知できる。
- Windows APIの活用: もし解析速度が致命的に不足する場合は、Windows API(`EnumFontFamiliesEx`など)を直接叩き、OSレベルでフォントリストを事前キャッシュすることも視野に入れよ。
- 保守性の担保: `TextRange` プロパティを直接参照する場合、テキストが破壊されているとエラーが発生する。必ず `On Error Resume Next` で囲い込み、破損したオブジェクトをログに出力する「堅牢なエラーハンドリング」を実装すること。
—
結論
CorelDRAW VBAは、決して「おもちゃ」ではない。適切に制御されたメモリ管理と、オブジェクトのライフサイクルを理解したコードは、数万のベクターオブジェクトを秒単位で解析する強力な武器となる。
リファレンスの表面をなぞるだけの開発は卒業せよ。オブジェクトの裏側で何が起きているのか、その「質量」を感じながらコードを組むこと。それが、真の業務自動化エンジニアへの唯一の道である。
