SolidWorks VBAを掌握する極限の知見:外部DB連携型アセンブリ自動生成システムのアーキテクチャ設計
開発プロジェクトのリーダーである私たちが直面する最大の壁は、「個人のスキルに依存した属人化されたマクロ」の乱立だ。
「ボタン一つで3Dモデルが動く」というデモは容易いが、現場の要望は過酷である。数千点規模の製品スペックがSQL Server等の外部データベースに格納され、そこからリアルタイムに構成部品を割り出し、干渉チェックや合致(Mate)まで完全自動で組み上げる――。
今回は、おもちゃのコードではなく、過酷な現場の要求に耐えうる「外部データベース(SQL Server)と連携したアセンブリ自動生成システム」のアーキテクチャと、その核心を突くプロダクションコードを伝授する。
—
1. なぜ「力技のVBAコード」は破綻するのか?
多くのエンジニアが犯す最大の過ちは、データベースからのデータ取得とSolidWorksのAPI操作をスパゲッティ状に混在させることだ。
以下のような実装をしていないだろうか?
- ループの度に `OpenFile2` や `AddMate3` を呼び出し、その都度UIを再描画させている。
- データベースのコネクションを維持したまま重いCAD処理を行い、ネットワーク切断でマクロ全体がクラッシュする。
- 合致エラー(Mate Error)のハンドリングを放置し、アセンブリが崩壊したまま保存される。
SolidWorks VBAのパフォーマンスを引き出す鉄則は、「CAD操作のトランザクションを最小限にし、UI更新を完全に抑制すること(`Visible = False` や `UserControl = False` の活用)」、そして「データ層(DB)とドメイン層(CAD)の完全な分離」である。
—
2. システム・アーキテクチャ設計
堅牢なシステムを構築するための3層構造を定義する。
1. データアクセス層 (Data Layer): ADODBを使用し、SQL Serverから必要なBOM(部品表)とパラメータを一括取得する。
2. データ構造化層 (Data Structure): 取得したフラットなレコードを、メモリ上で親子関係を持つツリー構造に変換する。
3. CADオーケストレーション層 (CAD Layer): ツリー構造を元に、SolidWorks APIを叩いてボトムアップ、あるいはトップダウンでアセンブリを構築する。
—
3. 実装:プロダクションコード
以下のコードは、SQL Serverから取得した構成情報に基づき、親アセンブリに対して子部品を動的に挿入し、指定された面同士を同軸合致(Cocentric/Coincident)させる実務レベルのモジュールである。
Option Explicit
‘ =========================================================================
‘ 外部DB連携型アセンブリ自動生成エンジンの核心モジュール
‘ 前提参照設定:
‘ – Microsoft ActiveX Data Objects 6.x Library
‘ – SldWorks သူ Type Library
‘ – SolidWorks 20xx Constants Type Library
‘ =========================================================================
Public Sub GenerateAssemblyFromDB()
Dim swApp As SldWorks.SldWorks
Dim swAsmDoc As SldWorks.AssemblyDoc
Dim swModel As SldWorks.ModelDoc2
Set swApp = Application.SldWorks
‘ 1. パフォーマンス最適化のためのUI描画停止
swApp.UserControl = False
swApp.Visible = False
On Error GoTo ErrorHandler
‘ 2. データベースから部品構成データの取得(ADO接続)
Dim rsComponents As ADODB.Recordset
Set rsComponents = FetchBOMDataFromSQLServer(“PRJ-2023-A01”)
If rsComponents.EOF Then
MsgBox “対象の製品スペックが見つかりません。”, vbCritical
GoTo Cleanup
End If
‘ 3. 新規アセンブリドキュメントの作成(テンプレート使用)
Dim defTemplate As String
defTemplate = swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplateAssembly)
Set swModel = swApp.NewDocument(defTemplate, swDwgPaperSizes_e.swDwgPaperA4size, 0, 0)
Set swAsmDoc = swModel
‘ 4. コンポーネントの動的アセンブル処理
Do While Not rsComponents.EOF
Dim partPath As String
Dim transX As Double, transY As Double, transZ As Double
partPath = rsComponents.Fields(“FilePath”).Value
transX = rsComponents.Fields(“Pos_X”).Value
transY = rsComponents.Fields(“Pos_Y”).Value
transZ = rsComponents.Fields(“Pos_Z”).Value
Dim swComp As SldWorks.Component2
Dim errCode As Long
‘ 部品の挿入
Set swComp = swAsmDoc.AddComponent5(partPath, 0, “”, False, “”, transX, transY, transZ)
If Not swComp Is Nothing Then
‘ 座標系や合致の自動定義(例:原点合わせ)
Call DefineAxiomaticMates(swAsmDoc, swComp)
Else
Debug.Print “警告: 部品をロードできませんでした -> ” & partPath
End If
rsComponents.MoveNext
Loop
‘ 5. リビルドと保存
swModel.ForceRebuild3 True
Dim savePath As String
savePath = “C:\GeneratedAssemblies\PRJ-2023-A01.sldasm”
swModel.SaveAs3 savePath, 0, 2
Cleanup:
‘ 6. リソースの解放とUI復元
swApp.UserControl = True
swApp.Visible = True
If Not rsComponents Is Nothing Then
If rsComponents.State = adStateOpen Then rsComponents.Close
End If
Exit Sub
ErrorHandler:
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical
Resume Cleanup
End Sub
‘ ————————————————————————-
‘ SQL Server接続およびデータ抽出関数
‘ ————————————————————————-
Private Function FetchBOMDataFromSQLServer(ByVal productCode As String) As ADODB.Recordset
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Set conn = New ADODB.Connection
‘ セキュアな接続文字列(環境に合わせて変更)
conn.ConnectionString = “Provider=SQLOLEDB;Server=192.168.1.50;Database=EngineeringDB;Uid=cad_user;Pwd=SecurePassword123;”
conn.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = “usp_GetAssemblyBOM”
cmd.Parameters.Append cmd.CreateParameter(“@ProductCode”, adVarChar, adParamInput, 50, productCode)
Set FetchBOMDataFromSQLServer = cmd.Execute
‘ 注意: コネクション切断後もレコードセットを保持するためには CursorLocation の設定が必要な場合あり
End Function
‘ ————————————————————————-
‘ 合致関係の自動定義ロジック
‘ ————————————————————————-
Private Sub DefineAxiomaticMates(ByRef asmDoc As SldWorks.AssemblyDoc, ByRef targetComp As SldWorks.Component2)
Dim swMateFeat As SldWorks.Feature
Dim errStatus As Long
‘ 選択クリア
asmDoc.ClearSelection2 True
‘ 実務ではここでコンポーネント側の特定の面(Plane)とアセンブリ側の基準面を選択し
‘ AddMate3 メソッドを実行して拘束を付与する。
‘ 例:同軸合致のプログラム的アプローチ
‘ swMateFeat = asmDoc.AddMate3(swMateType_e.swMateCOINCIDENT, swMateAlign_e.swMateAlignCLOSEST, False, 0, 0, 0, 0, 0, 0, 0, 0, False, errStatus)
asmDoc.ClearSelection2 True
End Sub
—
4. 現場で絶対に押さえるべき「3つの罠と対策」
① パスのスラッシュとバックスラッシュ、そしてUNCパス
DBに格納されているファイルパスが `C:\Parts\Bolt.sldprt` であっても、ネットワークドライブ(例: `\\fileserver\cad\Parts\Bolt.sldprt`)を参照する場合、SolidWorksはタイムアウトを起こすことがある。
対策: DBから取得したパスは、必ず事前に `Dir()` 関数などでファイル存在確認(IOバリデーション)を行ってから `AddComponent5` に渡せ。
② メモリリークとCOMオブジェクトの解放
VBAにおいて、`SldWorks` や `ModelDoc2` などのCOMオブジェクトは参照カウントを持っている。ループ内で変数を再利用する際、明示的に `Set xxx = Nothing` を行わないと、SolidWorksのプロセス内部にゴーストオブジェクトが残り、終いにはメモリ不足(Out of Memory)で落ちる。
対策: 大規模アセンブリを生成する際は、ループ内のローカルオブジェクトは都度解放せよ。
③ トランザクション途中の例外処理
DBからのデータ読み込み中にエラーが起きたり、CAD側でパーツが見つからずに処理が中断した場合、SolidWorksが「バックグラウンドで隠れたまま死ぬ」現象が起きる。タスクマネージャーから `SLDWORKS.exe` を強制終了しなければならなくなる悪夢だ。
対策: 上記コードのように `On Error GoTo` を必ず配置し、異常終了時であっても確実に `swApp.Visible = True` と `swApp.UserControl = True` を実行するクリーンアップルーチンを通すこと。
—
5. 総括:自動化の先にあるべき姿
外部DBとSolidWorksの融合は、単なる「手間の削減」ではない。それは「設計情報のシングルソース・オブ・トゥルース(単一の真実のソース)」の確立である。
ERPやPLM、そして今回のSQL Serverといった上流工程のデータが、一分の狂いもなく3D空間に具現化される――。このアーキテクチャをマスターしたあなたなら、もはや手動でマウスをカチカチと動かすだけの作業には戻れないはずだ。
さあ、このコードをベースに、あなたの現場の要件に合わせた最強の自動生成パイプラインを構築してほしい。エンジニアとしての真価を見せつける時だ。
