テンプレートの不備をコードでねじ伏せろ:図面単位系をミリメートルに強制固定する堅牢な設計思想
業務自動化の現場において、最も低レベルで、かつ最も致命的なバグは何か?
それは、複雑な計算アルゴリズムのミスではない。「単位系の不一致」だ。
設計者が意図せず「インチ」設定のテンプレートで図面を開き、そこにミリメートルベースの部品図を配置する。寸法値は一見正しく見えるが、内部的な精度や許容差の解釈が狂い、製造現場へ誤ったデータが流出する。この「静かなる破壊」を防ぐのが、我々自動化エンジニアの使命である。
本記事では、単に「単位を変えるコード」を提示するのではない。なぜテンプレートに頼るだけでは不十分なのか、そして、いかなる環境下でも確実にミリメートル(MMGS)を強制適用するための、プロダクションレベルの設計思想を伝授する。
1. なぜ「テンプレート設定」だけでは不完全なのか
多くの初学者は「正しい単位設定のテンプレートを作っておけばいい」と考える。しかし、実務の現場は理想通りには動かない。
1. テンプレートの汚染: 誰かが誤って設定を変更したテンプレートがサーバーにアップロードされる。
2. システムのデフォルト設定: SolidWorksのシステムオプションがインチに設定されている場合、新規作成時の挙動が不安定になるケースがある。
3. ユーザーの誤操作: 既存の図面を開き、そこから「新規図面」を作成する際、意図しない設定が引き継がれることがある。
エンジニアリングにおける「堅牢性(Robustness)」とは、「外部の不確定要素(ユーザーやテンプレート)に依存せず、プログラムが自身の目的を完遂すること」を指す。つまり、図面を開いた瞬間に、コード側から「お前は今日からミリメートルとして生きるのだ」と強制的に命令を下す必要がある。
2. APIの深淵:単位系を制御するオブジェクトの選択
SolidWorks APIにおいて、単位系を制御するには `ModelDoc2` インターフェース、あるいは `SystemOptions` を介したアプローチが必要だ。
単に表示上のラベルを変えるのではなく、ドキュメントの内部的な「システム単位(System Units)」を書き換える必要がある。ここで重要なのは、「ドキュメントが図面(Drawing)であることを確認してから処理を行う」というガード句の設計だ。部品(Part)やアセンブリ(Assembly)に対して図面用の処理を走らせることは、実行時エラー(Runtime Error)を招き、自動化プロセス全体の信頼性を失墜させる。
3. プロダクション・グレードのコード実装
以下に、実務でそのまま利用可能な、エラーハンドリングとオブジェクト検証を組み込んだ堅牢なVBAコードを示す。
'**
' Module: DrawingUnitEnforcer
' Description: 新規図面または開いている図面の単位系を強制的にミリメートル(MMGS)に設定する
' Author: Chief Architect
'**
Option Explicit
' SolidWorks API Constant (定義されていない場合のための定義)
Const swDocDRAWING As Long = 3
Const swUnitSystemMMGS As Long = 1 ' Millimeter, Gram, Second
Sub Main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
On Error GoTo ErrorHandler
' 1. SolidWorks インスタンスの取得
Set swApp = Application.SldWorks
If swApp Is Nothing Then
MsgBox "SolidWorksが起動していません。", vbCritical
Exit Sub
End If
' 2. アクティブなドキュメントの取得
Set swModel = swApp.ActiveDoc
' 3. ドキュメントが存在するか、かつ図面(Drawing)であるかの厳格なチェック
If swModel Is Nothing Then
MsgBox "ドキュメントが開かれていません。", vbExclamation
Exit Sub
End If
If swModel.GetType <> swDocDRAWING Then
MsgBox "このマクロは図面ファイルに対してのみ実行可能です。", vbExclamation
Exit Sub
End If
' 図面オブジェクトへのキャスト
Set swDraw = swModel
' --- 処理開始 ---
' 画面更新を停止してパフォーマンスを向上させる(大規模図面対策)
swApp.LockDoc2(swModel)
Debug.Print "単位系の強制適用を開始します..."
' 4. 単位系の書き換え (System Units を MMGS に設定)
' SetUserPreferenceIntegerValue を使用することで、ドキュメントプロパティを直接書き換える
' これにより、表示だけでなく内部計算の基準がミリメートルに固定される
Dim status As Boolean
status = swModel.SetUserPreferenceIntegerValue(swUserPreferenceIntegerValue_e.swUnitSystem, swUnitSystemMMGS)
If status Then
Debug.Print "単位系をミリメートル(MMGS)に設定しました。"
' 5. 再描画を行い、変更を視覚的に反映させる
swModel.ForceRebuild3 True
' 成功メッセージ(実運用ではログ出力に留めるのがプロの作法)
' MsgBox "単位系をミリメートルに強制適用しました。", vbInformation
Else
Err.Raise vbObjectError + 513, "DrawingUnitEnforcer", "単位系の設定に失敗しました。"
End If
' --- 処理終了 ---
swApp.UnlockDoc2(swModel)
Exit Sub
ErrorHandler:
' 異常終了時でも、ロックを解除してシステムを保護する
If Not swModel Is Nothing Then swApp.UnlockDoc2(swModel)
MsgBox "致命的なエラーが発生しました。" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Description: " & Err.Description, vbCritical, "Execution Error"
Debug.Print "Error: " & Err.Description
End Sub
4. アーキテクトの視点:このコードが「強い」理由
このコードが、巷に溢れる「コピペ用スクリプト」と一線を画す理由は、以下の3点にある。
① ライフサイクル管理(Lock/Unlock)
`swApp.LockDoc2` と `swApp.UnlockDoc2` を使用している。これは、大規模な図面において、単位系を変更する際の再計算(Rebuild)が何度も走るのを防ぎ、処理速度を劇的に向上させるだけでなく、処理中のユーザー操作による競合を防ぐための「防壁」である。
② 徹底した型検証(Type Checking)
`swModel.GetType <> swDocDRAWING` によるガード句。自動化ツールを全社展開する場合、ユーザーは「今何を開いているか」を意識せずにボタンを押す。不適切なオブジェクトに対してメソッドを叩くことは、アプリケーションのクラッシュを意味する。これを未然に防ぐ設計こそが、プロフェッショナルである。
③ 決定論的なエラーハンドリング
`On Error GoTo ErrorHandler` を実装し、エラー発生時でも `UnlockDoc2` を確実に実行するように設計している。もしロックしたままエラーで落ちれば、そのSolidWorksインスタンスは「操作不能」という最悪の状態に陥る。エンジニアは、「成功させること」以上に「失敗した時にシステムを壊さないこと」に責任を持たなければならない。
5. 次のステップへ:データベース連携を見据えて
もし君が、このマクロを単体のツールではなく、ERPやPDM(Product Data Management)と連携した巨大なシステムの一部として組み込むなら、単位設定は「ハードコード」してはならない。
「どのプロジェクトはミリメートルか?」「どの顧客はインチ指定か?」という情報を、外部のCSVやSQLデータベースから読み込み、`swUnitSystemMMGS` の値を動的に切り替えるように拡張せよ。
「コードは常に変化する環境に対して、いかに柔軟かつ強固であるべきか」
この問いを常に持ち続けること。それが、ただのプログラマーを、伝説的なアーキテクトへと変える唯一の道である。
