スクリプトを「システム」へ昇華させよ:図面・DB・PDMを繋ぐ双方向同期ファクトリーの設計思想
設計現場の自動化を志すエンジニアが、最初にぶつかる壁がある。それは「動くスクリプトは書けても、壊れないシステムは書けない**」という現実だ。
単発のプロパティ書き換えマクロなら、誰でも書ける。しかし、数千件の部品を抱えるエンタープライズ環境において、SQLデータベースやPDM(Product Data Management)と連携し、図面の属性情報を「マスターデータ」と完全に同期させる。この「双方向リアルタイム同期ファクトリー」の構築は、もはや単なるVBAの範疇を超え、システムアーキテクチャの領域である。
本記事では、型番や属性情報の不一致という設計現場の致命的なリスクを根絶するための、堅牢な自動化システムの設計指針と実装コードを伝授する。
1. アーキテクチャの要:Single Source of Truth (SSoT)
多くの開発者が犯す最大の過ちは、図面ファイル(Drawing)を「データの持ち主」だと勘違いすることだ。
図面はあくまで、設計情報を可視化するための「ビュー(View)」に過ぎない。データの真の持ち主(Single Source of Truth)は、SQLデータベース、あるいはPDMのデータベースであるべきだ。
構築すべき同期フロー
1. Downstream Sync (DB $\to$ Drawing): DBのマスター情報を読み取り、図面シートのプロパティ、タイトルブロック、さらには図面構成自体を動的に生成する。
2. Upstream Sync (Drawing $\to$ DB): 図面上で承認されたステータスや、設計者が更新した属性情報を、図面保存時または特定のトリガーによりDBへ書き戻す。
このフローにおいて、「図面が書き換わったからDBを直す」のではなく、「DBが正解であり、図面をそれに強制的に合わせる」という思想を徹底しなければ、データの整合性は必ず崩壊する。
2. 堅牢な設計のための3つの鉄則
プロフェッショナルのコードには、以下の3要素が組み込まれている。
① トランザクションとエラーハンドリングの分離
DB操作とSolidWorks API操作は、エラーの性質が全く異なる。APIは「オブジェクトが存在しない」といった実行時エラーが多く、DBは「接続タイムアウト」や「デッドロック」が起こる。これらを混同して一つの `On Error Resume Next` で済ませるような設計は、バグの温床でしかない。
② 接続のライフサイクル管理
DB接続(ADODB.Connection)をグローバル変数として開きっぱなしにしてはいけない。リソースの枯渇、およびネットワーク瞬断時の再接続不能を招く。「必要な時に開き、処理が終わったら即座に閉じる」。これが鉄則だ。
③ APIコール・コストの最適化
`CustomPropertyManager` へのアクセスは、ループ内で何度も繰り返すべきではない。一度取得した値はメモリ(Dictionaryオブジェクト等)にキャッシュし、計算・照合を行う。SolidWorks APIの呼び出し回数を最小限に抑えることが、大規模図面処理のパフォーマンスを決定づける。
3. 実装:双方向同期エンジン(Production-Ready Code)
以下に、SQL Serverへの接続、図面へのプロパティ注入、およびステータスの書き戻しを行うための、クラスモジュール設計を意識したコード例を示す。
※このコードを動かすには、VBAの参照設定で `Microsoft ActiveX Data Objects x.x Library` が必要である。
' ==============================================================================
' Module: DrawingSyncFactory
' Description: SQL DBとSolidWorks図面間の双方向属性同期エンジン
' Author: Chief Architect
' ==============================================================================
Option Explicit
' データベース接続文字列(環境に合わせて変更)
Private Const DB_CONN_STR As String = "Provider=SQLOLEDB;Data Source=SERVER_NAME;Initial Catalog=DB_NAME;User ID=USER;Password=PASS;"
''' <summary>
''' DBからデータを取得し、図面のプロパティおよびタイトルブロックを更新する
''' </summary>
Public Sub SyncDownstream(swApp As SldWorks.SldWorks, drawingPath As String)
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swCustPropMgr As SldWorks.CustomPropertyManager
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim partNumber As String
On Error GoTo ErrorHandler
' 1. 図面ファイルのロード
Set swModel = swApp.OpenDoc6(drawingPath, swDocDRAWING, swOpenDocOptions_Silent, "", 0, 0)
If swModel Is Nothing Then Err.Raise 1001, , "図面ファイルを開けませんでした。"
Set swDraw = swModel
' 2. 図面からPartNumber(キー)を取得
' ※図面自体のプロパティから、紐づく部品の型番を取得する設計
Set swCustPropMgr = swModel.Extension.CustomPropertyManager("")
swCustPropMgr.Get4 "PART_NUMBER", False, "", partNumber
If partNumber = "" Then Err.Raise 1002, , "型番(PART_NUMBER)が図面に見つかりません。"
' 3. DB接続とデータ取得
Set conn = New ADODB.Connection
conn.Open DB_CONN_STR
Set rs = New ADODB.Recordset
' SQL Injectionを防ぐため、本来はパラメータクエリを使用すべきだが、ここでは簡略化
Dim sql As String
sql = "SELECT Material, Revision, Status FROM PartMaster WHERE PartNumber = '" & partNumber & "'"
rs.Open sql, conn, adOpenStatic, adLockReadOnly
If rs.EOF Then
MsgBox "DBに該当の型番が見つかりません: " & partNumber, vbCritical
GoTo CleanUp
End If
' 4. 図面へのプロパティ反映 (Downstream Sync)
' 取得した値を図面のカスタムプロパティへ書き戻す
Debug.Print "Syncing Part: " & partNumber
swCustPropMgr.Add3 "MATERIAL", swCustomInfoType_e.swCustomInfoText, rs.Fields("Material").Value & "", swCustomPropertyAddOption_e.swCustomPropertyReplaceValue
swCustPropMgr.Add3 "REVISION", swCustomInfoType_e.swCustomInfoText, rs.Fields("Revision").Value & "", swCustomPropertyAddOption_e.swCustomPropertyReplaceValue
' 5. 保存
swModel.Save3 swSaveAsOptions_e.swSaveAsOptions_Silent, 0, 0
MsgBox "同期完了: " & partNumber, vbInformation
CleanUp:
' リソースの確実な解放
If Not rs Is Nothing Then If rs.State = adStateOpen Then rs.Close
Set rs = Nothing
If Not conn Is Nothing Then If conn.State = adStateOpen Then conn.Close
Set conn = Nothing
Exit Sub
ErrorHandler:
MsgBox "致命的なエラーが発生しました:" & vbCrLf & Err.Description, vbCritical
Resume CleanUp
End Sub
''' <summary>
''' 図面の変更(ステータス等)をDBへ書き戻す
''' </summary>
Public Sub SyncUpstream(swApp As SldWorks.SldWorks, drawingPath As String)
Dim swModel As SldWorks.ModelDoc2
Dim swCustPropMgr As SldWorks.CustomPropertyManager
Dim conn As ADODB.Connection
Dim partNumber As String
Dim newStatus As String
On Error GoTo ErrorHandler
Set swModel = swApp.OpenDoc6(drawingPath, swDocDRAWING, swOpenDocOptions_Silent, "", 0, 0)
Set swCustPropMgr = swModel.Extension.CustomPropertyManager("")
' 図面上の現在のステータスを取得
swCustPropMgr.Get4 "WORKFLOW_STATUS", False, "", newStatus
swCustPropMgr.Get4 "PART_NUMBER", False, "", partNumber
If partNumber = "" Or newStatus = "" Then
MsgBox "同期に必要なプロパティが不足しています。", vbExclamation
Exit Sub
End If
' DBへの書き戻し (Upstream Sync)
Set conn = New ADODB.Connection
conn.Open DB_CONN_STR
Dim sql As String
' 実際の運用では、更新対象を限定するWHERE句とトランザクション管理が必須
sql = "UPDATE PartMaster SET Status = '" & newStatus & "' WHERE PartNumber = '" & partNumber & "'"
conn.Execute sql
MsgBox "DBステータスを更新しました: " & newStatus, vbInformation
CleanUp:
If Not conn Is Nothing Then If conn.State = adStateOpen Then conn.Close
Set conn = Nothing
Exit Sub
ErrorHandler:
MsgBox "DB書き戻しエラー: " & Err.Description, vbCritical
Resume CleanUp
End Sub
4. アーキテクトの視点:運用における「落とし穴」
このシステムを実戦投入する際、エンジニアが考慮すべきはコードの記述量ではない。「例外的な状況」をいかに定義するかだ。
1. 同時実行制御 (Concurrency Control):
複数のユーザーが同時に同じ部品の図面を更新し、DBへ書き戻そうとした場合、データが上書きされる可能性がある。DB側での `RowVersion`(タイムスタンプ)による楽観的ロック、あるいはPDMのチェックイン/アウト機能と連携した排他制御を必ず設計に組み込め。
2. ネットワークの不確実性:
工場内のWi-FiやVPNは、常に不安定である。`conn.ConnectionTimeout` を適切に設定し、接続失敗時に「リトライするのか」「ユーザーに通知して中断するのか」のポリシーを明確にせよ。
3. 監査ログ (Audit Trail):
「誰が、いつ、どの図面から、どの値をDBへ変更したか」のログを、図面プロパティではなく、DB側の履歴テーブルに記録せよ。これがなければ、データ不整合が起きた際に原因究明が不可能になる。
結論
図面自動化の極致とは、SolidWorksの操作術を知ることではない。「データがどこに存在し、どう流れるべきか」という情報のライフサイクルを支配することにある。
今回提示した「同期ファクトリー」の設計思想を武器に、単なる「便利ツール」の作成者から、企業のインフラを支える「システムアーキテクト」へと進化してほしい。
