【SolidWorks VBAを掌握する極限の知見】単位系の罠を断つ:`SwApp.SetUserPreferenceIntegerValue` によるドキュメント強制統制
歴戦の自動化エンジニアであれば、一度は悪夢を見たことがあるはずだ。
「数値を流し込んだはずが、生成されたモデルが数千倍のサイズになっている」、あるいは「海外拠点の図面を読み込んだ途端、アセンブリが崩壊した」。
原因の9割は 「単位系(MMGS / IPS)の暗黙の前提」 にある。
SolidWorks VBAの開発において、最も愚かで、最も頻発するバグが「単位の混同」だ。VBAのコード上で `100` と書いたとき、それがミリメートルなのか、メートルなのか、インチなのか。それはアクティブなドキュメントの設定依存であり、ユーザーがうっかりUI上の単位を変更した瞬間、君のコードはゴミを出力する凶器へと変貌する。
今回は、この環境依存の不確実性を完全に排除し、コードの実行文脈において単位系をハードコードレベルで支配するための極限の知見を授ける。
—
1. なぜ「アクティブドキュメントの単位系」を信用してはならないのか
初心者プログラマーは、以下のようなコードを平然と書く。
‘ = 危険なアンチパターン =
Dim swPart As ModelDoc2
Set swPart = swApp.NewDocument(“C:\Templates\Part.prtdot”, 0, 0, 0)
‘ ここでユーザーがテンプレート側の単位を変更していたらすべてが狂う
swPart.Extension.SetUserPreferenceStringValue swUserPreferenceStringValue_e.swDocumentUnitsLength, “millimeters”
甘い。これでは不十分だ。
SolidWorksのAPIにおける単位系は、アプリケーションレベルの設定、ドキュメントテンプレートのデフォルト設定、そしてセッションごとのユーザー設定が複雑に絡み合っている。
ここで登場するのが、アプリケーション全体の設定を強制上書きする `SwApp.SetUserPreferenceIntegerValue` である。
このメソッドを制す者のみが、環境に依存しない「絶対的堅牢性」を持つマクロを構築できる。
—
2. 単位系をコードで強制固定するメカニズム
SolidWorksのシステムオプションにおいて、単位系は数値の列挙体(Enum)として管理されている。
ドキュメント新規作成時、あるいは処理の開始直目に、以下のAPIを用いてアプリケーションのデフォルト単位系(またはドキュメント単位系)をプログラム側からねじ込む。
使用する主要なEnum
- `swUserPreferenceIntegerValue_e.swUnitSystem`
- `0`: IPS (インチ・ポンド・秒)
- `1`: MKS (メートル・キログラム・秒)
- `2`: CGS (センチメートル・グラム・秒)
- `3`: MMGS (ミリメートル・グラム・秒)
これを、マクロのイニシャライズ(初期化)フェーズで確実に叩く。
—
3. 【実戦コード】環境依存を殺す完全自動化テンプレート
以下のコードは、単にドキュメントを開く・作成するだけでなく、メモリの適切な管理と単位系の強制統制を同時に行う、チーフアーキテクト水準のプロダクションコードである。
Option Explicit
‘ ==============================================================================
‘ 模範的SolidWorks VBAモジュール: 単位系強制統制と安全なオブジェクトライフサイクル管理
‘ ==============================================================================
Sub Main_CreatePartWithStrictUnits()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim lRet As Long
‘ 1. SldWorks アプリケーションのインスタンス取得(Late/Early Bindingは環境に合せる)
Set swApp = Application.SldWorks
If swApp Is Nothing Then
MsgBox “SolidWorksが起動していません。”, vbCritical
Exit Sub
}
‘ 2. 【最重要】アプリケーションレベルで単位系を「MMGS (ミリメートル)」に強制固定
‘ ユーザーのUI設定に関わらず、この瞬間から数値はすべて「mm」として解釈される
lRet = swApp.SetUserPreferenceIntegerValue(swUserPreferenceIntegerValue_e.swUnitSystem, 3)
If lRet = 0 Then
MsgBox “単位系の強制設定に失敗しました。”, vbCritical
GoTo CleanUp
End If
‘ 3. 新規パーツ作成(適切なパスのテンプレートを指定)
Dim templatePath As String
templatePath = swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplatePart)
Set swModel = swApp.NewDocument(templatePath, 0, 0, 0)
If swModel Is Nothing Then
MsgBox “パーツドキュメントの作成に失敗しました。”, vbCritical
GoTo CleanUp
End If
‘ 4. ジオメトリ生成処理(例:100mm x 100mm のスケッチ)
‘ 単位系がMMGSに固定されているため、渡す数値「0.1」ではなく「100.0」が確実にミリメートルとして処理される
Call ExecuteGeometoryGeneration(swModel)
CleanUp:
‘ 5. 厳格なメモリ解放(COMオブジェクトの参照リークを完全阻止)
Set swModel = Nothing
Set swApp = Nothing
MsgBox “処理が正常に完了しました。”, vbInformation
End Sub
Private Sub ExecuteGeometoryGeneration(ByRef swModel As SldWorks.ModelDoc2)
‘ 単位系が保証された安全な空間でのフィーチャ操作
swModel.SketchManager.InsertSketch True
‘ センター長方形を描画(100mm x 100mm)
Dim boolstatus As Boolean
boolstatus = swModel.SketchManager.CreateCenterRectangle(0, 0, 0, 0.05, 0.05, 0) ‘ ※内部単位(メートル系API)を使う場合の注意点へ続く
swModel.SketchManager.InsertSketch False
End Sub
—
4. チーフアーキテクトからの深層警告:API内部単位の罠
ここで一つ、シニアエンジニアであっても見落としがちな極限の知見を共有しよう。
`SwApp.SetUserPreferenceIntegerValue` で単位系を `MMGS` に設定しても、すべてのAPIメソッドの引数がミリメートルを受け入れるわけではない。
例えば、一部の古いジオメトリ作成系APIや数学計算(MathUtility)のベクター値では、依然として「内部単位(MKS:メートル)」を要求するもの存在する。
- ユーザー入力・寸法値・フィーチャ定義(Feature Data):
- UI上の表示単位、および `SetUserPreferenceIntegerValue` で指定した単位系(MMGSならmm)に依存する。
- 低レイヤーのジオメトリ・数学系API(MathUtility / Body creation等):
- APIの仕様により、強制的に 「メートル (m)」 で渡す必要がある場合がある。
したがって、真に堅牢なシステムを構築する場合は、「ユーザーが入力するパラメータ」と「APIが要求する内部単位」の変換レイヤー(Wrapper)をコード内に一枚噛ませるべきだ。
‘ 単位変換ラッパーの概念例(ミリメートル入力を内部メートルへ変換)
Private Function ToInternalUnits(ByVal mmValue As Double) As Double
ToInternalUnits = mmValue / 1000#
End Function
—
5. まとめ
VBAにおけるマクロの品質は、「いかに環境の揺らぎを排除するか」で決まる。
ユーザーのPC環境、前回のセッションの状態、テンプレートの差異。これらすべてのノイズを `SwApp.SetUserPreferenceIntegerValue` でねじ伏せ、コードの実行文脈を完全に支配せよ。
妥協したコードは、現場を止める。
完璧に統制されたコードだけが、真の自動化をもたらすのだ。
