【入門編】【実務中級】Excelの座標テーブル(X, Y, Z, 軸周り回転)を読み込み、アセンブリ内の複数部品を3次元空間に一括マッピング配置 – SolidWorks VBA解析バイブル

スポンサーリンク

こんにちは!SolidWorks VBAの世界へようこそ。

3D CADの操作の中で、最も時間が取られ、かつ精神を消耗しやすい作業の一つが「大量の部品を、指定された座標にひたすら配置していく作業」です。

「測定データやレイアウト指示書(Excel)を見ながら、手作業で1点ずつコンポーネントを挿入し、合致(Mate)を設定して、角度を微調整する……」

もしあなたが今、このような作業で一日を終えているなら、今日がその「単純作業」から脱却する記念日になります。

今回は、Excelにまとめられた座標テーブル(X, Y, Z, および回転角度)を読み込み、アセンブリ内の特定コンポーネントの3次元位置を一瞬で書き換えて完璧にマッピングするVBAツールを開発します。

マクロの記録から一歩踏み出し、SolidWorksの「本質的なオブジェクト操作」をマスターしましょう。ここをクリアすれば、SolidWorks VBAの基本はバッチリですよ!

—

1. なぜ「合致」ではなく「トランスフォーム(座標変換)」なのか?

プログラミングで部品を配置しようとするとき、多くの人が「合致(Mate)をVBAで自動追加すればいいのでは?」と考えます。

しかし、実務においてこれは罠になり得ます。
数百個の部品に対して愚直に合致を定義していくと、アセンブリの挙動は劇的に重くなり、時には合致の競合(エラー)でマクロがストップしてしまいます。

そこで、プロの開発者が使うのが「トランスフォーム(MathTransform)の直接書き換え」です。

3次元空間における「トランスフォーム」のイメージ

SolidWorks内のすべての部品は、アセンブリの原点に対する「位置(並進ベクトル)」と「傾き(回転行列)」の情報を持っています。

[ 3D空間でのパーツの状態 ]
■ 位置 (X, Y, Z) ───> どこにあるか
■ 回転 (Rx, Ry, Rz) ───> どの方向を向いているか
↓
これらを1つの「4×4の行列(マトリクス)」として表現したものが
SolidWorksの「MathTransform(トランスフォーム)」です。

合致で縛るのではなく、この「位置と傾きの方程式」をExcelの値で直接上書きしてあげることで、アセンブリが一切重くならず、一瞬でパーツを整列させることができるのです。

—

2. 準備:Excelの座標テーブルを作成する

まずはインプットとなるExcelシートを用意しましょう。デスクトップ等に `layout_data.xlsx` という名前で保存してください。
シート名は `Sheet1` とし、以下のようなレイアウトにします。

| A: 部品インスタンス名 | B: X (mm) | C: Y (mm) | D: Z (mm) | E: Z軸回転 (deg) |
| :— | :— | :— | :— | :— |
| Part1-1 | 100.0 | 50.0 | 0.0 | 45.0 |
| Part1-2 | 200.0 | -150.0 | 50.0 | 90.0 |
| SubAssy-1 | 0.0 | 300.0 | -20.0 | -30.0 |

> 💡 先輩のアドバイス:
> SolidWorksアセンブリ内での「部品インスタンス名」とは、デザインツリーに表示されている `Part1-1` や `SubAssy-1` などの名前のことです(`.sldprt` などの拡張子は除きます)。

—

3. 実装:一括マッピングを行う極限のVBAコード

それでは、SolidWorksのマクロエディタ(Alt + F11)を開き、新しい標準モジュールを追加して以下のコードを貼り付けてください。

※このコードを実行する前に、SolidWorksで対象のアセンブリを開いておき、Excelのライブラリ(`Microsoft Excel 16.0 Object Library` 等)への参照設定を有効にしてください(VBAメニューの「ツール」→「参照設定」からチェックを入れます)。

Option Explicit

‘ ==============================================================================
‘ ■ Excelレイアウトインポーター
‘ Description: Excelの座標テーブルを読み込み、アセンブリ内の同名部品の位置・角度を
‘ 一括でトランスフォーム書き換えによって配置します。
‘ ==============================================================================

Sub ImportComponentLayout()
‘ SolidWorksオブジェクト
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim swMathUtil As SldWorks.MathUtility

‘ Excelオブジェクト(実行時バインディング)
Dim xlApp As Object
Dim xlBook As Object
Dim xlSheet As Object
Dim excelPath As String

‘ 各種変数
Dim compName As String
Dim posX As Double, posY As Double, posZ As Double
Dim rotZ As Double
Dim radZ As Double

‘ SolidWorksの初期化
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc

‘ ドキュメントが開かれているか、かつアセンブリであるかのチェック
If swModel Is Nothing Then
MsgBox “SolidWorksでアセンブリを開いてから実行してください。”, vbCritical, “エラー”
Exit Sub
End If

If swModel.GetType <> swDocumentTypes_e.swDocASSEMBLY Then
MsgBox “アクティブなファイルがアセンブリではありません。”, vbCritical, “エラー”
Exit Sub
End If

Set swAssy = swModel
Set swMathUtil = swApp.GetMathUtility

‘ — Excelファイルの選択 —
‘ 実務で使いやすいよう、ファイル選択ダイアログを開きます
excelPath = swApp.GetOpenFileName(“座標テーブルの選択”, “”, “Excel Files (.xls; .xlsx)|.xls;.xlsx|”, 0, “”, “”)
If excelPath = “” Then Exit Sub ‘ キャンセルされた場合

‘ Excelをバックグラウンドで起動
On Error Resume Next
Set xlApp = CreateObject(“Excel.Application”)
On Error GoTo 0

If xlApp Is Nothing Then
MsgBox “Excelを起動できませんでした。”, vbCritical, “エラー”
Exit Sub
End If

‘ 画面更新を止めてパフォーマンス向上
xlApp.Visible = False
Set xlBook = xlApp.Workbooks.Open(excelPath)
Set xlSheet = xlBook.Sheets(1) ‘ 1番目のシートを対象とする

‘ 描画と再計算を一時停止(パフォーマンスの極限化)
swModel.FeatureManager.EnableFeatureTree = False ‘ ツリー更新の抑制

Dim row As Long
row = 2 ‘ 1行目はヘッダーと仮定し、2行目からスタート

‘ ループ処理:Excelのデータがなくなるまで読み込む
Do While xlSheet.Cells(row, 1).Value <> “”

compName = xlSheet.Cells(row, 1).Value

‘ 座標値の取得(ミリメートルからSolidWorks標準の「メートル」へ変換!)
posX = xlSheet.Cells(row, 2).Value / 1000#
posY = xlSheet.Cells(row, 3).Value / 1000#
posZ = xlSheet.Cells(row, 4).Value / 1000#

‘ 回転角度(Degree)をラジアン(Radian)に変換
rotZ = xlSheet.Cells(row, 5).Value
radZ = rotZ (3.14159265358979 / 180#)

‘ コンポーネントの位置変更処理を実行
Call ApplyTransformToComponent(swAssy, swMathUtil, compName, posX, posY, posZ, radZ)

row = row + 1
Loop

‘ 後処理:Excelを安全に閉じる
xlBook.Close SaveChanges:=False
xlApp.Quit
Set xlSheet = Nothing
Set xlBook = Nothing
Set xlApp = Nothing

‘ SolidWorksの描画を再開し、アセンブリを再構築
swModel.FeatureManager.EnableFeatureTree = True
swModel.ForceRebuild3 True ‘ 強制再構築で画面を最新状態に

MsgBox “マッピングが完了しました!” & vbCrLf & “処理件数: ” & (row – 2) & ” 件”, vbInformation, “成功”
End Sub

‘ ==============================================================================
‘ ■ サブ関数:コンポーネントにトランスフォームを適用する
‘ ==============================================================================
Private Sub ApplyTransformToComponent(ByRef swAssy As SldWorks.AssemblyDoc, _
ByRef swMathUtil As SldWorks.MathUtility, _
ByVal compName As String, _
ByVal x As Double, ByVal y As Double, ByVal z As Double, _
ByVal angleRad As Double)

Dim swComp As SldWorks.Component2
Dim swModelDoc As SldWorks.ModelDoc2
Set swModelDoc = swAssy

‘ アセンブリ内から名前でコンポーネントを検索
‘ (注: 大文字小文字や、後ろの「-1」などのインスタンス番号に注意)
Set swComp = swAssy.GetComponentByName(compName)

If swComp Is Nothing Then
‘ 見つからない場合はイミディエイトウィンドウにログを出してスキップ
Debug.Print “【警告】コンポーネントが見つかりません: ” & compName
Exit Sub
End If

‘ 固定(Fixed)されているコンポーネントはトランスフォームを受け付けないため、一時的にフローティングにする
Dim isFixed As Boolean
isFixed = swComp.IsFixed
If isFixed Then
swComp.MakeFloating
End If

‘ — 1. 回転行列の作成(Z軸周りの回転) —
‘ 3次元の回転軸ベクトル(Z軸 = 0, 0, 1)を定義
Dim axisData(2) As Double
axisData(0) = 0#
axisData(1) = 0#
axisData(2) = 1#

Dim swAxisVec As SldWorks.MathVector
Set swAxisVec = swMathUtil.CreateVector(axisData)

‘ 回転軸と角度から回転トランスフォームを生成
Dim swRotPointData(2) As Double ‘ 回転の中心点(原点 0, 0, 0)
swRotPointData(0) = 0#
swRotPointData(1) = 0#
swRotPointData(2) = 0#

Dim swRotPoint As SldWorks.MathPoint
Set swRotPoint = swMathUtil.CreatePoint(swRotPointData)

Dim swRotTransform As SldWorks.MathTransform
Set swRotTransform = swMathUtil.CreateTransformRotateAxis(swRotPoint, swAxisVec, angleRad)

‘ — 2. 並進ベクトル(位置)の作成 —
Dim transData(2) As Double
transData(0) = x
transData(1) = y
transData(2) = z

Dim swTransVec As SldWorks.MathVector
Set swTransVec = swMathUtil.CreateVector(transData)

Dim swTransTransform As SldWorks.MathTransform
Set swTransTransform = swMathUtil.CreateTransform(swTransVec)

‘ — 3. 回転と並進を合成する —
‘ Multiplyメソッドでマトリクスを掛け合わせ、ひとつのトランスフォームにします
Dim swFinalTransform As SldWorks.MathTransform
Set swFinalTransform = swRotTransform.Multiply(swTransTransform)

‘ — 4. コンポーネントに適用 —
‘ 第一引数にトランスフォーム、第二引数をTrueにすることで、アセンブリ上の絶対座標として適用
swComp.Transform2 = swFinalTransform

‘ 元々固定されていた部品であれば、固定状態に戻す
If isFixed Then
swComp.MakeFixed
End If
End Sub

—

4. コードの本質解説:ここを理解すれば基本はバッチリ!

このマクロがやっていることは、一見難しそうに見えますが、パーツに分ければ非常にシンプルです。
つまずきやすいポイントを「3つの本質」に絞って解説します。

① 単位の壁「ミリメートル」と「メートル」

初心者の方が最も頻繁に遭遇するバグが、「実行したら、部品がはるか彼方に飛んでいって消えた(あるいは小さく固まっている)」という現象です。

  • Excel上の数値:`100.0` (mm)
  • SolidWorks内部の基準単位:メートル (m)

APIに座標を渡すときは、必ず `1000` で割ってメートル単位(`0.1` m)に変換する必要があります。

posX = xlSheet.Cells(row, 2).Value / 1000#

この1行が、あなたを「部品消失バグ」から救ってくれます。

② `MathUtility`によるマトリクスの合成

3次元空間での移動と回転をプログラムでスマートに処理するために、SolidWorksは `MathUtility` という数学ツールを提供しています。

1. 回転を作る:`CreateTransformRotateAxis` で「どの点を中心に、どの軸周りで、何ラジアン回転するか」を定義。
2. 移動を作る:`CreateTransform` で「どの方向にどれだけ平行移動するか」を定義。
3. 合体させる:`Multiply` メソッドを使って、2つのトランスフォームを掛け合わせて1つの「最終位置・姿勢マトリクス」を完成させます。

これをそのまま `swComp.Transform2 = swFinalTransform` と代入するだけで、パーツは指示された場所に吸い込まれるように移動します。

③ 「固定(Fixed)」された部品への配慮

実務のアセンブリでは、基準となる部品が「固定」されていることがよくあります。
固定された部品に対して直接トランスフォームを適用しようとしても、SolidWorksは「動かせません」と命令を無視してしまいます。

そこで、このコードでは以下のようなプロのケアを行っています。

If swComp.IsFixed Then
swComp.MakeFloating ‘ 一時的に固定を解除
End If

‘ (位置を変更する処理)

If isFixed Then
swComp.MakeFixed ‘ 元通り固定する
End If

この配慮があるかないかが、実務で「使えるマクロ」と「エラーで止まるマクロ」の決定的な差になります。

—

5. 陥りやすいエラーと解決のヒント

エラー1: 「コンポーネントが見つかりません」とログに出る

  • 原因: Excelに書いた名前と、SolidWorksのデザインツリー上の名前が一致していません。
  • 対策: アセンブリ内の部品名には、通常 `Part1-1` のように末尾にインスタンス番号(`-1` や `-2`)がつきます。Excel側のリストにこの番号まで正確に記載されているか確認してください。

エラー2: 回転角度が思った方向と違う

  • 原因: 度(Degree)とラジアン(Radian)の変換ミス、または回転軸の間違い。
  • 対策: コード内の `radZ = rotZ (3.14159265358979 / 180#)` を通しているか確認してください。また、今回のサンプルは「Z軸(上方向または手前方向)」周りの回転ですが、アセンブリの基準軸が異なる場合は、回転軸ベクトル `axisData` を `(1, 0, 0)` [X軸] や `(0, 1, 0)` [Y軸] に変更してみてください。

—

6. まとめ:自動化がもたらす未来

手作業で行えば数時間かかる「レイアウト調整」が、このマクロを使えばものの1秒で完了します。

この手法を応用すれば、

  • Excelで計算したらせん階段の手すり位置に、子柱パーツを自動でずらりと並べる
  • 3次元測定機から出力されたCSV座標を読み込み、実際の測定位置に測定ポイント(球パーツ)をマッピングする
  • 工場全体のレイアウト図面(座標リスト)から、設備モデルを一瞬で自動配置する

といった、高度な自動化システムへと発展させることが可能です。

「マクロの記録」を卒業し、SolidWorksの内部データを直接コントロールする快感を、ぜひあなたの手で体感してください。
ここを乗り越えたあなたなら、もうどんなレイアウト作業も恐れることはありません。

分からなくなったら、いつでもこのコードに戻ってきてくださいね。応援しています!

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