SolidWorks VBAを掌握する極限の知見
【数式・グローバル変数】EquationMgr.GetEquationCountとValue2プロパティを用いたパーツ内寸法の動的数式書き換えバッチ
開発プロジェクトの現場において、設計変更の波をかぶるたびに手動でパーツの寸法やグローバル変数を書き換えてはリビルドをかける……そんな非生産的な作業にいつまで時間をドブに捨てているのか。
「数式(Equation)」や「グローバル変数」は、SolidWorksのパラメトリック設計の心臓部だ。しかし、この心臓部をAPIから制御しようとした途端、多くの開発者が「数式のインデックスズレ」「型ミスマッチ」「サイレントエラー(エラーを吐かずに勝手に落ちる、あるいは不正な値に書き換わる)」という泥沼にハマり込む。
ネット上の浅薄なリファレンスをコピペしただけのコードでは、実務の巨大アセンブリや複雑なコンフィギュレーションを持つパーツの波状攻撃の前にはひとたまりもなくクラッシュする。
今回は、`EquationMgr`(数式マネージャー)のライフサイクルを完全に掌握し、`GetEquationCount`と`Value2`プロパティを駆使して、「安全に、かつ爆速でパーツ内寸法の数式を一括書き換え・リビルドするプロダクションコード」を伝授する。
—
1. なぜ安易な数式書き換えはバグを生むのか?(アーキテクチャの罠)
SolidWorksのAPIで数式を操作する際、多くのエンジニアが犯す最大の過ちが「数式のインデックス(行番号)を固定で決め打ちする」こと、あるいは「エラーハンドリングなしに `Value2` を直叩きする」ことだ。
罠その1:インデックスの変動
`EquationMgr` の中にある数式は、追加・削除が行われるたびにインデックスが動的に変動する。上から順に `0, 1, 2…` と並んでいるからといって、特定の数式をインデックス番号だけで指定して書き換えると、設計意図とは全く別の寸法が書き換わり、最悪の場合パーツが完全に破綻する(ジオメトリの崩壊)。
罠その2:数式文字列の構文エラー
SolidWorksの数式は、構文規則が非常にシビアだ。全角文字の混入、ダブルクォーテーションのミス、存在しない変数名や寸法名(`D1@Extrude1`など)を指定すると、APIは容赦なくエラーを返すか、あるいは最悪なことに「不正な数式」としてミュートされた状態で数式マネージャーに登録される。
これらを完全に防ぐためには、「名前(グローバル変数名や寸法名)でターゲットを特定し、安全な型で値を流し込み、即座にリビルドを強制する」という鉄則を守らなければならない。
—
2. 実務で耐えうる堅牢な設計アプローチ
今回のバッチ処理の要件定義は以下の通りだ。
1. アクティブなパーツドキュメントの安全な取得(図面やアセンブリが混入していないか厳密に型チェックする)。
2. 数式マネージャー(`IEquationMgr`)の取得。
3. グローバル変数の走査と特定(`GetEquationCount` で総数を取得し、ループ内で名前をパースしてターゲットを絞り込む)。
4. `Value2` プロパティを通じた安全な数値・数式の書き換え。
5. 自動リビルド(`ForceRebuild3`)の確実な実行。
—
3. プロダクションコード:グローバル変数一括書き換えバッチ
以下のコードは、エラーハンドリング、オブジェクトのライフサイクル管理、そして実務で耐えうる堅牢性をすべて備えたSolidWorks VBAのマクロだ。そのまま自社の業務自動化ツールに組み込んでほしい。
Option Explicit
‘ ==============================================================================
‘ 処理名: パーツ内グローバル変数・数式動的書き換えバッチ
‘ 概要: EquationMgrを完全に制御し、指定したグローバル変数の数式/値を
‘ 安全に書き換えて一括リビルドを実行するプロダクションコード。
‘ ==============================================================================
Sub RunEquationBatchUpdate()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Dim swEqMgr As SldWorks.EquationMgr
Set swApp = Application.SldWorks
If swApp Is Nothing Then Exit Sub
‘ 現在アクティブなドキュメントを取得
Set swModel = swApp.ActiveDoc
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “致命的エラー”
Exit Sub
End If
‘ ドキュメントタイプがパーツ(Part)であるか厳密にチェック
If swModel.GetType <> swDocPART Then
MsgBox “このマクロは「パーツ(.sldprt)」ファイルでのみ実行可能です。”, vbExclamation, “型不一致”
Exit Sub
End If
Set swPart = swModel
‘ 数式マネージャーを取得
Set swEqMgr = swModel.GetEquationMgr
If swEqMgr Is Nothing Then
MsgBox “数式マネージャーの取得に失敗しました。”, vbCritical, “APIエラー”
Exit Sub
End If
‘ ————————————————————————–
‘ 書き換え設定の定義(実務では外部CSVやDB、UIの入力値から動的に取得する)
‘ ————————————————————————–
Const TARGET_VARIABLE As String = “Length” ‘ 変更したいグローバル変数名
Const NEW_VALUE As String = “150.0” ‘ 新しい値(または数式文字列: “Width 2” など)
Dim eqCount As Long
eqCount = swEqMgr.GetEquationCount
If eqCount = 0 Then
MsgBox “このパーツには登録されている数式・グローバル変数がありません。”, vbInformation, “情報”
Exit Sub
End If
Dim i As Long
Dim targetIndex As Long
targetIndex = -1
‘ ————————————————————————–
‘ 【重要】インデックスではなく名前(グローバル変数名)でターゲットを特定する
‘ ————————————————————————–
For i = 0 To eqCount – 1
Dim eqStr As String
eqStr = swEqMgr.Equation(i)
‘ Equation文字列の構造は ” “GlobalVariableName” = 100 ” のようになっている
‘ 厳密にパースするか、左辺にターゲット名が含まれているか確認する
If InStr(1, eqStr, “””” & TARGET_VARIABLE & “”””, vbTextCompare) > 0 Then
targetIndex = i
Exit For
End If
Next i
‘ トランザクション的処理の開始(パフォーマンス向上と画面描画停止)
swModel.Extension.EnableAnimations = False
On Error GoTo ErrorHandler
If targetIndex >= 0 Then
‘ — 既存の数式/グローバル変数を更新する場合 —
‘ Value2プロパティ(インデックス指定)を用いて値を直接書き換える
‘ ※注意: Value2に渡す文字列は “= 150.0” のようにイコールを含める必要がある場合があるが、
‘ Equation自体を書き換える方が安全なケースが多い。用途に合わせて使い分ける。
‘ ここではEquation自体を安全に再定義するメソッドを使用
Dim formattedEquation As String
formattedEquation = “””” & TARGET_VARIABLE & “” = ” & NEW_VALUE
Dim setResult As Long
setResult = swEqMgr.SetEquation(targetIndex, formattedEquation)
If setResult <> 0 Then
Err.Raise vbObjectError + 1000, “EquationUpdate”, “数式の更新に失敗しました。エラーコード: ” & setResult
End If
Else
‘ — 存在しない場合は新規追加する —
Dim addResult As Long
Dim newEqString As String
newEqString = “””” & TARGET_VARIABLE & “” = ” & NEW_VALUE
‘ 引数: Index (-1で末尾に追加), Equation
addResult = swEqMgr.Add(-1, newEqString)
If addResult < 0 Then Err.Raise vbObjectError + 1001, "EquationAdd", "グローバル変数の新規追加に失敗しました。構文を確認してください。" End If End If ' -------------------------------------------------------------------------- ' 強制リビルドの実行(最重要ステップ) ' -------------------------------------------------------------------------- ' 単なるRebuildではなく、強制全体リビルド(ForceRebuild3)を叩くことで ' 依存関係にあるフィーチャのジオメトリを確実に再計算させる。 Dim rebuildSuccess As Boolean rebuildSuccess = swModel.ForceRebuild3(False) If Not rebuildSuccess Then Err.Raise vbObjectError + 1002, "Rebuild", "パーツのリビルドに失敗しました。ジオメトリの破綻を確認してください。" End If ' 正常終了時のクリーンアップ swModel.Extension.EnableAnimations = True MsgBox "グローバル変数 [" & TARGET_VARIABLE & "] の更新とリビルドが正常に完了しました。", vbInformation, "処理成功" Exit Sub ErrorHandler: ' 異常終了時も必ず画面描画フラグを戻す(戻し忘れるとSolidWorksがフリーズしたように見える) swModel.Extension.EnableAnimations = True MsgBox "予期せぬエラーが発生しました。" & vbCrLf & _ "Description: " & Err.Description, vbCritical, "致命的エラー" End Sub ---
4. チーフアーキテクトからの実務アドバイス:ファイル・DB連携の極意
このマクロを単体のオモチャで終わらせず、社内の生産システムやPDM、あるいはExcel・Access等のデータベースと結合した「真の自動化バッチ」へと昇華させるための極意を授ける。
1. 外部データとの非同期分離
バッチ処理を行う際は、VBAのコード内に直接変更値をハードコーディングしてはならない。必ず外部のCSVやJSON、あるいはDBから「パーツ番号」「変数名」「変更値」のセットを読み込ませ、ループ処理で次々とパーツを開いては書き換えて保存(`Save3`)して閉じる(`CloseDoc`)というヘッドレス(UI非表示)に近い一括バッチパイプラインを構築すること。
2. スワップファイルとトランザクション管理
大量のパーツを一括置換する際、途中でSolidWorksが落ちたり、不正な数式で保存されてしまうと取り返しがつかない。処理の開始前には必ず `FileSystemObject` 等を用いて対象ファイルのバックアップを自動生成する防衛機制(セーフティネット)をコードに組み込むのが、プロのエンジニアの流儀だ。
3. `EnableAnimations = False` の徹底
数式を変更してリビルドを走らせるたびに、SolidWorksがいちいちグラフィック画面を再描画していたら、1パーツあたり数秒のロスが積もり積もって、何千パーツもあるプロジェクトでは数時間の無駄になる。上記のコードにも入れている通り、一括処理の際は必ず画面描画やアニメーションをミュートし、処理が終わった瞬間に解放する鉄則を忘れてはならない。
—
終わりに
SolidWorks APIは、正しく使えばあなたの右腕となり、数日かかる設計変更作業をわずか数秒のバッチ処理へと変えてくれる最強の武器だ。しかし、オブジェクトのライフサイクルやインデックスの概念を無視した実装は、組織全体に不具合の爆弾をばらまくことにもなり得る。
今回解説した『名前による特定』『厳密なエラーハンドリング』『強制リビルドの制御』をマスターすれば、あなたの書くVBAコードの信頼性はプロの域へと達するだろう。
妥協のない設計で、真の業務自動化を掴み取れ。
