【テクニカル・上級編】【実務中級】アセンブリ内で重複して配置されている同一部品(余剰パーツ)をVBAで検出してクリーンアップする自動化 – SolidWorks VBA解析バイブル

スポンサーリンク

アセンブリの「負の遺産」を殲滅せよ:重複コンポーネントを排除するVBA極限最適化術

設計の現場において、アセンブリファイルは時として「ゴミ屋敷」と化す。設計変更の履歴が積み重なり、見えない場所に重なった同一部品、あるいは構成管理から逸脱した幽霊のようなインスタンス。これらはモデルの再構築時間を増大させ、PDMとの連携において致命的なコンフリクトを引き起こす。

本稿では、SolidWorks APIを使い倒し、重複コンポーネントを論理的に特定・削除する「クリーンアップ・アルゴリズム」の深淵に迫る。VBAという古き良き言語を使いながらも、メモリ管理と計算量に配慮した、プロフェッショナルが実装すべきコードを提示する。

—

1. 重複判定の本質:名前か、IDか、それとも「位置」か

単純に「ファイル名が同じだから重複」と見なすのは素人仕事だ。我々が対峙すべきは、「コンポーネントID(Instance ID)」と「コンポーネントの変換行列(Transform Matrix)」である。

  • 同一IDの重複: 基本的にSolidWorksのアセンブリ構造上発生しないが、破壊されたフィーチャーデータにより稀に発生する。
  • 実質的な重複: ファイル名が同一かつ、配置座標(変換行列)が完全に一致、あるいは極めて近いもの。

これらを判定するには、`IComponent2` インターフェースの `GetTransform` メソッドから得られる行列の各要素を比較し、微小な浮動小数点誤差(イプシロン)を考慮した判定を行う必要がある。

—

2. 破壊的処理を安全に行うためのアーキテクチャ

アセンブリ操作において最も恐ろしいのは、削除したことによる「合致(Mate)の破綻」ではない。「削除したはずのオブジェクトへのポインタがメモリ上に残り、後続の処理でAccess Violation(メモリ違反)を引き起こすこと」である。

実装のポイント

1. SelectionManagerの利用: 削除対象を明示的に選択し、`IModelDoc2::DeleteSelection2` を用いる。
2. オブジェクトの明示的解放: `Set obj = Nothing` をループの最後に行うのは当然だが、さらに `DoEvents` を適切に挟むことで、バックグラウンドの描画処理と同期させる。
3. Undoスタックの制御: 処理の開始と終了で `IModelDoc2::BeginUndoGroup` / `EndUndoGroup` を使い、万が一の際に一括ロールバックを可能にする。

—

3. 実装コード:重複コンポーネント・クリーナー

このコードは、カレントアセンブリ内のコンポーネントをスキャンし、同一ファイル名かつ同一座標の部品を特定して削除する。

Option Explicit

‘ 重複削除のメインプロシージャ
Public Sub CleanUpDuplicateComponents()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim vComps As Variant
Dim i As Long, j As Long

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

If swModel.GetType <> swDocASSEMBLY Then Exit Sub
Set swAssy = swModel

swModel.BeginUndoGroup

‘ 全コンポーネント取得
vComps = swAssy.GetComponents(False)

‘ ここでコレクションや配列を使い、重複比較アルゴリズムを回す
‘ 計算量は O(N^2) になるため、大規模アセンブリでは注意が必要
For i = LBound(vComps) To UBound(vComps)
For j = i + 1 To UBound(vComps)
If IsDuplicate(vComps(i), vComps(j)) Then
‘ 重複と判定されたコンポーネントを選択して削除
vComps(j).Select4 False, Nothing, False
swModel.DeleteSelection2 False
Debug.Print “Removed: ” & vComps(j).Name2
End If
Next j
Next i

swModel.EndUndoGroup
MsgBox “クリーンアップ完了”
End Sub

‘ 変換行列に基づいた厳密な一致判定
Private Function IsDuplicate(comp1 As SldWorks.Component2, comp2 As SldWorks.Component2) As Boolean
‘ 1. ファイル名チェック
If comp1.GetPathName <> comp2.GetPathName Then Exit Function

‘ 2. 変換行列の比較 (簡易版: 各要素の差が微小か)
Dim m1 As Variant, m2 As Variant
m1 = comp1.GetTransform.ArrayData
m2 = comp2.GetTransform.ArrayData

Dim k As Integer
For k = 0 To 15
If Abs(m1(k) – m2(k)) > 0.000001 Then Exit Function
Next k

IsDuplicate = True
End Function

—

4. シニアエンジニアのための「極限の知見」

メモリとパフォーマンスの制御

`GetComponents` はアセンブリの深さに関わらず全コンポーネントをフラットに取得する。数千パーツを超えるような巨大アセンブリの場合、この処理はメインスレッドを長時間占有する。
もしシステムがフリーズする場合は、`Win32 API` の `GetTickCount` 等を使い、一定時間ごとに制御をOSに戻す「タイムスライス」を組み込むべきだ。

Windows APIとの連携による堅牢性

自動化プロセス中にSolidWorksが「応答なし」になることを防ぐため、`RegisterWindowMessage` 等を用いて、現在の処理状況を外部の監視ツールへ送信する仕組みを実装することも検討してほしい。これは、社内システム管理者として、自動化プロセスの死活監視を行う上で必須のスキルである。

最後に

VBAはレガシーと言われるが、SolidWorksのCOMインターフェースを直接叩く力において、これに勝る直感的なツールは未だ存在しない。アセンブリの整理は、設計者の思考を整理することと同義である。
無駄なインスタンスを排除し、軽快なモデル環境を作る。それこそが、我々エンジニアが追求すべき「デジタル上の断捨離」なのだ。

このコードをただコピペするだけでなく、君自身の設計環境に合わせて最適化せよ。それが、真のアーキテクトへの第一歩となる。

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