序文:そのコードは「動く」だけか、それとも「設計」されているか
SolidWorks VBAの世界へようこそ。私はこれまで数えきれないほどの自動化プロジェクトを救済してきたが、初心者が最も頻繁に、そして最も無残に躓くのが「ドキュメントの初期化」と「ファイル保存」だ。
ネットに転がっている「とりあえず動く」サンプルコードをコピペするのは今日で終わりにしよう。実務で求められるのは、ユーザーの環境が変わっても、テンプレートの配置が変わっても、あるいは保存パスに拡張子が抜けていても、涼しい顔をして処理を完遂する「堅牢なプログラム」だ。
今回は、`PartDoc`オブジェクトを支配し、拡張子の呪縛から解放されたプロレベルのパーツ新規作成ロジックを伝授する。
—
1. 「ハードコード」という名の時限爆弾を排除せよ
初心者がやりがちな最大のミスは、テンプレートファイルのパスをソースコードに直接書き込む(ハードコードする)ことだ。
‘ 悪い例:自分のPCでしか動かないコード
Set swModel = swApp.NewDocument(“C:\ProgramData\SolidWorks\SOLIDWORKS 2023\templates\Part.prtdot”, 0, 0, 0)
これをやると、SolidWorksのバージョンが変わったり、他人のPCで実行した瞬間にランタイムエラーで爆死する。プロは、SolidWorksのシステム設定から「現在アクティブなテンプレートパス」を動的に取得する。これが鉄則だ。
—
2. ModelDoc2 と PartDoc:ポインタの真実
SolidWorks APIにおいて、`ModelDoc2` はすべてのドキュメント(部品・アセンブリ・図面)の基底クラスだ。しかし、パーツ固有の操作(フィーチャの追加や材料の設定)を行うには、これを `PartDoc` として扱う必要がある。
多くのエンジニアがこの「型」の意識を曖昧にしているが、オブジェクトのライフサイクルを管理する上では、「今どのインターフェースを操作しているのか」を常に意識せよ。
—
3. 実践:プロダクション・グレードのパーツ作成コード
以下に、実務でそのまま使える堅牢なコードを示す。このコードには、テンプレートパスの自動取得、拡張子の自動補完、そしてエラーハンドリングが組み込まれている。
Option Explicit
”’
”’
Public Sub CreateNewPartRobustly()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Dim templatePath As String
Dim savePath As String
Dim errors As Long
Dim warnings As Long
‘ 1. アプリケーションインスタンスの捕捉
Set swApp = Application.SldWorks
‘ 2. システム設定から「デフォルトの部品テンプレート」を動的に取得
‘ これにより、環境依存のエラーを完全に排除する
templatePath = swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplatePart)
If templatePath = “” Then
MsgBox “デフォルトテンプレートが見つかりません。SolidWorksのオプションを確認してください。”, vbCritical
Exit Sub
End If
‘ 3. 新規ドキュメント作成
‘ NewDocumentの引数: (テンプレートパス, 用紙サイズ, 幅, 高さ)
Set swModel = swApp.NewDocument(templatePath, 0, 0, 0)
If swModel Is Nothing Then
MsgBox “ドキュメントの作成に失敗しました。”, vbCritical
Exit Sub
End If
‘ 4. PartDocインターフェースへのキャスト(パーツ固有の操作を可能にする)
Set swPart = swModel
‘ — ここでジオメトリ生成などの処理を行う —
Debug.Print “新規パーツを初期化しました: ” & swModel.GetTitle
‘ 5. 安全な保存処理(拡張子なしパスへの対応)
‘ 例として、デスクトップに「NewPart_2023」という名前で保存したい場合
savePath = CreateObject(“WScript.Shell”).SpecialFolders(“Desktop”) & “\NewPart_Sample”
‘ 拡張子をチェックし、無ければ付与する(保守性の極意)
savePath = ValidateFilePath(savePath, “.sldprt”)
‘ SaveAs3メソッドによる保存
‘ swSaveAsOptions_Silent: ダイアログを表示せずに上書き/保存
Dim status As Boolean
status = swModel.Extension.SaveAs3(savePath, swSaveAsOptions_e.swSaveAsOptions_Silent, _
swSaveAsOptions_e.swSaveAsOptions_CopyAndOpen, _
Nothing, errors, warnings)
If status Then
MsgBox “正常に保存されました: ” & savePath, vbInformation
Else
MsgBox “保存失敗。エラーコード: ” & errors, vbExclamation
End If
End Sub
”’
”’
Private Function ValidateFilePath(ByVal path As String, ByVal extension As String) As String
If Right(LCase(path), Len(extension)) <> LCase(extension) Then
ValidateFilePath = path & extension
Else
ValidateFilePath = path
End If
End Function
—
4. チーフアーキテクトによる深掘り解説
なぜ `SaveAs3` を使うのか?
旧来の `SaveAs2` や `SaveAs` は、現代のAPI設計では非推奨(Obsolete)に近い。`SaveAs3` はエラーや警告の詳細をビットフラグで返してくれるため、なぜ保存に失敗したのか(読み取り専用なのか、ディスク容量不足なのか等)を正確にトラッキングできる。
拡張子補完の重要性
ユーザーや外部データベースから「ファイル名」だけが渡されるケースは非常に多い。そこでプログラム側が `ValidateFilePath` のようなユーティリティ関数を持っていないと、拡張子なしのファイルが生成され、Windowsが認識できないゴミデータを作成してしまう。これは自動化ツールの信頼性を著しく損なう。
データベース連携への布石
実務では、この後に「作成したパーツ名をDBに登録する」といった処理が続く。その際、`swModel.GetPathName` を使うと、保存されるまでは空文字が返ってくることに注意せよ。ドキュメントを初期化した直後(保存前)は `GetTitle` で仮の名前を取得し、保存後にフルパスを確定させる。この順序を間違えると、DBに空のパスを登録するバグを仕込むことになる。
—
結論:神は細部に宿る
初心者は「線が引けた」「穴が開いた」と喜ぶが、プロは「いかにしてプログラムを落とさないか」「いかにしてユーザーの環境を汚さないか」に心血を注ぐ。
今回紹介したテンプレートパスの動的取得と、拡張子のバリデーションは、地味だが極めて重要な「プロの作法」だ。この基盤の上にこそ、複雑なジオメトリ生成アルゴリズムが積み上がるのである。
君のコードが、単なる自動化ツールから、真の「エンジニアリング資産」へと昇華することを期待している。
