【SolidWorks VBA】図面のノイズを制御せよ:中心マーク一括削除による「プロフェッショナルな図面」の自動生成術
設計現場において、モデル(3D)と図面(2D)の整合性を保つことは至上命題である。しかし、モデル側のフィーチャー(穴や円筒形状)に紐付いて、図面ビューへ「過剰に自動生成される中心マーク」に悩まされたことはないだろうか?
これらは、図面を不必要に煩雑にし、視認性を低下させる。さらには、図面ファイル自体のデータ容量を肥大化させ、表示パフォーマンスを阻害する「ノイズ」である。
本記事では、単に「中心マークを消す」という初歩的な作業を超え、実務に耐えうる堅牢な設計思想に基づいた、図面クレンジング・マクロの構築術を伝授する。
1. アーキテクトの視点:なぜ「単純なループ」では失敗するのか
初心者が陥る最大の罠は、コレクション(集合体)を走査しながら、その要素を削除しようとすることだ。
致命的な設計ミス:前方走査(Forward Loop)
例えば、図面内のアノテーション(注記)を `0` から `Count – 1` までループで回し、条件に合致したものを `Delete` していくコードを書いたとしよう。
' 【アンチパターン:絶対に真似してはいけない】
For i = 0 To annotationCount - 1
Set swAnn = swView.GetAnnotation(i)
If swAnn.GetType = swAnnotationType_e.swAnnotationType_CenterMark Then
swAnn.Delete ' ここで要素が消えると、インデックスが詰まり、次の要素がスキップされる
End If
Next i
要素を削除した瞬間、コレクションのインデックスは再構成される。つまり、削除した直後の要素は、次のループでスキップされてしまうのだ。これは、大規模な図面を処理する際、消し残しが発生する原因となる。
正解:後方走査(Backward Loop)
プロフェッショナルのコードは、常に「末尾から先頭へ」向かって走査する。これならば、要素を削除しても、未処理の要素のインデックスには影響を与えない。
2. 実装戦略:オブジェクト階層の完全掌握
図面操作のAPIリファレンスを読み解くと、以下の階層構造を辿ることがわかる。
1. `DrawingDoc`: 図面ドキュメント全体
2. `Sheet`: 各シート
3. `View`: 各ビュー(投影図、詳細図など)
4. `Annotation`: ビュー内に存在する注記(中心マーク、寸法、注記など)
我々の任務は、`View` の中にある `Annotation` を特定し、その `Type` が `swAnnotationType_CenterMark` であるものを見つけ出し、抹消することだ。
3. プロダクション・コード:堅牢な中心マーク・クリーナー
以下に、そのまま実務へ投入可能なレベルのコードを示す。エラーハンドリング、後方走査、そしてオブジェクトの解放を考慮した設計となっている。
Option Explicit
'' <summary>
''' 図面内の全てのシート、全てのビューを走査し、
''' 自動生成された中心マークを一括削除する。
''' </summary>
Public Sub CleanAllCenterMarks()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swSheet As SldWorks.Sheet
Dim vSheetNames As Variant
Dim i As Integer, j As Integer, k As Integer
Dim swView As SldWorks.View
Dim swAnn As SldWorks.Annotation
Dim annCount As Long
' エラーハンドリングの開始
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
' 画面更新を停止してパフォーマンスを向上させる(APIの制約により限定的だが習慣として)
' ※SolidWorks VBAでは完全に止めることは難しいが、処理の重い操作の前には意識すべき
' 2. 全てのシート名をループ
vSheetNames = swDraw.GetSheetNames
For i = 0 To UBound(vSheetNames)
' シートの切り替え
swDraw.ActivateSheet vSheetNames(i)
Set swSheet = swDraw.GetCurrentSheet
' 3. ビューの走査(シート内の全ビュー)
' GetFirstViewはシート自体を指すため、次のViewからが実際の投影図となる
Set swView = swDraw.GetFirstView
While Not swView Is Nothing
' ビュー内のアノテーション数を取得
annCount = swView.GetAnnotationCount
' 4. 【重要】後方走査によるアノテーションの削除
' インデックスが詰まるのを防ぐため、末尾から 0 に向かってループする
For k = annCount - 1 To 0 Step -1
Set swAnn = swView.GetAnnotation(k)
' アノテーションの型を確認
If Not swAnn Is Nothing Then
If swAnn.GetType = swAnnotationType_e.swAnnotationType_CenterMark Then
' 中心マークを削除
swAnn.Delete
End If
End If
Next k
' 次のビューへ
Set swView = swView.GetNextView
Wend
Next i
' 5. 変更を反映
swModel.ForceRebuild3 True
MsgBox "図面クリーニングが完了しました。", vbInformation
Exit Sub
ErrorHandler:
MsgBox "予期せぬエラーが発生しました。" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Description: " & Err.Description, vbCritical
End Sub
4. 設計の深掘り:実務で差がつく3つのポイント
① `GetFirstView` の罠
`swDraw.GetFirstView` は、実は「シートそのもの」を指す特殊なビューを返す。実際の投影図(Front View等)は、その `GetNextView` から始まる。この階層構造を理解していないと、最初のビューをスキップしてしまうミスを犯す。
② パフォーマンスの最適化
大規模なアセンブリ図面では、ビューの数が数百に及ぶこともある。
このマクロでは `swModel.ForceRebuild3 True` を最後に一度だけ実行している。ループ内で毎回 `ForceRebuild` を呼び出すのは、エンジニアとして「敗北」を意味する。再構築は、全てのデータ操作が完了した後の「最後の一撃」であるべきだ。
③ 削除(Delete)か、非表示(Hide)か
本コードでは `Delete` を採用している。これは「図面をクリーンにする」という目的に対して最も効果的だ。しかし、もし「後で元に戻せる可能性を残したい」という要件があるならば、`swAnn.IsVisible = False` に書き換えるべきだ。
「破壊的変更を行うコードには、常にその意図を明確にする」。これが、保守性の高いツールを作る上での鉄則である。
まとめ
自動化エンジニアの仕事は、単に「動くもの」を作ることではない。
「例外に強く、データ構造を理解し、計算量を最小限に抑えた、信頼されるツール」を作ることだ。
今回学んだ「後方走査」と「オブジェクト階層の正しい走査」は、SolidWorks VBAに限らず、あらゆるコレクション操作の基本である。この知見を胸に、次の開発に挑んでほしい。
