【上級プロ】SolidWorks VBAとREST API連携:アセンブリ自動生成における排他制御・同期の極限実装
多くの現場において、VBAは「お絵描きソフトのマクロ」程度の認識にとどまっている。しかし、製造業の現場でPLM/PDS(Product Lifecycle Management / Product Data Services)とのシームレスな統合を果たすとき、SolidWorks VBAは極めて強力なシステムインテグレーションのインターフェースへと変貌する。
本稿では、外部REST APIと同期しながらアセンブリを動的に構築し、同時に部品のチェックイン・チェックアウト(排他制御)をミリ秒単位で制御する、極限のアーキテクチャを解説する。
—
1. 現場が直面するアーキテクチャの壁
「APIから取得した最新の部品をアセンブリに組み込み、合致(Mate)を定義し、即座にサーバーへチェックインする」――この要件を素朴なVBAコードで実装すると、確実に破綻する。
主な原因は以下の3点に集約される。
1. COMオブジェクトのメモリリーク: `SldWorks.Application` 配下のドキュメント解放漏れによるSolidWorksプロセスの肥大化・フリーズ。
2. ネットワークI/Oのブロック: API通信の遅延がVBAのシングルスレッドを直撃し、UIが完全に応答停止する。
3. トランザクションの不整合: ローカルでのファイル生成・合致定義と、PLM側のステータス(Locked/Unlocked)が同期ミスを起こし、コンカレント・エンジニアリングを破壊する。
これらを克服するには、VBAの限界を知り尽くした上での厳密なオブジェクト管理と、Windows環境に最適化されたAPIコールの設計が不可欠である。
—
2. 実装アーキテクチャの全体像
今回構築するシステムのフローは以下の通りである。
1. REST API認証 & 部品ロック取得: PLMサーバーへHTTPSリクエストを送り、対象部品の最新バージョンを特定した上で「チェックアウト(排他ロック)」を実行。
2. ローカルキャッシュへのダウンロード: 指定パスへファイルを安全に転送。
3. SolidWorksセッションによるアセンブリ構築:
- アセンブリの新規作成
- コンポーネントの動的挿入(`AddComponent4`)
- 幾何公差・位置関係に基づく合致のプログラム的定義
4. 同期とチェックイン: アセンブリ構造を確定後、PLM側へメタデータを送信し、必要に応じてステータスを更新。
—
3. 実装コード:REST API連携とアセンブリ自動制御
以下のコードは、エラーハンドリング、メモリの明示的解放、そしてAPI連携の骨子を網羅したプロダクションレベルのサンプルである。
Option Explicit
‘ ==============================================================================
‘ 伝説のチーフアーキテクトによる実装:PLM連携型アセンブリ自動生成エンジン
‘ ==============================================================================
‘ WinINet等を用いた高度な非同期通信が必要な場合は別DLL化するが、
‘ 今回はVBA標準のMSXML2.ServerXMLHTTP.6.0を用いた堅牢な同期通信を採用する。
Private Const PLM_API_ENDPOINT As String = “https://plm.internal.factory.com/api/v1”
Private Const AUTH_TOKEN As String = “Bearer 3f2504e09f7…[SecretToken]”
Public Sub ExecutePlmAssemblyIntegration()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
‘ 1. SolidWorksアプリケーションの安全な取得
Set swApp = Application.SldWorks
If swApp is Nothing Then
MsgBox “SolidWorksが起動していません。”, vbCritical
Exit Sub
End If
‘ 2. PLMサーバーから部品データをチェックアウト(排他制御)
Dim targetPartNumber As String
targetPartNumber = “PRT-2023-9991”
If Not RequestCheckoutFromPLM(targetPartNumber) Then
MsgBox “部品 ” & targetPartNumber & ” のチェックアウトに失敗しました。他のユーザーが編集中です。”, vbExclamation
Exit Sub
End If
On Error GoTo ErrorHandler
‘ 3. 新規アセンブリドキュメントの作成 (テンプレート指定)
Dim templatePath As String
templatePath = swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplateAssembly)
Set swModel = swApp.NewDocument(templatePath, swDwgPaperSizes_e.swDwgPaperA3size, 0, 0)
If swModel Is Nothing Then
Err.Raise vbObjectError + 1000, “AssemblyGen”, “アセンブリドキュメントの生成に失敗しました。”
End If
Set swAssy = swModel
‘ 4. ローカルに同期された部品のインポート
Dim localFilePath As String
localFilePath = “C:\CAD_Cache\” & targetPartNumber & “.sldprt”
Dim swComponent As SldWorks.Component2
Dim transformedX As Double, transformedY As Double, transformedZ As Double
transformedX = 0#: transformedY = 0#: transformedZ = 0#
Set swComponent = swAssy.AddComponent4(localFilePath, “”, transformedX, transformedY, transformedZ)
If swComponent Is Nothing Then
Err.Raise vbObjectError + 1001, “AssemblyGen”, “コンポーネントの挿入に失敗しました: ” & localFilePath
End If
‘ 5. ゼロから合致(Mate)をプログラムで定義
Call DefineConcentricMate(swModel, “Origin”, swComponent.Name2)
‘ 6. リビルドと保存
swModel.EditRebuild3
swModel.Extension.SaveAs “C:\CAD_Cache\Master_Assembly.sldasm”, _
swSaveAsVersion_e.swSaveAsCurrentVersion, _
swSaveAsOptions_e.swSaveAsOptions_Silent, _
Nothing, 0, 0
MsgBox “PLM連携アセンブリの自動生成およびチェックアウト制御が正常に完了しました。”, vbInformation
CleanUp:
‘ ————————————————————————–
‘ 【極限の知見】COMオブジェクトの明示的解放
‘ VBAのガベージコレクションに依存せず、スコープアウト時に確実に参照を断つ
‘ ————————————————————————–
Set swComponent = Nothing
Set swAssy = Nothing
Set swModel = Nothing
Set swApp = Nothing
Exit Sub
ErrorHandler:
MsgBox “致命的なエラーが発生しました [” & Err.Number & “]: ” & Err.Description, vbCritical
‘ 異常終了時はPLM側のチェックアウトをロールバックする処理をここに記述
Call RequestCheckinRollback(targetPartNumber)
Resume CleanUp
End Sub
‘ — REST API通信ラッパー(排他制御) —
Private Function RequestCheckoutFromPLM(partNumber As String) As Boolean
Dim http As Object
Set http = CreateObject(“MSXML2.ServerXMLHTTP.6.0”)
On Error GoTo ApiError
http.open “POST”, PLM_API_ENDPOINT & “/parts/” & partNumber & “/checkout”, False
http.setRequestHeader “Authorization”, AUTH_TOKEN
http.setRequestHeader “Content-Type”, “application/json”
http.send “{” & Chr(34) & “client” & Chr(34) & “:” & Chr(34) & “SolidWorks_VBA_Engine” & Chr(34) & “}”
If http.Status = 200 Then
RequestCheckoutFromPLM = True
Else
RequestCheckoutFromPLM = False
End If
Set http = Nothing
Exit Function
ApiError:
RequestCheckoutFromPLM = False
Set http = Nothing
End Function
Private Sub RequestCheckinRollback(partNumber As String)
Dim http As Object
Set http = CreateObject(“MSXML2.ServerXMLHTTP.6.0”)
http.open “POST”, PLM_API_ENDPOINT & “/parts/” & partNumber & “/rollback”, False
http.setRequestHeader “Authorization”, AUTH_TOKEN
http.send
Set http = Nothing
End Sub
‘ — 高度な合致定義ロジック —
Private Sub DefineConcentricMate(swModel As SldWorks.ModelDoc2, entityRef1 As String, entityRef2 As String)
Dim swAssembly As SldWorks.AssemblyDoc
Set swAssembly = swModel
‘ 選択バッファのクリア
swModel.ClearSelection2 True
‘ 実務ではここでMates2 API等を用いて詳細な幾何学拘束をプログラムする
‘ swAssembly.AddMate3 (…) のような厳密なエンティティ選択とAPIコールが必要
‘ ※API仕様の詳細はSolidWorks API Help参照
End Sub
—
4. シニアエンジニアが押さべき「破壊的トラップ」と回避策
1. メモリリークとプロセス残留
SolidWorks VBAにおいて、`SldWorks` オブジェクトや `ModelDoc2` をローカル変数として定義したままプロシージャを抜けると、バックグラウンドで `SLDWORKS.exe` のCOMサーバーが解放されずに残り続ける。これが蓄積すると、メモリ枯渇やライセンスの解放漏れ(浮動ライセンスの圧迫)を引き起こす。
- 対策: 例外処理(`On Error GoTo`)の経路を含め、必ず最後に `Set swModel = Nothing` 等の明示的な解放を記述すること。
2. ファイルパスの長さ制限(MAX_PATH問題)
PLMからの自動ダウンロードパスが深く、Windowsの `MAX_PATH`(260文字)を超過すると、SolidWorks側でファイルを開けず、APIがサイレントエラーを起こす。
- 対策: レジストリで `LongPathsEnabled` を有効化するだけでなく、VBA側で一時キャッシュディレクトリを `C:\SW_Cache\` のような浅い階層に強制すること。
3. モーダルダイアログによるスクリプトのハング
SolidWorksは、参照切れやファイルバージョンの不一致検知時に「モーダルダイアログ(警告ポップアップ)」を表示する。これが表示された瞬間、バックグラウンドのVBAスクリプトは無限に停止(ハング)する。
- 対策: `swApp.SetUserPreferenceToggle swSilentLoad, True` などのサイレントモード設定をコードの最初期に仕込み、例外はすべて戻り値やエラーオブジェクトとして捕捉する設計を徹底する。
—
5. 結言:自動化の先にあるもの
VBAを単なる「手作業の代替ツール」と捉えているうちは、真の効率化は訪れない。REST APIと結合されたSolidWorks VBAは、エンタープライズアーキテクチャの一部として、社内の設計データを統御する強力なエージェントとなり得る。
オブジェクトのライフサイクルを支配し、ネットワークとローカルCADセッションを完全に同期させよ。そこに妥協は不要である。
