こんにちは!AutoCAD VBAの世界へようこそ。
マクロの記録ボタンを押すだけの自動化から一歩抜け出し、「自分の手でCADを自在に操りたい」と願うあなたにとって、今日は記念すべき日になるはずです。
現場で図面を扱っていると、こんな面倒な作業に直面したことはありませんか?
「配置された数百個の機器(空調、照明、家具など)に、図面上の左上から右下へ向かって、1つずつ『EQ-001』『EQ-002』……と連番を振っていく作業」
これを人の手でやると、途中で番号が飛んだり、同じ番号を二度振ってしまったりするヒューマンエラーの温床になります。しかも、途中に機器を追加しようものなら、地獄のような修正作業が待っていますよね。
今回は、この「図面内のオブジェクトに、綺麗な順序で連番を自動付与するプロフェッショナルなVBAプログラム」を一緒に作っていきましょう。
ここをクリアすれば、AutoCAD VBAのオブジェクトモデルの核心と、実務で使えるアルゴリズムの組み方が一気にバッチリ理解できるようになりますよ。それでは、熱いエンジニアの魂を込めて解説していきます!
—
1. なぜ「連番付与」はAutoCAD VBAの登竜門なのか?
ただ図面の中にあるオブジェクトを全スキャンして番号を振るだけなら、実はそこまで難しくありません。しかし、「特定の順序(例えば、左から右、上から下という人間の視線の動き)に合わせて並べ替え、属性や文字を書き換える」となると話は別です。
ここには、AutoCAD VBAを使いこなす上で避けて通れない以下の重要な要素がすべて詰まっています。
- オブジェクトのコレクション(`ModelSpace`)の走査
- 各図形が持つ座標データ(`InsertionPoint`など)の取得と判定
- VBA標準機能を使ったデータの並べ替え(ソート)アルゴリズム
- 文字オブジェクト(`AcDbText` / `AcDbMText`)やブロック属性の書き換え
これらを一つずつ、優しく紐解いていきましょう。
—
2. 開発の全体像とアプローチ
今回のプログラムでは、以下のステップで処理を行います。
1. ターゲットの選定: 図面から「連番を付与したい対象(今回は特定の文字列やブロック)」を抽出する。
2. 座標の取得とソート(ここがキモ!): 図面上の配置順(X座標が小さい順、同じならY座標が大きい順など)に、抽出したオブジェクトを並び替える。
3. 連番の書き込み: 並び順に従って、`”EQ-001″`, `”EQ-002″` と名前(またはテキスト)を書き換えていく。
まずは、実務でそのままコピペして動かせる完成版のコードをお見せします。そのあとで、中身をじっくり解説しますね。
—
3. 実用コード:自動連番付与マクロ
以下のコードを、AutoCADのVBAエディタ(`Alt + F11` で起動)の標準モジュールに貼り付けてください。
Option Explicit
‘ ==============================================================================
‘ 担当:先輩エンジニア
‘ 概要:モデル空間内の特定の文字列を持つテキストオブジェクトを検出し、
‘ 画面上の「上から下、左から右」の自然な順序でソートして連番を付与する
‘ ==============================================================================
Sub AutoAssignSequenceNumber()
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.Application.ActiveDocument
‘ 1. ユーザーへの事前確認
Dim confirmMsg As String
confirmMsg = “図面内のテキストに連番(EQ-001〜)を自動付与します。” & vbCrLf & _
“処理を実行してもよろしいですか?”
If MsgBox(confirmMsg, vbYesNo + vbQuestion, “自動連番付与ツール”) = vbNo Then Exit Sub
‘ 2. 処理対象データの収集(座標とオブジェクトを格納する配列を用意)
Dim ent As AcadEntity
Dim textObj As AcadText
Dim dataList() As Variant
Dim count As Long
count = 0
‘ モデル空間を走査
For Each ent In acadDoc.ModelSpace
‘ 文字オブジェクト(AcadText)かつ、プレフィックスが「EQ-TEMP」等のものを対象とする
If TypeOf ent Is AcadText Then
Set textObj = ent
‘ 仮の文字列から始まるものをターゲットとする(実務ではレイヤや画層で絞り込むのもアリ)
If Left$(textObj.TextString, 7) = “EQ-TEMP” Then
ReDim Preserve dataList(3, count)
dataList(0, count) = textObj.Handle ‘ オブジェクトの識別子(Handle)
dataList(1, count) = textObj.InsertionPoint(0) ‘ X座標
dataList(2, count) = textObj.InsertionPoint(1) ‘ Y座標
dataList(3, count) = textObj ‘ オブジェクト本体への参照
count = count + 1
End If
End If
Next ent
If count = 0 {
MsgBox “対象となるテキスト(’EQ-TEMP’で始まるもの)が見つかりませんでした。”, vbExclamation, “終了”
Exit Sub
}
‘ 3. 座標による並べ替え(簡易バブルソート:上から下、左から右)
‘ ※実数が膨大な場合はアルゴリズムの改良が必要ですが、通常のマクロならこれで十分高速です
Dim i As Long, j As Long
Dim tempHandle As String, tempX As Double, tempY As Double, tempObj As Object
For i = 0 To count – 2
For j = i + 1 To count – 1
‘ 条件:Y座標が大きい(上にある)順。Y座標がほぼ同じなら、X座標が小さい(左にある)順
Dim needSwap As Boolean
needSwap = False
‘ AutoCADのY座標は上がプラスなので、Yが大きい方が「上」
If dataList(2, i) < dataList(2, j) Then
needSwap = True
ElseIf Abs(dataList(2, i) - dataList(2, j)) < 10# Then ' Y座標の誤差を考慮(10mm以内なら同一行とみなす)
If dataList(1, i) > dataList(1, j) Then
needSwap = True
End If
End If
If needSwap Then
‘ データの入れ替え(スワップ)
‘ Handle
tempHandle = dataList(0, i): dataList(0, i) = dataList(0, j): dataList(0, j) = tempHandle
‘ X
tempX = dataList(1, i): dataList(1, i) = dataList(1, j): dataList(1, j) = tempX
‘ Y
tempY = dataList(2, i): dataList(2, i) = dataList(2, j): dataList(2, j) = tempY
‘ Object
Set tempObj = dataList(3, i): Set dataList(3, i) = dataList(3, j): Set dataList(3, j) = tempObj
End If
Next j
Next i
‘ 4. 連番の書き込み処理
Dim seq As Long
Dim formattedNum As String
For i = 0 To count – 1
seq = i + 1
‘ 3桁のゼロ埋めフォーマット(”EQ-001″, “EQ-002” …)
formattedNum = “EQ-” & Format(seq, “000”)
Set textObj = dataList(3, i)
textObj.TextString = formattedNum
textObj.Update ‘ 画面上の描画を更新
Next i
‘ 5. 完了通知
MsgBox count & “件のオブジェクトに連番を正常に付与しました!”, vbInformation, “完了”
End Sub
—
4. コードの重要ポイントをプロの視点で解説
ここからは、なぜこのコードが実務で耐えうるのか、重要なポイントを噛み砕いて解説します。
① `ModelSpace` の全走査と `TypeOf` による型安全性の確保
AutoCADの図面空間には、線(Line)、円(Circle)、文字(Text)など、多種多様な図形が混ざっています。
If TypeOf ent Is AcadText Then
この一文によって、「文字オブジェクトだけに絞り込む」というフィルターをかけています。これを怠ると、線分オブジェクトをテキストとして扱おうとして「型が一致しません」という致命的なエラー(実行時エラー 13)を引き起こします。型チェックはプログラマの基本の「キ」ですよ。
② 厄介な「図面の座標系」をどう料理するか?
AutoCADの座標は、左下が原点(0,0)ではなく、画面の上がYプラス、右がXプラスです。
人間が図面を見る時は、「左上から右下へ」視線を動かします。そのため、今回のコードでは以下のロジックをソート部分に組み込みました。
1. Y座標が大きい(=図面の上側にある)ものを優先して処理する
2. ただし、Y座標がほぼ同じ(例えば10mm以内)であれば、X座標が小さい(=左側にある)ものを優先する
これにより、図面上のレイアウトが多少ガタついていても、人間の感覚に近い美しい順序で番号を並べ替えることができます。
③ 実務で必須の `Format` 関数によるゼロ埋め
`”EQ-” & Format(seq, “000”)` という記述に注目してください。
これによって、`1` は `”EQ-001″` に、`12` は `”EQ-012″` に変換されます。ファイル名や管理番号のソートにおいて、桁数が揃っていないと(EQ-1, EQ-10, EQ-2 のように)文字コード順で並んでしまい後々痛い目を見ます。最初から3桁ゼロ埋めにしておくのが、プロの現場の作法です。
—
5. 陥りやすい罠とデバッグのコツ
AutoCAD VBAを開発していると、必ずと言っていいほど以下の罠にハマります。先輩からのアドバイスとして頭の片隅に置いておいてください。
- 罠1: 画面が更新されない?
- 対策: オブジェクトのプロパティを変更した後は、必要に応じて `.Update` メソッドを呼び出しましょう。AutoCADのメモリ上のデータと、画面上の描画が乖離するのを防げます。
- 罠2: 大量のオブジェクトで処理がフリーズしたように重い
- 対策: 今回はシンプルなバブルソートを使っています。もし対象が数千〜数万個に及ぶ場合は、処理の最初に `AcadApplication.ActiveDocument.Utility.Prompt` でステータスバーに進捗を出したり、画面描画を一時停止する `Application.ScreenUpdating = False` 相当の工夫(AutoCADの場合はレイヤーやビューのロック)を検討してください。
—
6. おわりに
お疲れ様でした!
今回作成した「自動連番付与プログラム」は、単なるマクロの域を超え、「空間座標の概念」と「データの整列アルゴリズム」を融合させた本格的なCAD自動化プログラムです。
ここをクリアできたあなたなら、文字の置換だけでなく、ブロック属性の自動一括書き換えや、外部Excel連携によるパーツリストの自動生成など、どんな応用課題でも必ずクリアできるはずです。
「面倒な定型作業はプログラムに任せ、自分たちはクリエイティブな設計に集中する」
そんなスマートなエンジニアライフを、今日からぜひ満喫してください。
それでは、次回の実践的AutoCAD VBA講座でお会いしましょう。バッチリ自動化を進めていってくださいね!
