1. 大規模図面自動生成におけるアーキテクチャとボトルネック
SolidWorks APIを利用した図面自動化において、最もエンジニアを悩ませるのは「単一図面内のマルチシート(複数シート)動的生成におけるパフォーマンス低下とCOMオブジェクトの肥大化」である。
UI上の手動操作を単にマクロ記録したようなコードは、シート数が増えるにつれて指数関数的に処理速度が低下し、最終的にはSolidWorksプロセスのクラッシュやメモリリークを引き起こす。この現象の根本原因は、SolidWorksのオブジェクトモデル(`SldWorks` -> `ModelDoc2` -> `DrawingDoc` -> `Sheet`)におけるイベント伝播、ビューの再計算(Rebuild)、そして不必要なGUI描画のオーバーヘッドにある。
[SldWorks]
│
└── [ModelDoc2] (Type: swDocDRAWING)
│
└── [DrawingDoc]
│
├── [Sheet: “Sheet1”] (A3 / Assembly View)
├── [Sheet: “Sheet2”] (A4 / Part Detail)
└── [Sheet: “Sheet3”] (A4 / BOM & Section)
本稿では、単一の3Dモデル(アセンブリまたはパーツ)から、用途に応じた異サイズ用紙(A3/A4等)、異スケール、第一角法/第三角法の異なるシート群を高速かつ堅牢に自動生成する「プロダクション環境レベルのアーキテクチャ」を解説する。
—
2. コア・メカニズム:`NewSheet4` と `SetProperties2` の解剖
マルチシート生成を制御する中核メソッドは `IDrawingDoc::NewSheet4` と `ISheet::SetProperties2` である。これらを正しく理解せずに運用すると、テンプレートの読み込み失敗や図枠(Sheet Format)の不一致が多発する。
2.1 `IDrawingDoc::NewSheet4` のパラメータ構造
`NewSheet4` は、新しいシートをドキュメントに追加するための最下層APIである。
Function NewSheet4( _
ByVal Name As String, _
ByVal PaperSize As Long, _
ByVal TemplateIn As Long, _
ByVal Scale1 As Double, _
ByVal Scale2 As Double, _
ByVal FirstAngle As Boolean, _
ByVal TemplateName As String, _
ByVal Width As Double, _
ByVal Height As Double, _
ByVal PropertyViewName As String _
) As Boolean
- `PaperSize` (`swDwgPaperSizes_e`): `swDwgPaperA3size` や `swDwgPapersUserDefined` を指定。カスタムサイズの場合は `Width` と `Height` が適用される。
- `TemplateIn` (`swDwgTemplates_e`): `swDwgTemplateCustom` を指定することで、独自の図枠ファイル(`.slddrt`)を適用可能。
- `Scale1` / `Scale2`: 分子と分母(例:1:5 のスケールを設定する場合、`Scale1 = 1`, `Scale2 = 5`)。
- `FirstAngle`: `True` で第一角法、`False` で第三角法(日本国内の機械設計では基本的に `False`)。
- `PropertyViewName`: リンクするプロパティ(カスタムプロパティ等の参照元)として指定するビュー名。
2.2 `ISheet::SetProperties2` による動的再設定
シート生成後、あるいは既存シートのプロパティを破壊せずに変更する場合は `ISheet::SetProperties2` を使用する。
Function SetProperties2( _
ByVal PaperSize As Long, _
ByVal TemplateIn As Long, _
ByVal Scale1 As Double, _
ByVal Scale2 As Double, _
ByVal FirstAngle As Boolean, _
ByVal Width As Double, _
ByVal Height As Double, _
ByVal KeepExistingManipulators As Boolean _
) As Boolean
2.3 描画ロックと計算負荷の極限削減
マルチシート生成時、1シート追加するごとにSolidWorksは画面描画と図面ビューの再計算を行う。これを抑制するために、以下の3重の対策を講じる。
1. `IModelDocExtension::EnableGraphicsUpdate`: 画面描画の全停止。
2. `ISldWorks::CommandInProgress`: SolidWorks内部のバックグラウンドイベント発火の抑制。
3. 非アクティブシート処理: 可能な限りシート切り替え(`ActivateSheet`)を行わずにバックグラウンドで操作を完結させる。
—
3. 完全実装コード:堅牢なマルチシート図面自動生成エンジン
以下のVBAコードは、プロダクション環境での使用を想定した完全な実装例である。モデルファイルから「A3全体図シート」「A4構成品詳細シート」を自動生成し、ビューの配置、スケールの個別適用、明示的なメモリ解放までを一貫して行う。
Option Explicit
‘ ==============================================================================
‘ 構造体・定数定義
‘ ==============================================================================
Private Type SheetConfig
SheetName As String
PaperSize As Long ‘ swDwgPaperSizes_e
TemplatePath As String ‘ .slddrtファイルのフルパス
ScaleNumerator As Double ‘ スケール分子
ScaleDenominator As Double ‘ スケール分母
IsFirstAngle As Boolean ‘ True: 第一角法, False: 第三角法
Width As Double ‘ カスタムサイズ時用(m)
Height As Double ‘ カスタムサイズ時用(m)
End Type
‘ Windows APIによる高精度タイム計測(デバッグ・パフォーマンス検証用)
If VBA7 Then
Private Declare PtrSafe Function GetTickCount Lib “kernel32” () As Long
Else
Private Declare Function GetTickCount Lib “kernel32” () As Long
End If
‘ ==============================================================================
‘ メイン処理エントリポイント
‘ ==============================================================================
Public Sub Execute_MultiSheet_Generation()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swModExt As SldWorks.ModelDocExtension
Dim startTime As Long
startTime = GetTickCount()
On Error GoTo ErrorHandler
‘ SolidWorksインスタンス取得
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ ドキュメント検証
If swModel Is Nothing Then
Err.Raise vbObjectError + 512, , “アクティブなドキュメントが存在しません。”
End If
If swModel.GetType <> swDocDRAWING Then
Err.Raise vbObjectError + 513, , “本マクロは図面ドキュメント(.slddrw)で実行してください。”
End If
Set swDraw = swModel
Set swModExt = swModel.Extension
‘ ————————————————————————–
‘ パフォーマンス最適化: 描画およびイベントの停止
‘ ————————————————————————–
swApp.CommandInProgress = True
swModExt.EnableGraphicsUpdate = False
‘ ————————————————————————–
‘ シート構成データの定義(実務では外部JSON/CSV/DBから動的ロードを推奨)
‘ ————————————————————————–
Dim configs(1) As SheetConfig
‘ シート1: A3 総組み立て図用
With configs(0)
.SheetName = “Top_Assembly_A3”
.PaperSize = swDwgPaperA3size
.TemplatePath = “C:\SolidWorks_Templates\A3_Landscape.slddrt”
.ScaleNumerator = 1#
.ScaleDenominator = 10#
.IsFirstAngle = False
.Width = 0.42
.Height = 0.297
End With
‘ シート2: A4 詳細図用
With configs(1)
.SheetName = “Component_Detail_A4”
.PaperSize = swDwgPaperA4size
.TemplatePath = “C:\SolidWorks_Templates\A4_Portrait.slddrt”
.ScaleNumerator = 1#
.ScaleDenominator = 2#
.IsFirstAngle = False
.Width = 0.21
.Height = 0.297
End With
‘ ————————————————————————–
‘ マルチシート生成ループ
‘ ————————————————————————–
Dim i As Long
Dim currentSheet As SldWorks.Sheet
Dim boolStatus As Boolean
For i = LBound(configs) To UBound(configs)
‘ 初回シート(デフォルトのSheet1)の書き換えか、新規シート追加かの分岐
If i = 0 And swDraw.GetSheetCount = 1 Then
Set currentSheet = swDraw.GetCurrentSheet()
currentSheet.SetName configs(i).SheetName
‘ 既存シートのプロパティを再設定
boolStatus = currentSheet.SetProperties2( _
configs(i).PaperSize, _
swDwgTemplateCustom, _
configs(i).ScaleNumerator, _
configs(i).ScaleDenominator, _
configs(i).IsFirstAngle, _
configs(i).Width, _
configs(i).Height, _
True)
‘ 図枠(Sheet Format)の適用
If configs(i).TemplatePath <> “” Then
currentSheet.SetTemplateName configs(i).TemplatePath
currentSheet.ReloadTemplate True
End If
Else
‘ 新規シートの追加
boolStatus = swDraw.NewSheet4( _
configs(i).SheetName, _
configs(i).PaperSize, _
swDwgTemplateCustom, _
configs(i).ScaleNumerator, _
configs(i).ScaleDenominator, _
configs(i).IsFirstAngle, _
configs(i).TemplatePath, _
configs(i).Width, _
configs(i).Height, _
“”)
Set currentSheet = swDraw.Sheet(configs(i).SheetName)
End If
If Not boolStatus Then
Debug.Print “Warning: シート ‘” & configs(i).SheetName & “‘ の設定適用に失敗しました。”
End If
‘ シート固有のビュー配置等のサブルーチン呼び出し(参照渡し)
BuildSheetContents swDraw, currentSheet, configs(i)
‘ 明示的オブジェクト解放(ループ内リーク防止)
Set currentSheet = Nothing
Next i
‘ 最初のシートをアクティブ化してビューを全表示
swDraw.ActivateSheet configs(0).SheetName
swModel.ViewZoomtofit2
CleanUp:
‘ ————————————————————————–
‘ 後処理: ロック解除と明示的メモリ解放
‘ ————————————————————————–
On Error Resume Next
If Not swModExt Is Nothing Then swModExt.EnableGraphicsUpdate = True
If Not swApp Is Nothing Then swApp.CommandInProgress = False
Set currentSheet = Nothing
Set swDraw = Nothing
Set swModExt = Nothing
Set swModel = Nothing
Set swApp = Nothing
Debug.Print “処理完了: 実行時間 ” & (GetTickCount() – startTime) & ” ms”
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Number & vbCrLf & Err.Description, vbCritical, “SolidWorks API Error”
Resume CleanUp
End Sub
‘ ==============================================================================
‘ ビュー配置およびコンテンツ生成サブルーチン
‘ ==============================================================================
Private Sub BuildSheetContents( _
ByRef swDraw As SldWorks.DrawingDoc, _
ByRef swSheet As SldWorks.Sheet, _
ByRef config As SheetConfig)
‘ ※実際の開発では、対象モデルのパスを取得し CreateDrawViewFromModelView3 等で
‘ 任意の正投影図・等角図を自動配置するロジックをここに組み込む。
Dim swModel As SldWorks.ModelDoc2
Set swModel = swDraw
‘ モデルの再計算(シートごとに行わず、必要な場合のみ実行)
‘ swModel.EditRebuild3
Set swModel = Nothing
End Sub
—
4. オブジェクトライフサイクルとメモリ解放の深淵
VBA環境下において、SolidWorks APIのCOMオブジェクト(特に `DrawingDoc`, `Sheet`, `View`)は参照カウントによって管理されている。VBAのガベージコレクションは頼りにならず、明示的に参照を断ち切らなければ、SolidWorksプロセス内のアンマネージドメモリ領域にゴミが蓄積していく。
4.1 COM参照リークの発生パターン
以下のようなコードは典型的なメモリリークの温床である。
‘ 悪質な例:ドットチェインによる暗黙的参照の残存
swApp.ActiveDoc.IComDrawingDoc.GetCurrentSheet.GetName
上記を実行すると、`ActiveDoc` や `GetCurrentSheet` の戻り値であるCOMオブジェクトがVBAの内部一時変数に保持され、プロシージャを抜けるまで解放されない。大規模なループ処理内でこれを行うと、`SLDWORKS.exe` のメモリ使用量が数GBに達し、動作が不安定になる。
正しい手法:
すべてのオブジェクトを変数として明示的に宣言し、使用完了後に `Set xx = Nothing` で解放する。
‘ 正しい例:スコープを明確にし、明示的に解放する
Dim swModel As SldWorks.ModelDoc2
Dim swSheet As SldWorks.Sheet
Set swModel = swApp.ActiveDoc
Set swSheet = swDraw.GetCurrentSheet()
‘ 処理実行…
Set swSheet = Nothing
Set swModel = Nothing
4.2 `ActivateSheet` コストの完全回避
SolidWorks APIにおいて、`ActivateSheet` メソッドは内部的にGUIの再描画、UIツリー(FeatureManagerデザインツリー)の再構築、コンテキストの切り替えを発生させる極めて重い処理である。
シートを追加・編集する際、可能な限り `ActivateSheet` の呼び出し頻度を最小化しなければならない。`NewSheet4` や `SetProperties2` は、対象のシートがアクティブでなくても実行可能である。全シートの構築・ビュー配置が完了した最後に、一度だけ初期表示シートに対して `ActivateSheet` を呼び出すのが最適である。
—
5. アーキテクチャの高度化と実用化
実務で信頼性の高い図面自動生成システムを構築するためには、単なるコードの最適化だけでなく、例外処理と保守性を見据えた設計が不可欠である。
5.1 例外処理とロールバック
バッチ処理中に予期せぬエラー(テンプレートファイルが存在しない、3Dモデルの参照が切れている等)が発生した場合、途中で生成された不完全な図面ドキュメントがメモリ上またはディスク上に残存するリスクがある。
これを防ぐため、エラーハンドラ内でのクリーンアップ処理(`CleanUp` ラベルへのジャンプ)において、一時ドキュメントを保存せずにクローズする(`swApp.CloseDoc`)ロールバック機構を実装することが強く推奨される。
5.2 テンプレート非依存の堅牢化
環境の移行やSolidWorksのバージョンアップに伴い、図枠テンプレート(`.slddrt`)のファイルパスが変更されるリスクは常につきまとう。コード内に絶対パスをハードコーディングせず、以下のような構造を採用するべきである。
1. システムオプションからの動的取得: `swApp.GetUserPreferenceStringValue(swUserPreferenceStringValue_e.swDefaultTemplateDrawing)` を利用してデフォルトのテンプレートパスを取得する。
2. 設定ファイル(INI/JSON)の分離: シートのサイズ、スケール、テンプレートパスを外部設定ファイルに持たせ、VBA側は単なる実行エンジンとして機能させる。
5.3 結論
SolidWorks VBAによるマルチシート図面生成の自動化は、単にAPIを順次呼び出すだけでは成功しない。
- `NewSheet4` / `SetProperties2` の正確なパラメータ制御
- `EnableGraphicsUpdate` と `CommandInProgress` による描画・イベント制御
- `Set xx = Nothing` による厳格なCOMライフサイクル管理
これらの原則を徹底することで、数百枚の図面処理にも耐えうる、真に堅牢で高速なエンタープライズ・ソリューションが完成する。
