こんにちは。チーフアーキテクトの私だ。
これまで数多くの大規模アセンブリや複雑な機構設計の自動化プロジェクトを率いてきたが、現場からもっとも多く寄せられる悲鳴の一つがこれだ。
「可動範囲の干渉チェックを、手作業で合致の値を変えながら目視で確認するのは、もう限界だ」
シリンダーのストローク端、リンク機構の特異点、スライドガイドの限界位置。これらを人間がマウスを握ってポチポチと距離合致の値をいじり、その都度干渉検査を走らせる……。そんな前時代的なワークフローは、今日この瞬間で終わりにしよう。
今回は、SolidWorks VBAの底力を引き出し、距離合致のパラメータをインクリメントさせながらアセンブリの動作範囲を連続検証(スイープシミュレーション)するプロダクションコードを授与する。
単なる「動くコード」ではない。実務の巨大アセンブリでもメモリリークを起こさず、ミリ秒単位の無駄を削ぎ落とした堅牢な設計を叩き込む。心してついてきてほしい。
—
1. なぜ「力技のループ」はSolidWorksをクラッシュさせるのか
まず、アマチュアプログラマーが陥る罠について話しておこう。
彼らは次のようなコードを書く。
‘ 【アンチパターン】絶対に真似してはいけない例
Dim i As Double
For i = 0 To 100 Step 1
‘ 合致の距離を変更
swMate.Distance = i
‘ その都度アセンブリを再構築
swModel.EditRebuild3
Next i
一見、問題なく動くように見えるだろう。しかし、これを実務レベルの複雑なアセンブリで実行すると、高確率でメモリリーク、最悪の場合はSolidWorksごと強制終了(クラッシュ)する。
3つの致命的な原因
1. 暗黙の再構築(Rebuild)の呪縛: `EditRebuild3` や `ForceRebuild3` はアセンブリの規模が大きくなるほど重くなる。ループのたびに全体を再評価させてはならない。
2. COMオブジェクトの参照解放漏れ: VBAとSolidWorksのCOM境界を行き交う中で、一時オブジェクトの解放をサボると、あっという間にメモリが枯渇する。
3. 干渉検査(Interference Detection)の重さ: 位置を変えるたびに全部品の干渉検査を走らせたら、PCが発熱して使い物にならなくなる。
我々が目指すべきは、「必要最小限の再計算」と「トランザクション的な安全管理」を両立させた、プロフェッショナルなコードだ。
—
2. 堅牢なシミュレーションを構築するアーキテクチャ
今回の自動化スクリプトの全体設計はこうだ。
1. 対象合致の確実な捕捉: 名前(Name)依存ではなく、内部IDやタイプで確実に合致フィーチャーを特定する。
2. ステップ制御と範囲の安全保障: 最小値・最大値・刻み幅(インクリメント値)を定義し、オーバーランを防ぐ。
3. 軽量な更新処理: アセンブリ全体ではなく、合致フィーチャー単体の更新と、必要なコンポーネントの位置更新(`swModel.Extension.Rebuild`の適切なスコープ)を利用する。
4. 結果のロギング: 検証結果(どの位置で干渉が起きたか等)をイミディエイトウィンドウやCSVに出力する。
—
3. 【プロダクションコード】距離合致スイープ検証マクロ
以下のコードは、アクティブなアセンブリ内に存在する特定の「距離合致」をターゲットにし、指定した範囲で値をインクリメントさせながらアセンブリを駆動させる実用コードだ。
Option Explicit
‘ ==============================================================================
‘ 担当者向け:機構部品の距離合致スイープ検証スクリプト
‘ 前提条件: 対象のアセンブリに「TargetDistanceMate」という名前の距離合致が存在すること
‘ ==============================================================================
Sub RunDistanceMateSweepSimulation()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssoc As SldWorks.AssemblyDoc
Dim swFeat As SldWorks.Feature
Dim swMateData As SldWorks.DistanceMateFeatureData
‘ — 1. アプリケーションとドキュメントの取得 —
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 swAssoc = swModel
‘ — 2. ターゲット合致の検索 —
‘ 実務では名前決め打ちではなく、セレクションマネージャ等で選択させるアプローチも有効
Dim targetMateName As String
targetMateName = “距離合致1” ‘ ※ご自身の環境の合致名に変更してください
Set swFeat = FindFeatureByName(swModel, targetMateName)
If swFeat Is Nothing Then
MsgBox “指定された合致が見つかりません: ” & targetMateName, vbCritical, “エラー”
Exit Sub
End If
‘ フィーチャーから合致データを取得
Set swMateData = swFeat.GetDefinition
If swMateData Is Nothing Then
MsgBox “フィーチャーから合致データを取得できませんでした。”, vbCritical, “エラー”
Exit Sub
End If
‘ — 3. シミュレーションパラメータの設定 (単位: メートル) —
Dim dblStart As Double: dblStart = 0.0 ‘ 開始距離 (例: 0mm)
Dim dblEnd As Double: dblEnd = 0.05 ‘ 終了距離 (例: 50mm)
Dim dblStep As Double: dblStep = 0.005 ‘ 刻み幅 (例: 5mm)
Dim currentDist As Double
‘ 合致編集モードの開始 (Accessions)
swMateData.AccessSelections swModel, Nothing
‘ 画面描画を一時停止してパフォーマンスを極限まで高める
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayFreeze, True
On Error GoTo ErrorHandler ‘ 途中でエラーが起きても画面凍結を解除するための保険
Debug.Print “=== シミュレーション開始 ===”
‘ — 4. インクリメント・ループの実行 —
For currentDist = dblStart To dblEnd Step dblStep
‘ 距離を設定
swMateData.Distance = currentDist
‘ 定義を更新してアセンブリに適用
Dim boolstatus As Boolean
boolstatus = swFeat.ModifyDefinition(swMateData, swModel, Nothing)
If Not boolstatus Then
Debug.Print “警告: 距離 ” & (currentDist 1000) & ” mm での合致更新に失敗しました。”
End If
‘ 最小限の再構築(モデル全体ではなく、合致関係の解決を促す)
‘ swModel.EditRebuild3 だと重すぎるため、強制再計算を避けた軽量更新を使用
swModel.ForceRebuild3 False
‘ — 実務用フック —
‘ ここで干渉チェックAPI(swModel.Extension.InterferenceDetectionMgr)を
‘ 呼び出すことで、各ステップでの干渉有無を自動記録できます。
Debug.Print “検証中: 距離 = ” & Format(currentDist 1000, “0.0”) & ” mm”
‘ 視覚的に確認したい場合は DoEvents を挟む(ただしパフォーマンスは落ちる)
‘ DoEvents
Next currentDist
Debug.Print “=== シミュレーション正常終了 ===”
ErrorHandler:
If Err.Number <> 0 Then
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
End If
‘ — 5. 終了処理(リソースのクリーンアップ) —
‘ 合致データの編集モードを終了
swMateData.ReleaseSelectionAccess
‘ 画面描画の凍結を解除
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayFreeze, True
‘ 最終的なモデルの状態を綺麗に再構築
swModel.EditRebuild3
Set swMateData = Nothing
Set swFeat = Nothing
Set swModel = Nothing
Set swAssoc = Nothing
Set swApp = Nothing
End Sub
‘ — ヘルパー関数: 名前からフィーチャーを再帰的に検索 —
Private Function FindFeatureByName(ByVal model As SldWorks.ModelDoc2, ByVal featName As String) As SldWorks.Feature
Dim feat As SldWorks.Feature
Set feat = model.FirstFeature
Do While Not feat Is Nothing
If feat.Name = featName Then
Set FindFeatureByName = feat
Exit Function
End If
‘ サブフィーチャー(合致ホルダー内など)の走査が必要な場合の処理をここに拡張可能
Set feat = feat.GetNextFeature
Loop
Set FindFeatureByName = Nothing
End Function
—
4. プロジェクトを成功させるための実務的アドバイス
このコードをあなたの現場に導入するにあたり、チーフアーキテクトとしていくつか追加のアドバイスをしておこう。
1. 画面描画の凍結 (`swViewDisplayFreeze`) の威力
ループ内で画面がレンダリングされると、それだけで処理時間が10倍以上跳ね上がる。上記のコードでは描画を完全にロックしているため、裏で高速にシミュレーションが走る。結果だけをイミディエイトウィンドウやCSVに出力するのがプロのやり方だ。
2. 干渉チェック(Interference Detection)との結合
コメントアウトしている部分に `InterferenceDetectionMgr` を組み込むことで、「どのストローク位置で干渉カウンターが0以外になったか」をログに吐き出させることが可能だ。これにより、設計者は机上で「ストローク42mm時点で干渉発生」というファクトを手にすることができる。
3. 例外処理(Error Handler)の絶対死守
VBAで最も恐ろしいのは、ループの途中でエラーが起き、画面描画がフリーズしたまま(あるいはバックグラウンドでSolidWorksがゾンビ化して)残ることだ。`On Error GoTo ErrorHandler` を必ず配置し、異常終了時でも確実に `ReleaseSelectionAccess` と画面描画の復元が行われる構造にしなければならない。
—
最後に:自動化とは「エンジニアの自由時間の創出」である
手作業でのシミュレーションは、退屈でヒューマンエラーの温床だ。
今回提供したコードをベースに自社のアセンブリ構造に合わせたパスを通せば、帰宅ボタンを押す直前にマクロを走らせ、翌朝には「可動範囲の検証結果レポート」が完成している環境が手に入る。
コードは単なる文字列ではない。あなたの設計工数を守る盾であり、武器だ。
ぜひ、現場の業務効率化に役立ててほしい健闘を祈る。
