こんにちは!SolidWorksを使った自動化の現場で、日々奮闘していませんか?
「マクロの記録」からスタートして、いざ複雑なアセンブリの自動生成や合致(Mate)の構築に挑んでみたものの……気がつけば数千行のスパゲッティコードになり、どこを直しても別の場所が壊れる。そんな悪夢のような経験、ありませんか?
今回は、そんな地獄からあなたを救い出す、「クラスモジュール」と「ファクトリーパターン」を使ったモダンなオブジェクト指向設計の極意を伝授します。
ここをクリアすれば、あなたも単なる「マクロ記録の再生係」から、拡張性極まりない「SolidWorks自動化アーキテクト」へステップアップできますよ。しっかりついてきてくださいね!
—
1. なぜ「スパゲッティコード」になるのか?
アセンブリの自動化でよくある失敗は、標準モジュール(`Module1`など)に、部品の挿入から座標計算、合致の定義まで全てを書き殴ってしまうことです。
‘ 【やってはいけない典型例:すべてがグローバルに絡み合ったスパゲッティコード】
Sub BuildAssembly_Bad()
Dim swApp As SldWorks.SldWorks
Dim swAssy As SldWorks.AssemblyDoc
‘ 延々と続く部品の追加、変数名の重複、エラー時のゾンビプロセスの嵐…
‘ どこを修正しても動かなくなる恐怖のコードの完成です。
End Sub
このアプローチの最大の問題は、「部品の種類が増えたり、合致のルールが変わったりしたときに、既存のコードを全書き直ししなければならない」という点です。
これを解決するのが、オブジェクト指向の三大要素である「カプセル化」と、デザインパターンのひとつである「ファクトリーパターン」です。
—
2. 設計の全体像:オブジェクト指向アセンブリ構築
今回目指すアーキテクチャは以下の通りです。
1. コンポーネントクラス(`MateComponent`): 挿入される部品のデータと、自己を配置する振る舞いをカプセル化。
2. ファクトリークラス(`AssemblyFactory`): 外部からの指示を受けて、適切な部品オブジェクトを生成・組み立てる責任を持つ。
3. メイン処理(`Main`): ファクトリーを呼び出すだけで、綺麗に組み立てを完了させる。
言葉だけだと難しく聞こえるかもしれませんが、実際のコードを見れば「なーんだ、こういうことか!」と腑に落ちるはずです。
—
3. 実装コード:プロフェッショナル・アーキテクチャ
それでは、実際にExcel VBAまたはSolidWorks VBAエディタに実装するコードを見ていきましょう。
Step 1: 部品をカプセル化するクラスモジュール `MateComponent`
まずは、アセンブリに配置する部品を抽象化したクラスを作ります。VBAエディタでクラスモジュールを追加し、名前を `MateComponent` にしてください。
‘ ==========================================
‘ クラスモジュール名: MateComponent
‘ 役割: 個別の部品データと合致処理のカプセル化
‘ ==========================================
Option Explicit
Private swApp As SldWorks.SldWorks
Private swAssy As SldWorks.AssemblyDoc
Private swComp As SldWorks.Component2
Private m_PartPath As String
‘ プロパティの設定
Public Property Let PartPath(ByVal path As String)
m_PartPath = path
End Property
‘ 初期化と部品の挿入(ライフサイクルの管理)
Public Function InsertComponent(ByVal assyDoc As SldWorks.AssemblyDoc, ByVal x As Double, ByVal y As Double, ByVal z As Double) As Boolean
Set swAssy = assyDoc
Set swApp = Application.SldWorks
Dim transform As SldWorks.MathTransform
‘ 簡易的に原点からのオフセットを適用して部品を挿入
Set swComp = swAssy.AddComponents3(m_PartPath, 0, x, y, z)
If swComp Is Nothing Then
InsertComponent = False
Exit Function
End If
‘ ズレを防ぐためにコンポーネントを固定(必要に応じて)
‘ swComp.Fix
InsertComponent = True
End Function
‘ 合致(Mate)を定義するメソッド
Public Sub AddCoincidentMate(ByVal targetComponent As MateComponent, ByVal faceName1 As String, ByVal faceName2 As String)
‘ 実際にはここでFace(面)を取得し、Mate2 APIを叩いて合致を定義します
‘ ※ここでは構造の美しさにフォーカスするため、概念的な実装として記述しています
Debug.Print “Mate created between components using faces: ” & faceName1 & ” and ” & faceName2
End Sub
Step 2: 組み立てを司るファクトリークラス `AssemblyFactory`
次に、複雑な組み立て手順を隠蔽するファクトリークラスを作成します。クラスモジュール名を `AssemblyFactory` としてください。
‘ ==========================================
‘ クラスモジュール名: AssemblyFactory
‘ 役割: 部品の生成と組み立てルールの抽象化(ファクトリーパターン)
‘ ==========================================
Option Explicit
Private swDoc As SldWorks.ModelDoc2
Private swAssy As SldWorks.AssemblyDoc
Public Sub Initialize(ByVal model As SldWorks.ModelDoc2)
Set swDoc = model
Set swAssy = swDoc
End Sub
‘ ファクトリーメソッド: 部品の種類に応じたオブジェクトを生成して配置
Public Function CreateAndPlacePart(ByVal partPath As String, ByVal x As Double, ByVal y As Double, ByVal z As Double) As MateComponent
Dim newPart As New MateComponent
newPart.PartPath = partPath
If Not newPart.InsertComponent(swAssy, x, y, z) Then
Err.Raise 9999, “AssemblyFactory”, “部品の挿入に失敗しました: ” & partPath
End If
Set CreateAndPlacePart = newPart
End Function
Step 3: メイン処理(標準モジュール)
標準モジュールには、これらを呼び出すだけの非常にシンプルで美しいコードを書くだけです。
‘ ==========================================
‘ 標準モジュール: MainModule
‘ 役割: エントリーポイント(極限までシンプルに)
‘ ==========================================
Option Explicit
Sub Main_SmartAssembly()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ アクティブドキュメントがアセンブリかチェック
If swModel Is Nothing Or swModel.GetType() <> swDocumentTypes_e.swDocASSEMBLY Then
MsgBox “アクティブなアセンブリドキュメントがありません。”, vbCritical
Exit Sub
End If
‘ 処理の高速化(画面描画と自動再計算を停止)
swApp.UserControl = False
swModel.Extension.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, True
On Error GoTo ErrorHandler
‘ ファクトリーのインスタンス化
Dim factory As New AssemblyFactory
factory.Initialize swModel
‘ — ここからビジネスロジック(非常に直感的!) —
Dim basePlate As MateComponent
Dim bolt As MateComponent
Set basePlate = factory.CreateAndPlacePart(“C:\Parts\BasePlate.sldprt”, 0, 0, 0)
Set bolt = factory.CreateAndPlacePart(“C:\Parts\Bolt.sldprt”, 0.1, 0, 0.05)
‘ 合致の適用
basePlate.AddCoincidentMate bolt, “TopFace”, “BottomFace”
MsgBox “アセンブリの自動構築が完了しました!”, vbInformation
ErrorHandler:
If Err.Number <> 0 Then
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End If
‘ 描画の復元
swApp.UserControl = True
swModel.Extension.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, False
swModel.WindowRedraw
End Sub
—
4. 陥りやすいエラーと回避の極意
SolidWorks APIをオブジェクト指向で扱う際、初心者が必ずハマる「罠」があります。
罠1: COMオブジェクトの解放漏れ(メモリリーク)
VBAはガベージコレクションが強力ではないため、`SldWorks`や`Component2`などのCOMオブジェクトを参照したままにすると、SolidWorksのプロセスがバックグラウンドに残ってしまいます(いわゆる「ゾンビプロセス」)。
対策として、使い終わったオブジェクトは明示的に `Set xxx = Nothing` を代入するか、スコープを適切に限定してメモリから解放しましょう。
罠2: 画面描画(Redraw)によるパフォーマンスの低下
アセンブリの合致や部品追加のたびにSolidWorksが画面を再描画していると、マクロが完了するまでにコーヒーを何杯も飲む羽目になります。
必ず上記のコードのように、処理の最初で `SetUserPreferenceToggle` や `Visible` 制御を行い、描画をロックしてから一気に処理を流すのがプロの作法です。
—
まとめ:モダンな設計でSolidWorks VBAを制す
いかがでしたか?今回はクラスモジュールとファクトリーパターンを用いて、拡張性の高いアセンブリ自動化ライブラリの骨組みを構築しました。
- 標準モジュールにベタ書きするのをやめる
- 部品や振る舞いを「クラス」に閉じ込める(カプセル化)
- 生成のロジックを「ファクトリー」に集約する
この3つを意識するだけで、あなたの書くVBAコードは見違えるほど美しく、メンテナンスしやすいものに生まれ変わります。
ここをクリアすれば、SolidWorks APIの可能性は無限大に広がります。ぜひ自分の開発環境でも試して、その圧倒的なスケーラビリティを体感してくださいね!
