こんにちは!SolidWorks自動化の現場で泥臭く、かつエレガントなマクロを書き続けている先輩エンジニアです。
マクロの記録ボタンを押してフィレットを作ってみたものの、モデルの形状が変わった途端にエラーで止まってしまったり、意図しないエッジまで巻き込んで形状が破綻したり……そんな苦い経験はありませんか?
「全エッジ一括選択」という力技は、実務の現場では百害あって一利なしです。
今回は、「`Body2.GetEdges` を使ってエッジの長さを計算し、条件に合う特定のエッジだけにスマートにフィレットをかける」という、プログラミング中級者へのステップアップに不可欠な極限の知見を授けましょう。
ここをクリアすれば、あなたのSolidWorks VBAスキルは一気に実用レベルへ到達します。さあ、一緒に扉を開けましょう!
—
1. なぜ「全エッジ一括選択」は実務で使えないのか?
自動化の最大の敵は「モデルの変更(トポロジーの変動)」です。
例えば、設計変更によってエッジの総数が変わったり、ID番号がズレたりしたとき、ハードコーディングされたエッジ選択はあっさりクラッシュします。
実務で求められるのは、「プログラム自身がエッジの性質(長さや曲率)をその場でスキャンし、人間と同じように『あ、ここは微小だからスルーしよう』『ここは指定の長さだから処理しよう』と判断する知性」です。
これを叶えるのが、Bodyオブジェクトからエッジの配列をごっそり取得する `Body2.GetEdges` メソッドと、エッジの数学的情報を司る `Edge` オブジェクトの組み合わせです。
—
2. 攻略の全体像:フィルタリング・フィレットのアルゴリズム
今回構築するVBAマクロの全体像は以下の通りです。非常にシンプルですが、APIの本質が詰まっています。
1. アクティブなパーツドキュメントとボディを取得する
2. `Body2.GetEdges` で、そのボディを構成する全エッジ(の配列)を一網打尽に取得する
3. ループを回して各エッジの「長さ」を測定する
4. 「特定の長さ(例:10mm以上かつ50mm未満など)」に合致するエッジだけをコレクションに抽出する
5. 抽出したエッジの配列を指定して、一括でフィレットフィーチャを作成する
—
3. 実践!長さフィルタリング・フィレット生成コード
そのままコピペしてVBAエディタ([Alt] + [F11])に貼り付け、パーツを開いた状態で実行できる実用コードをプレゼントします。
Sub ApplySmartFilletWithLengthFilter()
Dim swApp As SldWorks.SldWorks
Dim swPart As SldWorks.PartDoc
Dim swModel As SldWorks.ModelDoc2
Dim swBody As SldWorks.Body2
Dim swSelMgr As SldWorks.SelectionMgr
Dim swFeatureMgr As SldWorks.FeatureManager
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ 0. ドキュメントの整合性チェック
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントがありません。”, vbCritical
Exit Sub
End If
If swModel.GetType <> swConst.swDocPART Then
MsgBox “このマクロはパーツドキュメントでのみ実行可能です。”, vbExclamation
Exit Sub
End If
Set swPart = swModel
Set swFeatureMgr = swModel.FeatureManager
‘ 1. 最初に見つかったソリッドボディを取得(簡易的な取得方法)
Dim vBodies As Variant
vBodies = swPart.GetBodies2(swConst.swSolidBody, True)
If IsEmpty(vBodies) Then
MsgBox “ソリッドボディが見つかりません。”, vbCritical
Exit Sub
End If
Set swBody = vBodies(0)
‘ 2. Body2.GetEdgesで全エッジを取得(VARIANT型で返る点に注意!)
Dim vEdges As Variant
vEdges = swBody.GetEdges()
If IsEmpty(vEdges) Then
MsgBox “エッジを取得できませんでした。”, vbCritical
Exit Sub
End If
‘ 3. 条件に一致するエッジを格納するための動的配列を準備
Dim targetEdges() As Object
Dim edgeCount As Long
edgeCount = 0
Dim i As Long
Dim swEdge As SldWorks.Edge
Dim swCurve As SldWorks.Curve
Dim edgeLength As Double
‘ フィルタリング条件(単位:メートル法なので注意!ここでは例として 5mm 〜 50mm のエッジを対象とする)
Const MIN_LENGTH As Double = 0.005 ‘ 5mm
Const MAX_LENGTH As Double = 0.05 ‘ 50mm
For i = LBound(vEdges) To UBound(vEdges)
Set swEdge = vEdges(i)
‘ エッジの数学的実体(Curve)を取得
Set swCurve = swEdge.GetCurve()
‘ エッジの長さを計算(CurveParamは使わず、Edgeオブジェクトから直接長さを取得可能)
‘ ※厳密にはGetCurveParam等を使うケースもありますが、Edgeの長さ評価にはGetCurveのパラメータ範囲を利用します
Dim startParam As Double, endParam As Double
Dim bIsClosed As Boolean, bIsPeriodic As Boolean
Call swCurve.GetEndPoints(startParam, endParam, bIsClosed, bIsPeriodic)
‘ パラメータ区間における実際の長さを取得するAPI
edgeLength = swCurve.GetLength(startParam, endParam)
‘ 条件判定:指定した長さのレンジ内か?
If edgeLength >= MIN_LENGTH And edgeLength <= MAX_LENGTH Then
' 条件に合致した場合、配列に保持
If edgeCount = 0 Then
ReDim targetEdges(0)
Else
ReDim Preserve targetEdges(edgeCount)
End If
Set targetEdges(edgeCount) = swEdge
edgeCount = edgeCount + 1
End If
Next i
' 4. 該当するエッジがなければ終了
If edgeCount = 0 Then
MsgBox "条件に一致するエッジが見つかりませんでした。", vbInformation
Exit Sub
End If
' 5. 選択解除&抽出したエッジをAPI経由で選択状態にする
swModel.ClearSelection2 True
Dim mark As Long
mark = 1 ' フィレットフィーチャ用の選択マーク(通常は1)
For i = 0 To edgeCount - 1
Dim swEntity As SldWorks.Entity
Set swEntity = targetEdges(i)
' AppendToSelection: 複数選択のときはTrueにする
swEntity.Select4 True, mark
Next i
' 6. フィレットフィーチャの実行(半径:2mmのフィレットを生成)
Dim filletRadius As Double
filletRadius = 0.002 ' 2mm
Dim swFeat As SldWorks.Feature
' FeatureManager.FeatureFillet2 引数:
' Type, Radius1, SetBack1, ConicRho1, OverflowType, FacesOrEdges, etc...
' 実務では既存の定番メソッドである FeatureFillet2 を用います
Set swFeat = swFeatureMgr.FeatureFillet2( _
swConst.swFeatureFilletType_ConstantRadius, _
filletRadius, _
0, 0, 0, 0, 0, _
Nothing, Nothing, 0, 0)
If Not swFeat Is Nothing Then
MsgBox "フィルタリングされた " & edgeCount & " 本のエッジにフィレットを適用しました!", vbInformation
Else
MsgBox "フィレットの生成に失敗しました。形状干渉を確認してください。", vbCritical
End If
End Sub
---
4. コードの急所:ここだけは絶対に押さえろ!
初心者から「中級者のエンジニア」へ脱皮するために、今回のコードのキモを3つ解説します。
① SolidWorks APIの基本単位は「メートル(m)」
コード内で `MIN_LENGTH = 0.005` と書いていることに気づきましたか?
SolidWorksの内部データベースは、ドキュメントの設定(mm単位など)に関わらず、すべて「メートル(m)」でデータをやり取りします。
「5mmのつもりで `5` と書いたら、5m(5,000mm)の巨大な指定になってエラーになった!」というのは、VBA開発者が一度は通る通過儀礼です。必ず `0.005` のようにメートル換算する意識を持ちましょう。
② `Body2.GetEdges` が返すのは VARIANT型(配列)
`vEdges = swBody.GetEdges()` は、エッジの詰まった「箱(配列)」を返します。
VBAではこれを `For i = LBound(vEdges) To UBound(vEdges)` というお決まりのイディオムで一つずつ取り出して料理します。このデータ構造の扱いに慣れると、面(Faces)や頂点(Vertices)の制御も完全にマスターできます。
③ `Entity.Select4` によるスマートな選択
抽出した `Edge` オブジェクトをそのままフィーチャ作成コマンドに渡すことはできません。SolidWorksでは「画面上で選択されている状態(Selection Managerが認識している状態)」にしてからフィーチャを叩くのが王道です。
`swEntity.Select4 True, 1` を使うことで、プログラムが自動で狙ったエッジをポチポチとクリックして選択状態にしてくれます。
—
最後に:エラーを恐れるな、ログを活用せよ
「思った通りのエッジが選ばれない」「フィレットで面がねじれてエラーになる」
そんなときは、`Debug.Print edgeLength` などをループ内に仕込んで、イミディエイトウィンドウに抽出されるエッジの長さを出力させてみてください。
「自分の目で数値を確認しながらロジックを組む」――これこそが、プログラミングによる自動化の最大の醍醐味であり、マクロの記録から脱却したエンジニアだけが味わえる快感です。
ここをクリアしたあなたなら、次は「曲率半径によるフィルタリング(円柱面のエッジだけを狙う)」など、さらに高度な条件分岐へと進むことができるはずです。
ぜひ自分の環境でコードを動かし、思い通りにエッジを操る快感に酔いしれてみてください。応援しています!
