【テクニカル・上級編】【中級者向け】図面内に配置された不要なスケッチエンティティや構築線を一括削除するクリーンアップVBA – SolidWorks VBA解析バイブル

スポンサーリンク
スポンサーリンク

デジタル・ハイジーン:SolidWorks図面における「ゴースト・エンティティ」の殲滅とメモリ管理の極致

大規模な設計プロジェクトにおいて、CADデータの「エントロピー(無秩序さ)」は静かに、しかし確実に進行する。

モデルから図面を生成する際、あるいは外部のSTEP/IGESファイルをインポートして図面化した際、図面ファイルには「意図しないスケッチエンティティ」が残留する。これらは、目には見えない、あるいは構築線として薄く表示されるだけの「ゴースト(幽霊)」だ。一見、設計に影響を与えない無害な存在に見えるが、数千枚の図面を管理するシステム管理者や、自動化パイプラインを構築するシニアエンジニアにとって、これらは致命的な毒となる。

ファイルサイズの肥大化、再構築(Rebuild)時間の増大、そして何より、後続のAPI処理やPLM連携における予期せぬエラーの温床となるからだ。

本稿では、単なる「削除マクロ」の提供はしない。SolidWorksのCOMオブジェクトモデルの深淵に触れ、メモリリークを回避し、実行速度を極限まで高めた「図面クリーンアップ・エンジン」の設計思想を詳解する。

1. 図面構造の解剖:なぜ単純な削除では不十分なのか

図面(`DrawingDoc`)の構造は、単なる平面ではない。それは `Sheet`、`View`、そして各ビューに紐付いた `Sketch` という階層構造を持つ複雑なデータベースである。

多くの開発者が陥る罠は、`SelectionMgr` を用いて画面上のオブジェクトを操作しようとすることだ。これはUI操作の自動化としては成立するが、大量のエンティティを処理する際には、選択操作に伴うグラフィックス更新のオーバーヘッドが指数関数的に増大し、システムをフリーズさせる。

真にプロフェッショナルなアプローチは、「階層的なオブジェクトトラバーサル(走査)」である。
1. `DrawingDoc` から全 `Sheet` を列挙。
2. 各 `Sheet` 内の全 `View` を列挙。
3. 各 `View` が持つ `Sketch` コンテキストへアクセス。
4. 条件に合致する `SketchEntity` を特定し、直接削除。

このプロセスにおいて、最も重要なのは「どのエンティティが『不要』であるか」の定義を厳格にすることだ。構築線(Construction lines)や、インポートされた際に生成される孤立した点(Points)を対象とするが、ユーザーが意図的に配置した注釈用スケッチまで破壊してはならない。

2. 実装:高パフォーマンス・クリーンアップ・エンジン

以下に、メモリ最適化とエラーハンドリングを極限まで突き詰めた実装例を示す。このコードは、64bit環境を想定し、Windows APIを用いた描画停止制御を組み込んでいる。

'==============================================================================
' Module: DrawingCleanupEngine
' Description: 図面内の不要なスケッチエンティティ(構築線・孤立点)を一括削除する
' Author: Chief Architect
'==============================================================================
Option Explicit

' Windows API: 描画の更新を抑制し、処理速度を向上させるための準備
' (VBAの標準機能だけでは不十分な場合があるため、システムレベルでの制御を意識する)

If VBA7 Then

Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)

Else

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

End If

Public Sub ExecuteCleanSweep() Dim swApp As SldWorks.SldWorks Dim swModel As SldWorks.ModelDoc2 Dim swDraw As SldWorks.DrawingDoc Dim swSheet As SldWorks.Sheet Dim vSheets As Variant Dim i As Long Dim swView As SldWorks.View Dim swSketch As SldWorks.Sketch Dim vEntities As Variant Dim swEnt As SldWorks.SketchEntity Dim deleteCount As Long Dim startTime As Double On Error GoTo ErrorHandler Set swApp = Application.SldWorks Set swModel = swApp.ActiveDoc ' 1. 実行環境のバリデーション If swModel Is Nothing Then Exit Sub If swModel.GetType <> swDocDRAWING Then MsgBox "図面ファイルを開いた状態で実行してください。", vbCritical Exit Sub End If Set swDraw = swModel startTime = Timer ' 2. パフォーマンス最適化:グラフィックス更新の停止 ' これを行わないと、1要素削除するごとに画面が再描画され、処理が壊滅的に遅くなる swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisplayGraphicsUpdate, False ' 3. 処理開始 vSheets = swDraw.GetSheetNames deleteCount = 0 For i = 0 To UBound(vSheets) swDraw.ActivateSheet vSheets(i) Set swSheet = swDraw.GetCurrentSheet ' シート内の全ビューを走査 ' GetFirstView はシート自体(Sheet View)を返すため、その次の View からが実質的なビュー Set swView = swDraw.GetFirstView Do While Not swView Is Nothing ' ビューに紐付くスケッチを取得 Set swSketch = swView.GetSketch If Not swSketch Is Nothing Then ' スケッチ内のエンティティを列挙 vEntities = swSketch.GetSketchEntities If Not IsEmpty(vEntities) Then Dim j As Long ' 後ろから走査するのが鉄則(削除によるインデックスのズレを防ぐ) For j = UBound(vEntities) To LBound(vEntities) Step -1 Set swEnt = vEntities(j) ' 【判定ロジック】 ' ここでは「構築線」または「点」を削除対象とする ' 必要に応じて、特定のレイヤーや名前によるフィルタリングを追加せよ If IsUnwantedEntity(swEnt) Then swEnt.Delete deleteCount = deleteCount + 1 End If Next j End If End If ' 次のビューへ Set swView = swView.GetNextView Loop Next i ' 4. 後処理と復元 swModel.ForceRebuild3 True swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisplayGraphicsUpdate, True MsgBox "クリーンアップ完了。" & vbCrLf & _ "削除されたエンティティ数: " & deleteCount & vbCrLf & _ "実行時間: " & Format(Timer - startTime, "0.00") & " 秒", vbInformation CleanExit: ' オブジェクトの明示的解放:メモリリークを防ぐための儀式 Set swEnt = Nothing Set swSketch = Nothing Set swView = Nothing Set swSheet = Nothing Set swDraw = Nothing Set swModel = Nothing Set swApp = Nothing Exit Sub ErrorHandler: swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisplayGraphicsUpdate, True MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical Resume CleanExit End Sub '============================================================================== ' Function: IsUnwantedEntity ' Description: エンティティが削除対象(不要な構築線等)か否かを判定する '============================================================================== Private Function IsUnwantedEntity(swEnt As SldWorks.SketchEntity) As Boolean Dim swSeg As SldWorks.SketchSegment Set swSeg = swEnt.GetSegment If swSeg Is Nothing Then ' セグメントを持たないもの(点など)の判定 ' 孤立した点などを検知する場合はここを拡張する IsUnwantedEntity = True Exit Function End If ' 構築線(Construction Geometry)であるかを確認 If swSeg.ConstructionGeometry = True Then IsUnwantedEntity = True Else IsUnwantedEntity = False End If End Function

3. 極限の知見:アーキテクトの視点

このコードを実戦投入するにあたり、以下の3点を肝に銘じておくことだ。

A. オブジェクトのライフサイクル管理

VBAはガベージコレクション(GC)に頼り切る設計は推奨されない。特にループ内で大量の `SketchEntity` オブジェクトを生成する場合、`Set swEnt = Nothing` による明示的な解放、あるいはスコープの限定を徹底しなければ、SolidWorksのプロセス(`SLDWORKS.exe`)のメモリ使用量が右肩上がりに増大し、最終的にクラッシュを引き起こす。

B. 逆方向走査(Reverse Iteration)の絶対原則

配列(`vEntities`)から要素を削除する場合、インデックスは動的に変化する。前から削除すると、削除した瞬間に次の要素のインデックスが繰り上がり、スキップが発生する。これはバグの温床だ。必ず `Step -1` を用いて、末尾から先頭へと走査せよ。これはエンジニアとしての「作法」である。

C. 描画更新の制御(Graphics Update Suppression)

`swApp.SetUserPreferenceToggle` による制御は、単なる高速化技術ではない。これは、API実行中の「状態の不安定さ」を回避するための防衛策でもある。描画更新がONのまま大量の削除を行うと、SolidWorksの内部計算エンジンとAPIの命令が競合し、不整合なデータが書き込まれるリスクがある。

結言

図面のクリーンアップは、単なる「掃除」ではない。それは、設計データの整合性を担保し、システムのライフサイクルを延命させるための「エンジニアリング」である。

提供したコードは、あくまで基盤に過ぎない。現場の要件に応じて、`IsUnwantedEntity` 内の判定ロジックを研ぎ澄ませ、独自の「不要定義」を組み込むこと。それが、真に堅牢な自動化システムを構築する唯一の道である。

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