CorelDRAW VBAを掌握する:レイヤー内オブジェクト集計の深淵と「メモリの作法」
CorelDRAWのオートメーションにおいて、最も初歩的かつ重要な「集計」というタスクでさえ、素人と熟練者ではコードの寿命と信頼性が決定的に異なる。
今回は、レイヤー内の全オブジェクトをカウントし、レポート化するスクリプトを例に、単なる「動くコード」から「保守可能な資産」へと昇華させるための極限の知見を授ける。
—
なぜ「ただのループ」ではいけないのか
CorelDRAWのオブジェクトモデルは階層構造(Layer -> Shape)を持つが、単に `For Each` を回せば良いというものではない。大規模なドキュメントにおいて、不用意な参照の保持はメモリリークを招き、最悪の場合、CorelDRAWのプロセス全体を不安定にさせる。
シニアエンジニアが重視すべきは以下の3点だ。
1. オブジェクトの明示的解放: `Set obj = Nothing` の徹底。
2. 型指定の最適化: バリアント型ではなく `Shape` 型で定義し、オーバーヘッドを最小化する。
3. 再帰的な走査: グループ化されたオブジェクト(`Shape.Type = cdrGroupShape`)をどう処理するか。ここが腕の見せ所となる。
—
レイヤーオブジェクト集計の実装コード
このコードは、現在のドキュメントの全ページを走査し、クラスごとにカウントするプロフェッショナル仕様のベースラインだ。
Option Explicit
‘ 伝説のアーキテクトが推奨する、型安全かつメモリ効率を考慮した集計ルーチン
Public Sub ExportLayerReport()
Dim doc As Document
Dim p As Page
Dim layer As layer
Dim shp As Shape
‘ 集計用カウンタ
Dim countVector As Long, countBitmap As Long, countText As Long
Set doc = ActiveDocument
‘ レイヤー走査のパフォーマンスを上げるため、画面描画を停止
Optimization = True
For Each p In doc.Pages
For Each layer In p.Layers
‘ レイヤー内を再帰的に走査するためのヘルパー関数を呼び出す
Call CountShapesRecursive(layer.Shapes, countVector, countBitmap, countText)
Next layer
Next p
Optimization = False
‘ レポート出力
MsgBox “オブジェクト集計完了:” & vbCrLf & _
“ベクター: ” & countVector & vbCrLf & _
“ビットマップ: ” & countBitmap & vbCrLf & _
“テキスト: ” & countText, vbInformation, “System Report”
‘ 明示的なメモリ解放(VBAのガーベジコレクションを信じないのが鉄則)
Set doc = Nothing
End Sub
Private Sub CountShapesRecursive(shapes As shapes, ByRef v As Long, ByRef b As Long, ByRef t As Long)
Dim s As Shape
For Each s In shapes
Select Case s.Type
Case cdrCurveShape, cdrRectangleShape, cdrEllipseShape
v = v + 1
Case cdrBitmapShape
b = b + 1
Case cdrTextShape
t = t + 1
Case cdrGroupShape
‘ グループ内は再帰的に潜る。これが正確性を担保する要諦
Call CountShapesRecursive(s.Shapes, v, b, t)
End Select
Next s
‘ 参照の解放
Set s = Nothing
End Sub
—
シニアエンジニアが知るべき「現場の極意」
1. Optimization = True の重み
CorelDRAW VBAにおいて `Optimization = True` は単なる描画停止ではない。内部的な「更新通知」を抑制し、DOMへのアクセス頻度を劇的に減らす。数万オブジェクトが存在するファイルでは、これがないだけで処理時間に10倍以上の差が出る。
2. 再帰処理の限界管理
このスクリプトはグループ化にも対応しているが、極端に深い入れ子構造(ネスト)を持つファイルではスタックオーバーフローのリスクがある。業務システムで扱う場合は、スタックサイズを意識するか、ループベースのスタック管理を行うのが「伝説級」の解法となる。
3. Windows APIとの連携(今後の展望)
もしこのカウント結果を外部データベースへ送信したり、ログファイルとして出力したい場合、`Win32 API` の `Kernel32.dll` を呼び出し、メモリマップドファイルを利用してプロセス間通信を行うのが、より高度なシステム連携の定石だ。
—
結びに:コードは「生き物」である
今回提供したコードはあくまで「始まり」に過ぎない。君たちが現場で直面するであろう「謎のクラッシュ」や「極端な低速化」は、CorelDRAWの仕様の隙間に潜んでいる。
常に `Set obj = Nothing` を忘れず、オブジェクトのライフサイクルを制御下に置くこと。それが、この過酷なVBA開発の荒野を生き抜くための唯一の武器となる。
次は、この集計結果をCSVに書き出し、外部のPythonデータ分析基盤へとシームレスに連携させるアーキテクチャについて語ろうか。準備ができたら、またここへ戻ってくるといい。
