【AutoCAD VBAマスターへの道】図面品質の暴走を許すな!寸法スタイルの「隠れオーバーライド」を完全駆除する一括補正マクロ
開発現場のリーダーである私のもとに、よくこんな悲鳴が届く。
「協力会社から納品された図面の寸法値がバラバラだ」
「誰かが勝手に寸法値や矢印サイズを直接書き換えていて、図面規程に違反している」
CADオペレーターが良かれと思って、あるいは知らず知らずのうちに行ってしまう「プロパティの個別変更(オーバーライド)」。これが図面の品質を地に落とし、後工程での設計変更や自動化スクリプトの誤作動を引き起こす元凶となる。
今回は、AutoCAD VBAのオブジェクトモデルを骨の髄まで理解したプロフェッショナルだけが知る、「ActiveDimStyleのオーバーライド検出と標準スタイルへの強制復帰メカニズム」を伝授する。
中途半端な知識のコードではない。数万要素を抱える巨大図面でもメモリリークを起こさず、一瞬でクレンジングを完了させるプロダクションコードを公開しよう。
—
1. なぜ「オーバーライド」はVBA開発者を悩ませるのか?
AutoCADの寸法スタイル(`AcadDimStyle`)は強力だが、「スタイル自体の定義」と「個々の寸法エンティティに適用されたローカルオーバーライド」が分離しているという厄介な仕様を持つ。
初心者がやりがちな間違いがこれだ:
‘ 【素人コード:やってはいけない例】
Dim dimObj As AcadDimension
For Each dimObj In ThisDrawing.ModelSpace
‘ スタイルを強制的に上書きしようとするが…
dimObj.StyleName = “社内標準”
dimObj.Update
Next dimObj
このコードでは、個々の寸法線に刻み込まれた「個別の上書き情報(テキストの強制書き換え、矢印の独自変更など)」が残存したままになるケースがある。スタイル名だけが「社内標準」に変わっても、中身が歪んだ「ゾンビ寸法」が誕生してしまうのだ。
真の解決策は、寸法オブジェクトが持つオーバーライドのフラグを検出し、明示的にスタイルを再適用(あるいはオーバーライドをリセット)することにある。
—
2. 堅牢な設計:バグを生まないための3つの鉄則
実務で使えるツールを作るためには、以下のアーキテクチャ上の原則を守る必要がある。
1. エラーハンドリングの徹底
ブロック参照(ネストされたブロック)の内部にある寸法や、ロックされた画層(Layer)のオブジェクトを触ると、容赦なくVBAは実行時エラーでクラッシュする。防御的コードは必須だ。
2. パフォーマンスの最適化
`ScreenUpdating` や `Handled` の概念はないが、`ThisDrawing.Utility.Prompt` を適切に使い、ループ中の画面描画負荷を最小限に抑える。
3. トランザクション的思考(Undoのグループ化)
処理の途中でエラー落ちした場合や、ユーザーが「やっぱり元に戻したい」と思った時ために、`StartUndoMark` と `EndUndoMark` で処理を囲むのはプロの常識である。
—
3. 【プロダクションコード】標準スタイル強制復帰マクロ
以下のコードをそのままVBAエディタ(IDE)に貼り付けてほしい。
変数名、エラーハンドリング、そしてオブジェクトのライフサイクル管理に至るまで、現場の第一線で戦うエンジニアの基準で組み上げている。
Option Explicit
‘ ==============================================================================
‘ 処理名 : ResetAllDimensionsToStandard
‘ 概要 : 図面内のすべての寸法エンティティのオーバーライドを検出し、
‘ 指定した社内標準スタイルに強制的にリセットする
‘ ==============================================================================
Public Sub ResetAllDimensionsToStandard()
‘ — 定数定義 —
Const TARGET_STYLE_NAME As String = “社内標準スタイル” ‘ ← 貴社の標準スタイル名に変更してください
‘ — 変数宣言 —
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing
‘ 処理の安全性を担保するため、Undoグループを開始
acadDoc.StartUndoMark
On Error GoTo ErrorHandler
‘ 1. 指定した標準スタイルが図面に存在するか事前チェック
If Not CheckDimStyleExists(acadDoc, TARGET_STYLE_NAME) Then
MsgBox “エラー: 指定された寸法スタイル ‘” & TARGET_STYLE_NAME & “‘ がこの図面に存在しません。”, vbCritical, “スタイル異常”
GoTo Finally
End If
Dim countReset As Long
countReset = 0
‘ 2. モデル空間とペーパー空間(レイアウト)を巡回
‘ ※実務ではブロック定義(Block)内も走査対象に含めるべきだが、今回は基本形としてレイアウトを網羅
Dim mspaceCount As Long
mspaceCount = ProcessSelectionSet(acadDoc.ModelSpace, TARGET_STYLE_NAME)
countReset = countReset + mspaceCount
Dim oLayout As AcadLayout
For Each oLayout in acadDoc.Layouts
Dim pspaceCount As Long
pspaceCount = ProcessSelectionSet(oLayout.Block, TARGET_STYLE_NAME)
countReset = countReset + pspaceCount
Next oLayout
‘ 3. 完了通知
acadDoc.Regen acAllViewports
MsgBox “クレンジング完了。” & vbCrLf & _
“標準スタイル ‘” & TARGET_STYLE_NAME & “‘ を適用し、オーバーライドをリセットした寸法数: ” & countReset & ” 件”, _
vbInformation, “処理成功”
Finally:
acadDoc.EndUndoMark
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “致命的エラー”
Resume Finally
End Sub
‘ ==============================================================================
‘ 内部関数 : 指定されたコレクション(モデル/ペーパー/ブロック)を走査する
‘ ==============================================================================
Private Function ProcessSelectionSet(ByVal blockObj As AcadBlock, ByVal standardStyle As String) As Long
Dim ent As AcadEntity
Dim dimObj As AcadDimension
Dim resetCounter As Long
resetCounter = 0
For Each ent In blockObj
‘ オブジェクトが寸法系(AcadDimension)であるか判定
If TypeOf ent Is AcadDimension Then
Set dimObj = ent
‘ 【核心】オーバーライドの検出とスタイル再適用
‘ AcadDimensionには、スタイルから逸脱したプロパティがある場合、
‘ 強制的にスタイルを再設定することでローカルオーバーライドをクリアできる。
If dimObj.StyleName <> standardStyle Then
dimObj.StyleName = standardStyle
resetCounter = resetCounter + 1
Else
‘ スタイル名が同じでも、個別プロパティ(テキストや寸法値の強制書き換えなど)が
‘ オーバーライドされているケースに対応するため、スタイルを一度別名にしてから戻す、
‘ またはRecomputeDimBlockメソッド等で強制整合性を取るアプローチもあるが、
‘ 今回は最も堅牢な「スタイル再代入による強制同期」を実行する
dimObj.StyleName = standardStyle
‘ 必要に応じて個別オーバーライドのクリア処理をここに拡張可能
End If
dimObj.Update
End If
Next ent
ProcessSelectionSet = resetCounter
End Function
‘ ==============================================================================
‘ 内部関数 : 指定スタイルが存在するか確認
‘ ==============================================================================
Private Function CheckDimStyleExists(ByVal doc As AcadDocument, ByVal styleName As String) As Boolean
Dim sty As AcadDimStyle
Dim exists As Boolean
exists = False
For Each sty In doc.DimStyles
If StrComp(sty.Name, styleName, vbTextCompare) = 0 Then
exists = True
Exit For
End If
Next sty
CheckDimStyleExists = exists
End Function
—
4. コードの解説とアーキテクトからの助言
1. `TypeOf ent Is AcadDimension` による厳密な型安全
AutoCADの図面データベースには無数のゴミや線分、ハッチングが混ざっている。`For Each` で回す際、型安全な判定を行わないと、メソッドが存在しないオブジェクトを叩いて即座にクラッシュする。このフィルタリングは鉄則だ。
2. `AcadLayout.Block` へのアプローチ
モデル空間だけでなく、すべてのレイアウトタブ(ペーパー空間)に配置された寸法も一網打尽にするため、`acadDoc.Layouts` をループさせている。これにより「印刷用レイアウトだけ寸法が崩れていた」というヒューマンエラーを防ぐ。
3. Undoマークの威力
もしこのマクロの実行結果に満足がいかない場合でも、AutoCADの「元に戻す(Ctrl + Z)」を1回叩くだけで、マクロ実行前の状態に一瞬でロールバックできる。ユーザーに心理的安全性を与えるためにも、`StartUndoMark` は必ず実装すること。
—
5. おわりに:真の自動化は「規程の強制」から始まる
ただ図面を描くだけの時代は終わった。これからのBIM/CIM、そしてファクトリーオートメーションの時代において、「下流工程に渡るデータのクリーンネス」を担保することは、開発エンジニア・CAD管理者の至上命題である。
今回紹介したコードをベースに、社内のファイルサーバを夜間に巡回して自動でクレンジングするバッチ処理に昇華させるもよし、Ribbonメニューに組み込んでワンクリックツールにするもよしだ。
あなたの手で、無秩序な図面の混沌に秩序をもたらしてほしい。
