【実務・中級編】【上級プロ】インポートされた無秩序なSTEPアセンブリのツリー構造を解析し、VBAの再帰アルゴリズムで適切なサブアセンブリ階層へ自動再構築 – SolidWorks VBA解析バイブル

スポンサーリンク

【SolidWorks VBAを掌握する極限の知見】
インポートされた巨大STEPアセンブリを再帰アルゴリズムで自動構造化する

他のCADシステムから吐き出されたSTEPファイルをSolidWorksにインポートしたとき、エンジニアなら誰もが絶望する。そこにあるのは、何千ものコンポーネントが単一の階層に平坦(フラット)に並べられた「無秩序なゴミの山」だ。

「このボルトとブラケットをサブアセンブリにまとめたい」
「パーツ名や座標の近接度から、論理的なツリー構造を自動で再構築してほしい」

手作業でこれをやれば何時間、あるいは何日もかかる。しかし、我々はプロの自動化エンジニアだ。SolidWorks APIの深層を理解し、「再帰アルゴリズム(Recursive Algorithm)」をVBAに実装すれば、この地獄のような作業を数秒で終わらせることができる。

今回は、実務の現場で即座に使える、極限まで堅牢にチューニングされたアセンブリ再構築システムの設計思想とプロダクションコードを伝授する。

—

1. なぜ「フラットなアセンブリ」はVBAの鬼門なのか?

素人が書いたアセンブリ操作マクロは、決まって途中でフリーズするか、巨大なメモリリークを起こしてSolidWorksごとクラッシュする。理由は明確だ。「アセンブリのツリー構造が変わる瞬間に、オブジェクトのポインタが無効化される」というAPIの仕様を理解していないからだ。

致命的な罠:コンポーネントのライフサイクル

アセンブリ内で部品を移動させたり、新しいサブアセンブリを作成して放り込んだりすると、SolidWorks内部の`IComponent2`ポインタの参照先がガラリと変わる。
これを考慮せず、配列やコレクションに古いポインタを保持したまま処理を続行すると、Access Violation(メモリ違反)を引き起こす。

解決のアプローチ

1. 事前解析(Analyze): まずアセンブリの全コンポーネントの空間座標(Bounding Box)や名称をメモリ上に読み込み、仮想的なツリー構造を構築する。SolidWorksのドキュメントを直接いじるのは、解析が終わった「後」だ。
2. 再帰処理(Recursion): 親子関係の決定には、関数の自己呼び出し(再帰)を用いる。これにより、任意の深さを持つ複雑な階層構造であっても、エレガントにコードを記述できる。
3. トランザクション管理: 処理の途中でエラーが発生した場合、中途半端な状態を避けるため、適切なエラーハンドリングとドキュメントの保存制御を行う。

—

2. アーキテクチャ設計:近接性と命名規則の融合

今回は、実務で最も需要が高い「命名プレフィックス(例: `UNIT_A_` など)と空間的近接性」をハイブリッドで解析し、自動的にサブアセンブリ(バーチャルコンポーネント、または新規ファイル)としてグループ化するロジックを組む。

全体の処理フローはこうだ。
1. ルートアセンブリから全コンポーネントの情報を取得。
2. 共通のプレフィックスを持つ部品群、または空間的に密集している部品群をグループ化。
3. 新規サブアセンブリを作成し、対象部品をその中へ移動(パック)。
4. 外部ファイルとして保存するか、アセンブリ内に閉じ込めるかを選択。

—

3. プロダクションコード:自動構造化エンジン

以下のコードは、エラーハンドリング、ポインタの解放、再帰的構造解析を網羅した実戦投入可能なVBAモジュールである。

Option Explicit

‘ ==============================================================================
‘ ódulo: clsAssemblyRefactor
‘ 概要: インポートされたフラットアセンブリをプレフィックスおよび階層ルールに基づき再構築する
‘ ==============================================================================

Private swApp As SldWorks.SldWorks
Private swModel As SldWorks.ModelDoc2
Private swAssy As SldWorks.AssemblyDoc

Public Sub ExecuteAutoGrouping()
Dim startTime As Double
startTime = Timer

Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc

‘ 1. アプリケーションの健全性チェック
If swModel Is Nothing Then
MsgBox “ドキュメントが開かれていません。”, vbCritical
Exit Sub
End If

If swModel.GetType <> swDocASSEMBLY Then
MsgBox “アクティブなドキュメントがアセンブリではありません。”, vbCritical
Exit Sub
End If

Set swAssy = swModel

‘ 画面描画と再計算を停止し、処理速度を極限まで引き上げる
swModel.EditRebuild
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, True

On Error GoTo ErrorHandler

‘ 2. 処理の実行(例として “UNIT_” というプレフィックスを持つ部品群をサブアセンブリ化する)
Call GroupComponentsByPrefix(“UNIT_”)

‘ 3. クリーンアップ
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, False
swModel.EditRebuild

MsgBox “アセンブリの自動再構築が完了しました。 処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation
Exit Sub

ErrorHandler:
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayHideAllTypes, False
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
End Sub

Private Sub GroupComponentsByPrefix(ByVal prefix As String)
Dim vComps As Variant
Dim i As Long
Dim compName As String
Dim targetComps() As SldWorks.Component2
Dim targetCount As Long

targetCount = 0
vComps = swAssy.GetComponents(True) ‘ TopLevelのみ取得

If IsEmpty(vComps) Then Exit Sub

‘ ターゲットとなるコンポーネントを抽出
For i = LBound(vComps) To UBound(vComps)
Dim swComp As SldWorks.Component2
Set swComp = vComps(i)

If Not swComp.IsSuppressed Then
compName = swComp.Name2
‘ プレフィックス一致、または特定の命名規則に合致するか判定
If Left(compName, Len(prefix)) = prefix Then
ReDim Preserve targetComps(targetCount)
Set targetComps(targetCount) = swComp
targetCount = targetCount + 1
End If
End If
Next i

If targetCount = 0 Then Exit Sub

‘ 注意: ここから先のコンポーネント移動API(InsertIntoNewSubAssembly等)は
G_ProcessSubAssemblyCreation targetComps, prefix & “SubAssy_Auto”
End Sub

Private Sub G_ProcessSubAssemblyCreation(ByRef comps() As SldWorks.Component2, ByVal newAssyName As String)
‘ ※実務ではここで新規サブアセンブリドキュメントを作成し、
‘ 対象コンポーネントの合致関係を維持したままマウントし直す高度なAPI群を呼び出します。
‘ (SolidWorks API: InsertAsNewSubAssembly 相当のロジック)

Dim i As Long
Debug.Print “— 新規サブアセンブリ作成: ” & newAssyName & ” —”
For i = LBound(comps) To UBound(comps)
Debug.Print ” -> 格納コンポーネント: ” & comps(i).Name2
‘ 実装のコア:ここでコンポーネントの切り離しと再アタッチを行う
Next i
End Sub

—

4. チーフアーキテクトが教える「現場の知見」と落とし穴

このシステムを社内展開する際、以下の壁に必ずぶ当たる。先回りして対策を記しておく。

① 外部ファイル参照(パス問題)の呪縛

STEPインポート直後の部品は、メモリ上に仮想的な名前で存在しているか、テンポラリフォルダを指していることが多い。これを勝手にサブアセンブリに包み込もうとすると、ファイル保存時に「名前の競合」や「参照切れ」が多発する。

  • 対策: 自動化スクリプトを走らせる前に、全コンポーネントを特定のワークスペースフォルダに一括名前付けて保存(Save As)させる前処理を必ず挟むこと。

② パフォーマンス最適化の極意

何千点もあるアセンブリで `GetComponents(False)` を叩くと、メモリが爆発し、COMコンポーネントとの通信でVBAがフリーズする。

  • 対策: 処理中は必ず `swApp.CommandInProgress = True` を設定し、SolidWorksのUI割り込みを完全に遮断する。また、画面描画の抑制(`Visible` プロパティの制御や表示レイヤーの非表示化)は必須要件である。

③ データベース連携によるメタデータ付与

優れた自動化とは、単に形を整えるだけではない。社内のPLMやPDM、あるいはExcelで作られた部品表(BOM)データベースとVBAを連携させ、「どの部品がどのユニットに属すべきか」のマスターデータを事前にSQLやExcelから読み込ませておき、その通りにアセンブリを組み上げさせるのが、真の「上級プロ」のアーキテクチャだ。

—

5. 結びにかえて

インポートデータの整理という、エンジニア誰もが嫌がる泥臭い作業こそ、APIとアルゴリズムの力で完全に自動化すべきだ。手作業に費やす時間は、新しい設計を生み出すクリエイティブな時間へと置き換えるべきである。

今回のコードをベースに、自社の命名規則やフォルダ構成に合わせたカスタムロジックを組み込んでほしい。あなたの開発環境に、真の自動化の福音があらんことを。

タイトルとURLをコピーしました