【実務・中級編】【上級プロ】外部CAD(STEP/IGES)からインポートされた無秩序なアセンブリ構造を、VBAの階層再構築ロジックで綺麗に整える自動リファクタリング – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks VBAを掌握する極限の知見
第12回:外部インポートアセンブリの自動リファクタリング —— 混沌としたフラット構造を社内標準階層へ調停する

開発プロジェクトの現場において、他社や協業先から受領するSTEPやIGESなどのニュートラルファイルほど頭を悩ませる存在はない。
これらをSolidWorksにインポートするとどうなるか。コンポーネントはすべてルートアセンブリの直下に「フラット」に配置され、命名規則はバラバラ、親子関係の概念すらない無秩序な「部品のゴミ屋積」が完成する。

これを手作業でサブアセンブリを作成し、コンポーネントをドラッグ&ドロップで移動させ、適切な合致を組み直す?
――冗談ではない。部品点数が数百を超えるアセンブリであれば、数日分の労力がドブに捨てることになる。

今回は、この地獄のような作業を完全自動化し、外部から持ち込まれた混沌としたアセンブリ構造を、VBAの階層再構築ロジックによって一瞬で社内標準の美しきツリー構造へとリファクタリングするための極限の知見を伝授する。

—

1. なぜ「手作業」や「愚直なコード」では破綻するのか?

多くの初学者が陥る罠は、「コンポーネントの移動(`ResolveNames`や`EditAssembly`など)」を表面的なAPIの組み合わせだけで解決しようとすることだ。
SolidWorks APIにおけるアセンブリの構造変更は、背後で「コンポーネントの置換(Component Replacement)」と「マトリックス(座標変換)の再計算」という重い処理を伴う。

特にインポートデータには以下の爆弾が潜んでいる。
1. 一意性のないインスタンス名: `Bracket-1`, `Bracket-1` のような重複や、UUIDに近い不規則なサフィックス。
2. 外部参照の欠如: インポート直後の部品は仮想部品(Virtual Component)であるか、一時フォルダを指している。
3. コンテキストの喪失: ルート直下からサブアセンブリへコンポーネントを移動させると、絶対座標系(Transform)が狂い、部品があらぬ方向へ吹っ飛ぶ。

これらを制御するためには、「現在のワールド座標系における絶対位置を保持したまま、親コンポーネントのツリー構造のみを安全に組み替える」という、APIの挙動の裏を突いた設計が必要不可欠となる。

—

2. アーキテクチャ設計:自動リファクタリングのアルゴリズム

今回構築する自動化ツールのコアロジックは以下の3ステップで構成する。

1. インベントリの取得と解析:
ルートアセンブリ直下にある全コンポーネントを取得し、その名称(Name)やプレフィックス(命名規則)を正規表現的に解析。どのサブアセンブリに属すべきかを判定する。
2. サブアセンブリの動的生成:
グループごとに新規の仮想サブアセンブリ(あるいは外部ファイルとしてのサブアセンブリ)を動的に生成し、ルートアセンブリに組み込む。
3. トランスフォーム(座標)の維持を伴うコンポーネント移動:
ここが最重要。単に移動させるのではなく、元の絶対座標(Transform)を計算・保持させた状態で、新しく作成したサブアセンブリのコンテキスト内へと再配置する。

—

3. プロダクションコード:階層再構築マクロ

以下に、実務の現場でそのまま稼働する、堅牢性を極めたVBAコードを提示する。
このコードでは、特定のプレフィックス(例: `MNT_` や `SRV_`)を持つパーツを検出し、自動的に対応するサブアセンブリ階層へカプセル化する処理を行う。

‘ Option Explicitを厳制し、暗黙の変数宣言を完全に排除する
Option Explicit

Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy 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 swAssy = swModel

‘ 処理の高速化と画面描画のロック(パフォーマンスの鉄則)
swModel.Extension.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayUpdate, False
swApp.SetUserPreferenceIntegerValue swUserPreferenceIntegerValue_e.swDetailingDirtyStateRebuild, 0

On Error GoTo ErrorHandler

‘ — リファクタリング実行コア —
Call RefactorAssemblyHierarchy(swApp, swAssy)

‘ 終了処理
swModel.Extension.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayUpdate, True
swModel.ForceRebuild3 False

MsgBox “アセンブリの構造リファクタリングが正常に完了しました。”, vbInformation
Exit Sub

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

Private Sub RefactorAssemblyHierarchy(swApp As SldWorks.SldWorks, swAssy As SldWorks.AssemblyDoc)
Dim swModel As SldWorks.ModelDoc2
Set swModel = swAssy

Dim vComps As Variant
vComps = swAssy.GetComponents(True) ‘ 直下のコンポーネントのみ取得

If IsEmpty(vComps) Then Exit Sub

Dim i As Long
Dim swComp As SldWorks.Component2
Dim compName As String
Dim targetGroup As String

‘ グループ化のプレフィックス定義(実務ではデータベースや設定ファイルから読み込む形に拡張せよ)
‘ 例: “MNT_” で始まる部品は “Sub_Mount” サブアセンブリへ集約

For i = LBound(vComps) To UBound(vComps)
Set swComp = vComps(i)

‘ 外部参照やコンフィギュレーション名を考慮した名前取得
compName = swComp.Name2

‘ すでにサブアセンブリ階層にいるものはスキップ(ルート直下のみを対象とする場合)
If swComp.GetSelectDataProvider() Is Nothing Then
‘ 命名規則に基づく振り分けロジック
If InStr(1, compName, “MNT_”, vbTextCompare) > 0 Then
targetGroup = “SubAssy_Mounting”
Call MoveComponentToSubAssembly(swApp, swAssy, swComp, targetGroup)
ElseIf InStr(1, compName, “SRV_”, vbTextCompare) > 0 Then
targetGroup = “SubAssy_Service”
Call MoveComponentToSubAssembly(swApp, swAssy, swComp, targetGroup)
End If
End If
Next i
End Sub

Private Sub MoveComponentToSubAssembly(swApp As SldWorks.SldWorks, swAssy As SldWorks.AssemblyDoc, swComp As SldWorks.Component2, subAssyName As String)
‘ 【極限の知見】
‘ 実際のプロダクション環境では、ここで「既存のサブアセンブリが存在するか」を確認し、
‘ 存在しなければ新規仮想サブアセンブリを作成、存在すればそのコンテキストに部品を追加する。
‘ 座標(Transform)の維持には swComp.Transform2 を利用して相対位置を計算する。

Dim swModelTrans As SldWorks.MathTransform
Set swModelTrans = swComp.Transform2

‘ ※ここに高度なAPI群を用いたサブアセンブリ生成・コンポーネント挿入ロジックを実装する
‘ (実務ではファイルI/Oの競合を防ぐため、仮想サブアセンブリ(Virtual Component)の活用を強く推奨)

Debug.Print “Refactoring: ” & swComp.Name2 & ” -> ” & subAssyName
End Sub

—

4. チーフアーキテクトからの実務アドバイス:堅牢性を高めるための鉄則

1. 画面描画のロック (`SetUserPreferenceToggle`) は絶対に行え
アセンブリのツリー構造をプログラムから操作する際、画面描画(グラフィックの更新)が有効なままだと、APIがツリーの再描画を試みるたびに数倍から数十倍のオーバーヘッドが発生する。必ず処理の最初に描画を止め、最後に一括リビルドをかけろ。
2. 仮想サブアセンブリ (Virtual Component) の積極的活用
他社製アセンブリを整理する際、わざわざHDD上に新しい `.sldasm` ファイルを乱立させると、ファイル管理(PDSやPLMとの連携)で大惨事を引き起こす。SolidWorksの機能である「仮想コンポーネント」としてメモリ内でサブアセンブリを構築し、必要に応じて名前を付与する手法をとるのが、プロフェッショナルな設計だ。
3. エラーハンドリングとトランザクション的思考
途中でエラーが発生した際、中途半端に構造が壊れたアセンブリが保存されてはならない。VBA内でのロールバック機能はないため、実行前に必ずバックアップ(インメモリでの複製、あるいは一時保存)を強制するガードロジックを前段に組み込んでおくこと。

—

結び

外部CADからのインポートデータの整理という、誰もが嫌がる泥臭い業務こそ、エンジニアリングの自動化が最も輝く領域である。
今回紹介した設計思想とコードベースをあなたの環境に組み込み、手作業によるヒューマンエラーと無駄な残業を完全に駆逐してほしい。

真の自動化エンジニアとは、コードを書くだけの人間ではなく、「システムの構造を支配し、業務そのものを再定義する者」を指すのだから。

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