【実務・中級編】【上級プロフェッショナル】図面内のオブジェクトに、連番(シーケンス番号)を自動付与し、カスタムプロパティとして管理する – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAの深淵:連番管理を「堅牢な資産」に変える設計術

AutoCADで「連番を振る」というタスクは、一見すると単純なループ処理に見える。しかし、実務レベルで数千・数万のオブジェクトを扱う際、その「単純さ」は脆弱性の温床となる。

多くの開発者が陥る罠は、「SelectionSetの管理放棄」と「XData/Propertyの不整合」だ。今回は、ただ動くコードではなく、プロジェクトの保守性を担保し、後から「誰が触っても壊れない」極限の設計を授ける。

1. なぜ「単純な連番」が破綻するのか

プロトタイプ段階では、`For Each`文で全オブジェクトを回すコードを書くだろう。だが、現実の図面は汚い。

  • 不意のUndo(元に戻す): ユーザーが途中で操作をキャンセルすれば、連番の整合性は崩壊する。
  • 非決定的な順序: AutoCADのDB格納順序は、作成・修正履歴に依存する。見た目通りに連番が振られない事態は、エンジニアとして許容してはならない。

解法: オブジェクトのX/Y座標によるソートを確定させ、`SelectionSet`を明示的に解放する。これがプロの流儀だ。

2. 実装の核心:連番付与ソリューション

以下のコードは、図面上の特定のブロックに対し、カスタムプロパティ(XRecord)としてユニークなIDを書き込むものだ。

プロダクションコード:`SequenceManager.bas`

Option Explicit

‘ ———————————————————
‘ 目的: 指定ブロックに連番を付与し、XRecordとして永続化する
‘ 設計指針: SelectionSetの再利用禁止、エラーハンドリングの徹底
‘ ———————————————————
Public Sub AssignSequenceToBlocks()
Dim ss As AcadSelectionSet
Dim ent As AcadEntity
Dim blockRef As AcadBlockReference
Dim i As Long
Dim seqName As String: seqName = “MY_ASSET_ID”

‘ 1. SelectionSetのクリーンアップ(重要:既存があれば必ず破棄)
On Error Resume Next
ThisDrawing.SelectionSets.Item(“BlockSelection”).Delete
On Error GoTo 0
Set ss = ThisDrawing.SelectionSets.Add(“BlockSelection”)

‘ 2. フィルタリング(ブロック名指定推奨)
Dim filterType(0) As Integer
Dim filterData(0) As Variant
filterType(0) = 0: filterData(0) = “INSERT”

ss.Select acSelectionSetAll, , , filterType, filterData

‘ 3. 座標による並び替え(簡易版:実際の現場では座標計算のソート関数を別途作成すること)
‘ ここでは簡略化のため順次処理とするが、実務では配列へ格納しソートを推奨

For i = 0 To ss.Count – 1
Set ent = ss.Item(i)
If TypeOf ent Is AcadBlockReference Then
Set blockRef = ent
‘ カスタムプロパティへの書き込み(XRecord使用)
Call WriteXRecord(blockRef, seqName, “ID-” & Format(i + 1, “0000”))
End If
Next i

‘ 4. 後処理
ss.Delete
MsgBox “連番の付与が完了しました。”, vbInformation
End Sub

‘ XRecordによる永続化(プロパティ管理の要)
Private Sub WriteXRecord(obj As AcadObject, key As String, val As String)
Dim xrec As AcadXRecord
Dim data(0) As Variant
Dim types(0) As Integer

‘ XRecordの作成・更新処理
‘ ※実運用では既存XRecordの有無を確認し、更新/作成を分岐させること
Set xrec = ThisDrawing.Dictionaries.Add(“MY_PROJECT_DATA”).AddXRecord(key)
data(0) = val: types(0) = 1
xrec.SetXRecordData types, data
End Sub

3. 「堅牢性」を極めるための3つの掟

① SelectionSetの「呪縛」を解く

VBAの`SelectionSet`はメモリを喰う。`ss.Delete`を忘れると、次回の実行時に「そんな名前は既に存在する」というエラーで沈黙する。必ず`On Error Resume Next`で既存の同名セットを削除してから生成するルーチンをテンプレート化せよ。

② カスタムプロパティの保存先

`Attribute(属性)`を使うのは避けろ。属性はユーザーがGUIで簡単に編集できてしまうため、管理データとしては脆い。`XRecord`(拡張レコード)を使用せよ。これは図面DBに深く潜り込み、不用意な変更を許さない。

③ トランザクション思考

数千のオブジェクトを処理する際、途中でクラッシュすると「連番が途中まで振られた死体」が残る。

  • 対策: 処理前に`ThisDrawing.StartUndoMark`を呼び出し、処理完了後に`EndUndoMark`を呼ぶ。これにより、万が一の際も「Undo 1回」で全ロールバックが可能になる。

4. 最後に:エンジニアとしての矜持

このコードは「動く」だけのものだ。実際の現場では、これに「CSVへのエクスポート機能」や「重複チェック機能」を付与することになるだろう。

しかし、最も重要なのは「コードの可読性と保守性」だ。
VBAは古い言語だが、正しく書けばAutoCADのエンジンを最も直接的に制御できる。小手先のテクニックで誤魔化さず、オブジェクトのライフサイクルを制御下に置く設計こそが、我々エンジニアの生存戦略である。

もし君がこのコードをベースに拡張するなら、まずは`Dictionary`オブジェクトを活用して、座標の重複チェックを実装してみろ。それが、中級者から「真のアーキテクト」へ至る階段だ。

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