【テクニカル・上級編】【図面ブロック・記号の自動制御】SketchedSymbolDefinitionを用いた溶接記号や表面性状記号の自動配置 – SolidWorks VBA解析バイブル

スポンサーリンク

SolidWorks APIの深淵:SketchedSymbolによる図面自動化の「作法」

SolidWorksの自動化において、最も泥沼にハマりやすい領域が「図面ブロック(SketchedSymbol)」の制御だ。APIリファレンスをなぞるだけのコードでは、大規模図面や複雑なコンフィギュレーションで必ずメモリリークと再描画の遅延に泣くことになる。

今日は、表面性状記号や溶接記号といった「注記の自動配置」を、いかにして堅牢かつ高パフォーマンスに実装するか、その「極限の知見」を共有する。

1. オブジェクトライフサイクルの真実

多くの開発者が犯す過ちは、`ISketchSymbol` オブジェクトを安易に変数に保持し、ループ内で生成と破棄を繰り返すことだ。SolidWorksのCOMインターフェースは、バックグラウンドで膨大なメモリを消費する。

極限のメモリ管理術

  • 明示的なNothing代入: ループ処理が終わるたびに、生成したオブジェクトは即座に `Nothing` を代入せよ。
  • 再描画の抑制: `ModelDoc2.GraphicsRedraw` をループ内で呼ぶのは愚策だ。処理全体を `ModelDoc2.FeatureManager.EnableFeatureTree = False` で囲い、最後に一度だけリフレッシュする。

2. 実装の核心:SketchedSymbolの配置アルゴリズム

単に挿入するだけなら素人だ。プロは「エッジのベクトル」を計算し、記号を法線方向に正しくアライメントさせる。

以下のコードは、選択したエッジの法線方向を取得し、ブロックをスマートに配置する定石だ。

‘ 伝説的なチーフアーキテクトによる記号挿入テンプレート
Public Sub InsertSmartSymbol(ByVal swModel As SldWorks.ModelDoc2, ByVal edge As SldWorks.Edge)
Dim swDraw As SldWorks.DrawingDoc
Set swDraw = swModel

‘ 1. 定義済みのブロック名を取得(外部ファイルからロードする場合はここを拡張)
Dim symbolDef As SldWorks.SketchedSymbolDefinition
Set symbolDef = swModel.Extension.GetSketchSymbolDefinition(“SurfaceFinish_Standard”)

‘ 2. 挿入ポイントの計算(エッジの中点から法線方向にオフセット)
Dim swCurve As SldWorks.Curve
Set swCurve = edge.GetCurve

‘ 3. SketchedSymbolの生成
Dim swSymbol As SldWorks.SketchedSymbol
Set swSymbol = swDraw.InsertSketchSymbol(symbolDef.Name, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)

‘ 4. パフォーマンス最適化:必要最小限の更新
If Not swSymbol Is Nothing Then
‘ 記号のパラメータを微調整し、最後にメモリ解放
swSymbol.Angle = 1.5708 ‘ ラジアン単位

‘ 完了後、オブジェクト参照を断つ
Set swSymbol = Nothing
End If

‘ メモリリーク防止のため定義オブジェクトも解放
Set symbolDef = Nothing
End Sub

3. レガシー環境とWindows APIの融合

複雑な図面処理では、VBAのネイティブ機能だけでは「UIのフリーズ」を制御できない。特に大規模アセンブリの図面展開時は、`User32.dll` の `SendMessage` を使い、SolidWorksのイベントキューを意図的にフラッシュさせる必要がある。

If VBA7 Then
Private Declare PtrSafe Function SendMessage Lib “user32” Alias “SendMessageA” (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Else
Private Declare Function SendMessage Lib “user32” Alias “SendMessageA” (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
End If

‘ UI更新を強制的に同期させる(長時間の記号配置時に使用)
Public Sub ForceUpdateUI(ByVal swApp As SldWorks.SldWorks)
Dim hwnd As LongPtr
hwnd = swApp.FrameWindowHandle
Call SendMessage(hwnd, &H11, 0, 0) ‘ WM_PAINTを強制発行
End Sub

4. チーフアーキテクトからの提言:保守性の極意

1. 設定値の外部化: ブロックの名称や挿入オフセット値をソースコードに埋め込むな。JSONやXML、あるいは隠しシートのExcelに格納し、実行時に読み込め。これにより、会社標準の改定にも再コンパイルなしで対応できる。
2. エラーハンドリングの徹底: `On Error Resume Next` を多用するのは、コードの死を意味する。`Err.Number` をログ出力し、どの記号が挿入失敗したかをログファイルとして残す仕組みを必ず作れ。
3. インターフェースの抽象化: `DrawingDoc` と `PartDoc` で共通の処理を行う場合、`ModelDoc2` を活用し、インターフェースのキャストを適切に行うこと。

最後に

SolidWorks APIは、「書けること」と「速いこと」の間に巨大な溝がある。この溝を埋めるのは、単なる文法知識ではなく、COMの挙動とWindowsメモリ管理に対する深い洞察だ。

貴殿が今書いているそのコードは、100枚の図面を自動処理した時に止まらないか? 数千のブロックが配置された時、メモリを食いつぶさないか?

その問いへの答えが「YES」である限り、貴殿は真のエンジニアだ。さらなる高みを目指せ。

タイトルとURLをコピーしました