【SolidWorks VBA極限解説】図面テンプレート変更の悪夢を断つ!シートフォーマット破損を防ぐ安全な移行術
こんにちは。開発プロジェクトの現場で数々の数万点規模のアセンブリや図面の自動化を手掛けてきたチーフアーキテクトの私だ。
SolidWorksのマクロ開発において、最もフラストレーションが溜まる瞬間の一つを知っているか?
それは「全社規格の改定や顧客指定のフォーマット変更に伴い、既存図面のシートフォーマットを一括置換した瞬間、丹念に配置したビューが吹き飛び、寸法線が宙を舞い、表題欄のカスタムプロパティがリンク切れを起こす」という、あの悪夢のような現象だ。
ネット上のサンプルコードをそのままコピペして、`SetTemplatePrts` や `SetupSheet5` あたりのAPIを適当に叩いていないか?
「動いたからよし」とするその場しのぎのコードは、実務の現場では地雷原を裸足で歩くようなものだ。
今回は、SolidWorks APIのオブジェクトモデルの裏側にある「ライフサイクル」と「再描画・更新の非同期性」を完全に掌握し、1バイトのデータ破損も許されないプロダクション環境で使える堅牢なシートフォーマット移行術をロジカルかつシャープに伝授する。
—
なぜ従来のコードはシートフォーマット破損を招くのか?
初心者が陥る最大の罠は、「図面テンプレート(Drawing Template – .drwdot)」と「シートフォーマット(Sheet Format – .slddrt)」の概念を混同している点にある。
- テンプレート (.drwdot): ページサイズ、単位、ドキュメントプロパティ、デフォルトのビュー設定、そしてデフォルトのシートフォーマットへの参照を持つ「親」である。
- シートフォーマット (.slddrt): 枠線、表題欄、REVマークなどの「外枠のグラフィックスとスケッチエンティティ」の集合体である。
APIで単に `SetSheetProperties` やシートフォーマットの再適用を行うと、SolidWorksの内部エンジンは既存のビュー座標系(Sheet Space)と新しいフォーマットの原点・サイズを再計算しようとする。この時、ビューとシートの紐付けが一時的にロストするか、スケールが強制リセットされることで、アノテーションのゾンビ化や消失が発生するのだ。
これを防ぐためには、APIの呼び出し順序を厳密に制御し、トランザクション的な安全性を担保しなければならない。
—
堅牢な移行を実現する3つのアーキテクチャ原則
1. アクティブビューの退避と復元: 操作中のビューコンテキストを明確にし、処理前後の状態を一致させる。
2. 適切なメソッドの選択: `SetSheetProperties` を使用する際、不要な再描画や強制スケーリングをバイパスするパラメータ設計を行う。
3. エラーハンドリングとファイルロックの回避: 読取専用ファイルの誤操作や、バックグラウンドでのドキュメント解放漏れ(メモリリーク)を完全に防ぐ。
—
【プロダクションコード】安全なシートフォーマット一括置換VBA
以下のコードは、単なるスニペットではない。エラーハンドリング、ビューの保護、そしてSolidWorksの重い描画エンジンを効率よく制御するためのベストプラクティスを凝縮した実用コードだ。
Option Explicit
‘ ==============================================================================
‘ 担当者必見:図面シートフォーマット安全置換マクロ
‘ Architecture: SolidWorks API Expert Grade
‘ ==============================================================================
Public Sub ExecuteSafeSheetFormatMigration()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDrawing As SldWorks.DrawingDoc
Dim swSheet As SldWorks.Sheet
‘ 厳格なアプリケーション参照の取得
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ 1. 事前検証(ドキュメントの型チェック)
If swModel Is Nothing Then
MsgBox “アクティブなドキュメントが存在しません。”, vbCritical, “致命的エラー”
Exit Sub
End If
If swModel.GetType <> swDocDRAWING Then
MsgBox “このマクロは図面ドキュメント(.slddrw)でのみ実行可能です。”, vbExclamation, “型不一致”
Exit Sub
End If
Set swDrawing = swModel
‘ 2. 画面描画の凍結(パフォーマンス爆弾の回避とちらつき防止)
swModel.Visible = False
swApp.CommandInProgress = True
On Error GoTo ErrorHandler
Dim sheetNames As Variant
Dim i As Long
Dim newSheetFormatPath As String
‘ 新しいシートフォーマットの絶対パス(環境に合わせて書き換えてください)
newSheetFormatPath = “C:\Standard_Templates\A3_New_Format.slddrt”
‘ ファイル存在チェック
If Dir(newSheetFormatPath) = “” Then
Err.Raise vbObjectError + 512, “SheetMigration”, “指定されたシートフォーマットが見つかりません: ” & newSheetFormatPath
End If
sheetNames = swDrawing.GetSheetNames
‘ 3. トランザクション処理開始
swModel.Extension.SetLockDeselect True ‘ 意図しない選択解除を防ぐ
For i = LBound(sheetNames) To UBound(sheetNames)
‘ 対象シートへアクティブ化
Dim status As Boolean
status = swDrawing.ActivateSheet(sheetNames(i))
If status Then
Set swSheet = swDrawing.GetCurrentSheet
Dim currentScale1 As Double
Dim currentScale2 As Double
Dim currentWidth As Double
Dim currentHeight As Double
Dim paperSize As Long
‘ 現在のシートプロパティ(サイズ・スケール)を退避
paperSize = swSheet.GetSize
swSheet.GetScale currentScale1, currentScale2
currentWidth = swSheet.GetSheetProperties4(paperSize, 0, currentScale1, currentScale2, True, currentWidth, currentHeight)
‘ 【核心部分】ビューやアノテーションの位置を破壊しないシートフォーマットの適用
‘ 引数: テンプレート名, シートフォーマット名, 用紙サイズ, 尺度1, 尺度2, カスタムプロパティを継承するかどうか
Dim formatApplied As Boolean
formatApplied = swSheet.SetupSheet5( _
swSheet.GetName(), _
paperSize, _
currentScale1, _
currentScale2, _
True, _
newSheetFormatPath, _
currentWidth, _
currentHeight, _
“Default” _
)
If Not formatApplied Then
Err.Raise vbObjectError + 513, “SheetMigration”, “シート ‘” & sheetNames(i) & “‘ のフォーマット適用に失敗しました。”
End If
End If
Next i
‘ 4. クリーンアップと保存処理の準備
swModel.Extension.SetLockDeselect False
swApp.CommandInProgress = False
swModel.Visible = True
‘ 再描画の強制実行
swModel.WindowRedraw
swModel.ForceRebuild3 False
MsgBox “すべてのシートフォーマットの安全な移行が完了しました。”, vbInformation, “成功”
Exit Sub
ErrorHandler:
‘ 異常系ハンドリング:確実にUIとロックを復旧させる
swModel.Extension.SetLockDeselect False
swApp.CommandInProgress = False
swModel.Visible = True
swModel.WindowRedraw
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “異常終了”
End Sub
—
ヴぁいタールなポイントを解説しよう。
`swSheet.SetupSheet5` の採用理由
古いAPIである `SetSheetProperties` や `SetupSheet2` は、フォーマット変更時にビューのスケールやアンカーポイントの再計算ロジックが脆弱である。`SetupSheet5` を適切に用いることで、既存の用紙サイズ・スケール比率(`currentScale1` / `currentScale2`)を維持したまま、バックグラウンドのグラフィックレイアウト(.slddrt)だけを安全に差し替えることが可能になる。
`swApp.CommandInProgress = True` と描画凍結のコンボ
数千枚の図面をバッチ処理する際、SolidWorksが毎シートの変更ごとにグラフィック画面を再描画(Viewport Update)すると、処理時間が何十倍にも膨れ上がり、最悪の場合はCOMオブジェクトのタイムアウトエラーを引き起こす。
`swModel.Visible = False` とコマンド進行中フラグを組み合わせることで、完全なサイレント・高速実行環境を作り出すことができる。
—
データベース連携・大規模バッチ処理への拡張性
もし君が、単体図面ではなく「PDMからチェックアウトした数百枚の図面」に対してこの処理を自動適用するツールを作っているのであれば、以下の設計を必ず組み込んでほしい。
1. ドキュメントの明示的な解放 (ReleaseComObject):
VBA単体ではメモリ解放のタイミングが曖昧になることがある。VB.NET (.NET Framework / .NET 6+) に移行し、`Marshal.ReleaseComObject` を用いてCOMコンテキストを完全に掃除しながらループを回すこと。メモリリークはSolidWorksマクロ開発者の最大の敵だ。
2. トランザクションログの出力:
どの図面が成功し、どの図面の表題欄カスタムプロパティ(材質や承認者名など)のリンクが切れたかをCSVやDBにログとして吐き出させる仕組みをラップすること。
—
チーフアーキテクトからの総括
「動けばいいや」で作られたコードは、組織の成長と共に技術的負債となり、やがてエンジニアの時間を奪うモンスターと化す。
今回紹介したシートフォーマットの移行術は、単なるAPIの組み合わせではない。SolidWorksという重厚長大なCADエンジンのライフサイクルを敬い、破綻のない手順を踏むための「エンジニアリングの作法」だ。
この知見を君のプロジェクトに組み込み、無駄な手戻りとトラブルのない、真にスマートな自動化環境を構築してほしい。健闘を祈る。
