【テクニカル・上級編】【上級プロ向け】外部リレーショナルデータベース(SQL Server)と完全同期した社内ベクターパーツ管理システム – CorelDRAW VBA解析バイブル

スポンサーリンク

CorelDRAW VBAを掌握する極限の知見:SQL Server完全同期型ベクターパーツ管理システム

レガシーとモダンが交錯するエンタープライズの現場において、デザインアセットの散逸は永遠の課題だ。「あのロゴの最新版はどこだ」「共有フォルダのどこに社内共通パーツがあるかわからない」――こうした属人化を排除し、デザインプロセスをサプライチェーンの一部として組み込むためには、CorelDRAWと外部リレーショナルデータベース(RDB)を直結させたアセット管理システムの構築が不可欠となる。

本稿では、CorelDRAW VBAとSQL Server(ADO)を完全同期させ、メモリリークを極限まで排除したプロフェッショナル向けベクターパーツ管理システムのアーキテクチャを詳説する。

1. アーキテクチャ概略:なぜ「ファイル共有」ではなく「SQL Server」なのか

多くの現場では、共通パーツをネットワーク上の共有フォルダにCDRファイルとして乱雑に配置している。しかし、ファイルサーバーはトランザクションを保証せず、並行書き込みによる破損、タグ検索の欠如、バージョン管理の不徹底を招く。

本システムでは、ベクターデータそのものをバイナリ(VARBINARY(MAX))としてSQL Serverに格納し、メタデータ(パーツ名、カテゴリ、タグ、最終更新者)をリレーショナルに管理する。CorelDRAW側からは、ADO(ActiveX Data Objects)を介して非同期に近い速度でクエリを発行し、必要なパーツのみをオンデマンドでドキュメントへロード、あるいは逆方向の同期(アップサート)を実行する。

2. 実装:SQL Server接続とバイナリ・ストリーム処理の極意

VBAにおける最大の罠は、COMオブジェクトのライフサイクル管理の甘さによるメモリリークと、ADOによるバイナリチャンクのメモリ効率の悪さである。以下の実装では、エラーハンドリングを徹底し、メモリの爆発を防ぐための定石を網羅している。

データベース通信モジュール (`modDatabase.bas`)

Option Explicit

‘ 接続文字列の定数化(環境に合わせて変更してください)
Private Const CONNECTION_STRING As String = _
“Provider=SQLOLEDB;Server=db_server_name;Database=VectorAssetsDB;Uid=app_user;Pwd=secure_password;”

Public Function OpenDatabaseConnection() As Object
Dim conn As Object
On Error GoTo ErrorHandler

Set conn = CreateObject(“ADODB.Connection”)
conn.ConnectionTimeout = 15
conn.CommandTimeout = 30
conn.Open CONNECTION_STRING

Set OpenDatabaseConnection = conn
Exit Function

ErrorHandler:
If Not conn Is Nothing Then
If conn.State = 1 Then conn.Close
Set conn = Nothing
End If
Err.Raise Err.Number, “OpenDatabaseConnection”, “DB接続に失敗しました: ” & Err.Description
End Function

Public Sub CloseDatabaseConnection(ByRef conn As Object)
On Error Resume Next
If Not conn Is Nothing Then
If conn.State = 1 Then conn.Close
Set conn = Nothing
End If
On Error GoTo 0
End Sub

3. コアロジック:CorelDRAWドキュメントとDB間のシームレスな同期

パーツを登録する際は、アクティブ選択図形を一時的にローカルのテンポラリCDRとして書き出し、そのバイナリモジュールをSQL Serverへ流し込む。逆にインポート時は、DBからバイナリをADOストリーム経由で一時ファイルに戻し、`ActiveLayer.LoadEx`でインポートする。

アセットマネージャーモジュール (`modAssetManager.bas`)

Option Explicit

‘ 選択図形をSQL Serverへバイナリとして登録・更新(Upsert)する
Public Sub SyncSelectedAssetToDB(ByVal assetName As String, ByVal category As String)
Dim conn As Object
Dim cmd As Object
Dim stream As Object
Dim tempPath As String
Dim s As ShapeRange

‘ 1. 選択チェック
If ActiveSelection.Shapes.Count = 0 Then
MsgBox “同期するベクターパーツを選択してください。”, vbExclamation
Exit Sub
End If

On Error GoTo ErrorHandler

‘ 2. 一時ファイルのパス生成
tempPath = Environ(“TEMP”) & “\corel_sync_temp.cdr”

‘ 3. 選択図形を一時CDRとしてエクスポート(CorelDRAW 2019以降対応の形式を指定)
Set s = ActiveSelectionRange
s.Export tempPath, cdrCDR, cdrSelection, , , 0 ‘ 圧縮オプション等は環境に依存

‘ 4. DB接続とADODB.Streamによるバイナリ読み込み
Set conn = OpenDatabaseConnection()
Set stream = CreateObject(“ADODB.Stream”)

stream.Type = 1 ‘ adTypeBinary
stream.Open
stream.LoadFromFile tempPath

‘ 5. パラメータ化クエリによるSQLインジェクション対策とバイナリ転送
Set cmd = CreateObject(“ADODB.Command”)
Set cmd.ActiveConnection = conn

‘ ストアドプロシージャを用いたUpsert処理を想定
cmd.CommandText = “sp_UpsertVectorAsset”
cmd.CommandType = 4 ‘ adCmdStoredProc

cmd.Parameters.Append cmd.CreateParameter(“@AssetName”, 200, 1, 100, assetName) ‘ adVarChar
cmd.Parameters.Append cmd.CreateParameter(“@Category”, 200, 1, 50, category) ‘ adVarChar
cmd.Parameters.Append cmd.CreateParameter(“@AssetBinary”, 205, 2, -1, stream.Read) ‘ adLongVarBinary

cmd.Execute

‘ 6. クリーンアップ
Kill tempPath
MsgBox “パーツ [” & assetName & “] のDB同期が完了しました。”, vbInformation

GoTo Finally

ErrorHandler:
MsgBox “同期処理中に致命的なエラーが発生しました: ” & Err.Description, vbCritical
If Dir(tempPath) <> “” Then Kill tempPath

Finally:
‘ オブジェクトの明示的解放(メモリリーク防止の鉄則)
If Not stream Is Nothing Then
stream.Close
Set stream = Nothing
End If
Set cmd = Nothing
CloseDatabaseConnection conn
End Sub

‘ DBからパーツを非同期風にインポートする
Public Sub ImportAssetFromDB(ByVal assetID As Long)
Dim conn As Object
Dim rs As Object
Dim stream As Object
Dim tempPath As String

On Error GoTo ErrorHandler

tempPath = Environ(“TEMP”) & “\corel_import_temp.cdr”

Set conn = OpenDatabaseConnection()
Set rs = CreateObject(“ADODB.Recordset”)

rs.Open “SELECT AssetBinary FROM VectorAssets WHERE AssetID = ” & assetID, conn, 0, 1 ‘ adOpenForwardOnly, adLockReadOnly

If Not rs.EOF Then
Set stream = CreateObject(“ADODB.Stream”)
stream.Type = 1 ‘ adTypeBinary
stream.Open
stream.Write rs.Fields(“AssetBinary”).Value
stream.SaveToFile tempPath, 2 ‘ adSaveCreateOverWrite

‘ CorelDRAWドキュメントへのインポート
ActiveLayer.LoadEx tempPath, cdrCDR

Kill tempPath
Else
MsgBox “指定されたIDのパーツが見つかりません。”, vbExclamation
End If

GoTo Finally

ErrorHandler:
MsgBox “インポートエラー: ” & Err.Description, vbCritical
If Dir(tempPath) <> “” Then Kill tempPath

Finally:
If Not stream Is Nothing Then
stream.Close
Set stream = Nothing
End If
If Not rs Is Nothing Then
If rs.State = 1 Then rs.Close
Set rs = Nothing
End If
CloseDatabaseConnection conn
End Sub

4. チーフアーキテクトの知見:VBAにおけるメモリ最適化とガベージコレクションのハック

CorelDRAW VBAで数万回に及ぶアセット操作や巨大なベクターデータの処理を行う際、最も恐れなければならないのは「VBAランタイムのメモリリーク(COMラッパーの蓄積)」である。

1. `Nothing` 代入の厳密なスコープ管理

VBAは参照カウンタ方式でメモリ管理を行っているが、ローカルスコープを抜けるまでオブジェクト変数がメモリ上に残るケースがある。特にループ内でのADOオブジェクトやCorelDRAWの Shape / ShapeRange オブジェクトの生成は、数イテレーションでメモリ枯渇(Out of Memory)を引き起こす。
ループ内でCOMオブジェクトを生成する場合は、必ず都度 `Set obj = Nothing` を実行し、さらに `Application.Optimization = True` を活用して画面描画とイベント処理を抑制すべきだ。

2. CorelDRAWの描画最適化ブロック

大量のベクターパーツを配置する際は、以下の最適化構文で囲むことで、実行速度が最大数十倍に跳ね上がる。

Sub OptimizeExecution(ByVal enable As Boolean)
With Application
.Optimization = enable
.EventsEnabled = Not enable
.ScreenRefresh
End With
End Sub

これをインポート処理の前後で挟むことにより、CorelDRAWが個々のシェイプ追加ごとに走らせる再描画や再計算のオーバーヘッドを完全に排除できる。

5. レガシー保守と将来への布石

本アーキテクチャは、CorelDRAWのバージョンが上がったとしても(COMインターフェースの互換性が保たれている限り)、SQL Server側のスキーマを拡張することで半永久的に耐えうるシステムとなる。
また、将来的にVBAから.NET Framework / .NET Core製のアドイン(COM Add-in)へ移行する際も、このデータベース設計(`VARBINARY` による一元管理)をそのまま流用できるため、技術的負債を残さない。

真のエンジニアリングとは、枯れた技術(VBA)と堅牢なインフラ(SQL Server)を極限までチューニングし、現場の生産性を暴力的に引き上げることに他ならない。コードの行間に宿る意図を汲み取り、今すぐ実務の現場へ実装してほしい。

タイトルとURLをコピーしました