【SolidWorks VBA極限解説】アセンブリの構成部品コンフィギュレーションを完全制御する技術
開発プロジェクトの現場において、アセンブリ内の特定パーツのコンフィギュレーション(構成部品のバリエーション)を手動で切り替える作業ほど、無駄でヒューマンエラーの温床になるものはない。
「A型番用の筐体に、B仕様の基板とC仕様のカバーを組み合わせて…」といったバリエーション展開を、CADオペレーターがマウス操作でポチポチと切り替えているようでは、業務効率化の「ぎ」の字もない。
今回は、SolidWorks VBAを用いてアセンブリ内の特定コンポーネントに対して、個別に異なるコンフィギュレーションをプログラムから正確かつ高速に割り当てる方法を伝授する。
ネット上の表面的なサンプルコードの寄せ集めとは一線を画す、「メモリ管理」「非効率な設計の排除」「エラーハンドリング」まで踏み込んだ、実務でそのまま使えるプロダクションコードを解説しよう。
—
1. なぜ「力技のコンフィギュレーション切り替え」は破綻するのか?
多くのVBA初心者が陥る罠が、`SelectByID2`でコンポーネントを選択し、その勢いでコンフィギュレーションを変更しようとするアプローチだ。
‘ 【アンチパターン】絶対にやってはいけないコード
boolstatus = Part.Extension.SelectByID2(“Part1-1@Assembly”, “COMPONENT”, 0, 0, 0, False, 0, Nothing, 0)
‘ ここでアクティブコンフィギュレーションを無理やり変えようとするが…
このアプローチがなぜ非効率で危険なのか。理由は以下の3点に集約される。
1. 画面描画(UI)への依存: 選択(Select)を伴う操作は、Graphics領域の描画更新やツリーのフォーカスに依存するため、実行速度が極めて遅い。
2. コンテキストの喪失: アセンブリの階層構造(サブアセンブリのネストなど)が深くなると、名前解決(Path名)が変わり、選択ミスによる暴走を引き起こす。
3. オブジェクトライフサイクルの無視: `Component2`オブジェクトを直接取得せず、文字列の選択に頼る設計は、大規模アセンブリにおいて確実にバグを生む。
堅牢な設計の要件
プロとして我々が実装すべきは、「UIを一切介さず、メモリ上のコンポーネントオブジェクトに対して直接コンフィギュレーションの変更を命じる」という設計だ。これにより、画面描画を抑制(`Visible = False` や `Freeze` 相当の処理)し、圧倒的な高速化と安定性を実現できる。
—
2. アセンブリ構造を走査し、安全にコンフィギュレーションを書き換えるアルゴリズム
アセンブリ内のコンポーネントは、ツリー構造(階層構造)を形成している。したがって、ルートアセンブリから再帰的(あるいはフラット)に `Component2` オブジェクトの配列を取得し、ターゲットとなる部品名に一致した場合のみ `SetConfiguration2` メソッドをたたく、というロジックが最も堅牢である。
プロダクションコード例
以下のコードは、指定したアセンブリ内の特定パーツ名(ファイル名ベース)を検索し、それぞれに対応するコンフィギュレーションを割り当てる実務用プロシージャだ。
Option Explicit
‘ メインエントリーポイント
Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssm As SldWorks.AssemblyDoc
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ ドキュメントが開かれているか、かつアセンブリかチェック
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “エラー”
Exit Sub
End If
If swModel.GetType <> swDocASSEMBLY Then
MsgBox “アクティブなドキュメントはアセンブリではありません。”, vbCritical, “エラー”
Exit Sub
End If
Set swAssm = swModel
‘ 画面更新を停止してパフォーマンスを極限まで引き上げる
swModel.Extension.UseExtraGraphics = True
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, True
On Error GoTo ErrorHandler
‘ — 【設定エリア】 変更対象の定義 —
‘ 実務ではここをCSVやDB、あるいはExcelシートからの読み込みに変更する
Dim targetCompName As String
Dim targetConfigName As String
targetCompName = “Bracket-1” ‘ 変更したいコンポーネント名(拡張子なし、またはインスタンス名)
targetConfigName = “Type-B_HeavyLoad” ‘ 適用したいコンフィギュレーション名
‘ コンポーネントの走査と変更実行
Call ApplyConfigurationToAssembly(swAssm, targetCompName, targetConfigName)
‘ 変更を反映するためにアセンブリを再構築
swModel.ForceRebuild3 False
MsgBox “コンフィギュレーションの適用が完了しました。”, vbInformation, “完了”
CleanUp:
‘ 画面更新を復元
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, False
swModel.Extension.UseExtraGraphics = False
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
Resume CleanUp
End Sub
‘ アセンブリ内のコンポーネントを再帰的に走査し、コンフィギュレーションを変更するコアプロシージャ
Private Sub ApplyConfigurationToAssembly(swAssm As SldWorks.AssemblyDoc, compName As String, configName As String)
Dim swModel As SldWorks.ModelDoc2
Set swModel = swAssm
‘ ルートコンポーネントを取得
Dim swRootComp As SldWorks.Component2
Set swRootComp = swAssm.GetRootComponent3(True)
If swRootComp Is Nothing Then Exit Sub
‘ 子コンポーネントの配列を取得
Dim vChildComps As Variant
vChildComps = swRootComp.GetChildren
If IsEmpty(vChildComps) Then Exit Sub
Dim i As Long
Dim swChildComp As SldWorks.Component2
For i = LBound(vChildComps) To UBound(vChildComps)
Set swChildComp = vChildComps(i)
‘ 再帰関数またはループで全階層をチェック(今回は簡潔のため直下+サブアセンブリ対応のロジック骨子)
ProcessComponentRecursive swChildComp, compName, configName
Next i
End Sub
‘ 再帰的にコンポーネントを探索して設定を変更する内部関数
Private Sub ProcessComponentRecursive(swComp As SldWorks.Component2, targetName As String, targetConfig As String)
If swComp Is Nothing Then Exit Sub
‘ コンポーネントのドキュメント名(またはインスタンス名)を取得
‘ GetPathName や Name2 を目的に応じて使い分ける
Dim fullPath As String
fullPath = swComp.GetPathName
‘ 例として、コンポーネントのファイル名(拡張子抜き)が一致するか判定
Dim compModelName As String
compModelName = GetFileNameWithoutExtension(fullPath)
If LCase(compModelName) = LCase(targetName) Then
‘ 該当パーツを発見した場合、コンフィギュレーションを変更
Dim boolstatus As Boolean
boolstatus = swComp.SetConfiguration2(targetConfig)
If Not boolstatus Then
Debug.Print “警告: コンポーネント [” & targetName & “”] に対するコンフィギュレーション [” & targetConfig & “] の適用に失敗しました。”
End If
End If
‘ サブアセンブリである場合はさらにその子を走査
Dim vChildren As Variant
vChildren = swComp.GetChildren
If Not IsEmpty(vChildren) Then
Dim j As Long
For j = LBound(vChildren) To UBound(vChildren)
ProcessComponentRecursive vChildren(j), targetName, targetConfig
Next j
End If
End Sub
‘ ユーティリティ: パスからファイル名(拡張子なし)を抽出
Private Function GetFileNameWithoutExtension(ByVal filePath As String) As String
If filePath = “” Then
GetFileNameWithoutExtension = “”
Exit Function
End If
Dim fileName As String
fileName = Mid(filePath, InStrRev(filePath, “\”) + 1)
Dim dotPos As Long
dotPos = InStrRev(fileName, “.”)
If dotPos > 0 Then
GetFileNameWithoutExtension = Left(fileName, dotPos – 1)
Else
GetFileNameWithoutExtension = fileName
End If
End Function
—
3. 実務運用における重要注意点とデータベース(外部ファイル)連携
上記のコードは単一のハードコーディングだが、実際の業務(受注生産型製品の自動生成など)では、外部のExcelマスタや生産管理DB(SQL Server等)から「どの製品型番に、どのパーツのどのコンフィギュレーションを割り当てるか」を読み込ませるアーキテクチャが必須となる。
ここでチーフアーキテクトとして、現場で必ず直面する「落とし穴」を先回りして共有しておこう。
1. メモリ不足(Out of Memory)とコンポーネントの軽量化
大規模アセンブリ(数千パーツ)に対してコンフィギュレーションを一斉に変更する場合、すべての部品モデルをメモリ上に完全ロード(Resolve)すると、PCのメモリが枯渇しSolidWorksごとクラッシュする。
- 対策: 処理を行う前に、対象コンポーネントが「軽量(Lightweight)」状態である場合、必要に応じて `SetSuppression2` やロード状態を制御するか、API側で自動解決される挙動を把握しておくこと。基本的には、変更対象のコンポーネントのみを的確にピンポイントで操作するアルゴリズムにすること。
2. 存在しないコンフィギュレーション名を指定した時の挙動
`SetConfiguration2` は、存在しないコンフィギュレーション名が渡された場合、`False`を返し、サイレントに失敗するか、デフォルトのコンフィギュレーションにフォールバックする。
- 対策: 事前に `ModelDoc2::GetConfigurationNames` などを叩いて、対象の部品ドキュメント(`swComp.GetModelDoc2`)に指定のコンフィギュレーションが存在するかをバリデーションする防衛的コード(Guard Clause)を必ず挟むこと。
‘ 厳密なバリデーションの例(抜粋)
Dim swCompModel As SldWorks.ModelDoc2
Set swCompModel = swComp.GetModelDoc2
If Not swCompModel Is Nothing Then
Dim configNames As Variant
configNames = swCompModel.GetConfigurationNames
‘ Array内に targetConfig が存在するかチェックするロジックをここに挿入
End If
—
4. チーフアーキテクトからの総括
SolidWorks VBAによるアセンブリ自動化は、単なる「手作業の置き換え」ではない。それは「CADデータの構造を完全に理解し、APIというダイレクトな神経回路を通じて、意のままにモデルを構築・変形させるエンジニアリング」である。
今回解説した再帰的走査と、UIを排したダイレクトなオブジェクト操作の組み合わせをマスターすれば、何百点もあるアセンブリのバリエーション違いを、わずか数秒で、ヒューマンエラーゼロで生成することが可能になる。
あなたのデスクトップで、今すぐこのコードを検証し、退屈な手作業の地獄から設計者たちを解放してやってほしい。
