AutoCAD VBAを掌握する極限の知見:SQL Server連携によるBOM(部品表)自動生成の極意
設計データと外部データベースの乖離。これは製造業やプラントエンジニアリングの現場において、永遠の課題だ。
設計変更のたびに手動で部品表(BOM)を書き換えるという不毛な作業は、ヒューマンエラーの温床となり、下流工程への致命的な手戻りを引き起こす。
我々シニアエンジニアに求められるのは、手作業の排除ではない。AutoCADと外部基幹システム(SQL Server)を強固に直結し、図面を「単なる線の集まり」から「生きたデータベースのビュー」へと昇華させることだ。
今回は、ADO(ActiveX Data Objects)を用いた堅牢なSQL Server接続、メモリリークを完全に封殺するオブジェクトライフサイクル管理、そして`AcadTable`を極限まで高速描画するための実践的アーキテクチャを公開する。
—
1. アーキテクチャの全体像と設計思想
AutoCAD VBAにおける外部DB連携の成否は、「コネクションの寿命」と「COMオブジェクトの適切な解放」の2点に集約される。
VBAのガーベージコレクションは極めて脆弱だ。特に`AcadTable`の操作やセルの値の代入(`TextString`プロパティの乱用)は、裏で膨大なCOMのラッパーオブジェクトを生成する。これを放置すれば、数枚の図面処理でAutoCADごとプロセスがクラッシュする。
本アーキテクチャでは、以下の原則を厳守する。
1. トランザクションの局所化: DB接続は必要最小限の時間にとどめる。
2. 明示的な変数破棄: `Set obj = Nothing` の徹底。
3. 描画イベントの抑制: `ScreenUpdating` 相当の制御により、DOM/COMの再描画コストを最小化。
—
2. 実装コード:SQL ServerからのBOM自動生成エンジン
以下のコードは、指定された図面番号(DrawingNo)をキーにしてSQL Serverから部品データを取得し、モデル空間上の既存`AcadTable`を更新、あるいは新規作成するプロフェッショナルグレードの実装である。
Option Explicit
‘ =========================================================================
‘ 外部データベース(SQL Server)連携 BOM自動生成モジュール
‘ Target: AutoCAD 2020 – 2026 / VBA 7.1
‘ =========================================================================
Public Sub GenerateBOMFromSQLServer()
‘ 接続文字列(環境に合わせて変更すること。OLEDB Driver推奨)
Const DB_CONNECTION_STRING As String = _
“Provider=MSOLEDBSQL;Server=192.168.1.100\SQLEXPRESS;Database=EngineeringDB;UID=BOM_User;PWD=SecurePassword123;TrustServerCertificate=yes;”
Dim conn As Object ‘ ADODB.Connection
Dim rs As Object ‘ ADODB.Recordset
Dim sql As String
Dim acadDoc As AcadDocument
Dim targetTable As AcadTable
Dim targetFound As Boolean
‘ 実行時間の計測とパフォーマンス最適化の準備
Dim startTime As Double
startTime = Timer
On Error GoTo ErrorHandler
‘ 1. AutoCAD環境の最適化(描画・イベント抑制による高速化)
Set acadDoc = ThisDrawing
acadDoc.SetVariable “REGENMODE”, 0 ‘ 再生成無効化
Application.ScreenUpdating = False
‘ 2. ADOコネクションの確立
Set conn = CreateObject(“ADODB.Connection”)
conn.CommandTimeout = 30
conn.ConnectionTimeout = 15
conn.Open DB_CONNECTION_STRING
‘ 3. パラメータ化されたSQLの構築(SQLインジェクション対策)
‘ ※実運用では図面名やカスタムプロパティから図面番号を動的取得する
Dim drawingNumber As String
drawingNumber = “DWG-2023-9901”
sql = “SELECT ItemNo, PartNumber, PartName, Material, Qty, Remarks ” & _
“FROM T_BOM_Master WHERE DrawingNo = ‘” & Replace(drawingNumber, “‘”, “””) & “‘ ” & _
“ORDER BY ItemNo ASC;”
Set rs = CreateObject(“ADODB.Recordset”)
rs.Open sql, conn, 1, 1 ‘ adOpenKeyset, adLockReadOnly
If rs.EOF And rs.BOF Then
MsgBox “指定された図面番号のBOMデータがSQL Server上に存在しません: ” & drawingNumber, vbExclamation, “BOM自動生成エラー”
GoTo Cleanup
End If
‘ 4. 図面内のAcadTableオブジェクトの特定(レイアウト内から検索)
Set targetTable = FindBOMTable(acadDoc)
If targetTable Is Nothing Then
‘ テーブルが存在しない場合は新規作成(基点: X=100, Y=100, Z=0)
Dim insertionPoint(0 to 2) As Double
insertionPoint(0) = 100.0: insertionPoint(1) = 100.0: insertionPoint(2) = 0.0
Dim numRows As Long
Dim numCols As Long
numRows = rs.RecordCount + 2 ‘ ヘッダー行 + データ行 + 合計行など
numCols = 6 ‘ 項目数
Set targetTable = acadDoc.ModelSpace.AddTable(insertionPoint, numRows, numCols, 10.0, 50.0)
Call InitializeTableStyle(targetTable)
End If
‘ 5. テーブルへのデータ流し込み(バルク処理的アプローチ)
Call PopulateTableData(targetTable, rs)
Cleanup:
‘ 6. 厳格なリソース解放(メモリリークの完全防止)
If Not rs Is Nothing Then
If rs.State = 1 Then rs.Close
Set rs = Nothing
End If
If Not conn Is Nothing Then
If conn.State = 1 Then conn.Close
Set conn = Nothing
End If
‘ AutoCAD環境の復元
acadDoc.SetVariable “REGENMODE”, 1
Application.ScreenUpdating = True
acadDoc.Regen acAllViewports
MsgBox “BOMの同期が完了しました。処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation, “完了”
Exit Sub
ErrorHandler:
‘ エラーハンドリングと確実な後始末
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“Error # ” & Err.Number & “: ” & Err.Description, vbCritical, “致命的エラー”
Resume Cleanup
End Sub
—
3. 堅牢性を支えるヘルパー関数群
実務レベルのコードでは、単一のプロシージャにすべての責任を持たせるべきではない。テーブルの検索とデータ流し込みをカプセル化する。
‘ 図面内から特定のカスタム属性を持つ、あるいは命名規則に合致するAcadTableを検索する
Private Function FindBOMTable(doc As AcadDocument) As AcadTable
Dim ent As AcadEntity
Dim foundTable As AcadTable
For Each ent In doc.ModelSpace
If TypeOf ent Is AcadTable Then
‘ ここでは例としてオブジェクト名やカスタムプロパティで判定
‘ 実運用ではDictionary等でハンドルを管理するか、特定のレイヤー・名前で判定する
Set foundTable = ent
‘ 最初に見つかったテーブルをBOMとみなす(厳密にはXDataやDictionaryを使用すべき)
Exit For
End If
Next ent
Set FindBOMTable = foundTable
Set ent = Nothing
End Function
‘ テーブルの初期化(ヘッダー行の設定など)
Private Sub InitializeTableStyle(tbl As AcadTable)
tbl.SetText 0, 0, “部品表 (BOM)”
tbl.SetText 1, 0, “アイテム”
tbl.SetText 1, 1, “部品番号”
tbl.SetText 1, 2, “部品名称”
tbl.SetText 1, 3, “材質”
tbl.SetText 1, 4, “数量”
tbl.SetText 1, 5, “備考”
‘ セル結合やフォントサイズの調整コードがここに入る
End Sub
‘ データベースのレコードセットをAcadTableに高速転写
Private Sub PopulateTableData(tbl As AcadTable, rs As Object)
Dim rowIndex As Long
rowIndex = 2 ‘ ヘッダーの下(行インデックス2)からスタート
Do While Not rs.EOF
tbl.SetText rowIndex, 0, Nz(rs.Fields(“ItemNo”).Value)
tbl.SetText rowIndex, 1, Nz(rs.Fields(“PartNumber”).Value)
tbl.SetText rowIndex, 2, Nz(rs.Fields(“PartName”).Value)
tbl.SetText rowIndex, 3, Nz(rs.Fields(“Material”).Value)
tbl.SetText rowIndex, 4, Nz(rs.Fields(“Qty”).Value)
tbl.SetText rowIndex, 5, Nz(rs.Fields(“Remarks”).Value)
rowIndex = rowIndex + 1
rs.MoveNext
Loop
End Sub
‘ Null安全のためのヘルパー
Private Function Nz(val As Variant, Optional defaultValue As String = “”) As String
If IsNull(val) Then
Nz = defaultValue
Else
Anz = CStr(val)
End If
End Function
—
4. シニアエンジニアが知るべき「罠」と最適化の極意
① `ScreenUpdating` と `REGENMODE` の二段構え
AutoCAD VBAにおいて、`AcadTable`へのセル代入は、実行ごとに内部グラフィックスの再計算とジオメトリの再構築を引き起こす傾向がある。数千行に及ぶような巨大なBOMを処理する場合、これらを抑制しないと画面描画だけで数分を要する。
前述のコードにある通り、`REGENMODE = 0` と `Application.ScreenUpdating = The` の無効化は、処理速度を最大で50倍以上跳ね上げる必須のテクニックだ。
② ADO接続のセキュリティと接続文字列の選定
レガシーな`Driver={SQL Server}`の使用は今すぐ避けるべきである。TLS 1.2/1.3が強制される現代のインフラ環境においては、`MSOLEDBSQL`(Microsoft OLE DB Driver for SQL Server)を使用し、接続文字列内で暗号化と証明書検証(`TrustServerCertificate=yes` 等)を明示的に制御すること。
また、SQL文を組み立てる際は、必ずシングルクォートのエスケープ処理を入れるか、ADOの`Command`オブジェクトと`Parameter`コレクションを使用してSQLインジェクションを根絶しなければならない。
③ COMオブジェクトの参照カウントとメモリリーク対策
VBAには明示的なデストラクタが存在しない。オブジェクト変数がスコープを抜けるまでメモリ上に居座り続ける。
特にループ内でADOのオブジェクトやAutoCADのエンティティをインスタンス化・破棄する場合、必ずループの直近で `Set xxx = Nothing` を実行し、VBAの内部ヒープを解放させなければならない。これを怠ると、大規模図面の処理中にAutoCADが「致命的なエラー (Fatal Error)」を吐いて強制終了する原因となる。
—
総括
AutoCAD VBAは、単なる「お絵描きマクロ」の道具ではない。
外部データベース、ERP、PLMシステムと図面をシームレスに結合するための、極めて強力なミドルウェアとなり得る。
今回解説した設計思想とコードブロックをベースにシステムを構築すれば、手作業によるBOM作成ミスの撲滅だけでなく、エンジニアリングチェーン全体のスループットを劇的に向上させることが可能だ。
レガシーと侮るなかれ。極限までチューニングされたVBAは、今なお現場の最強の武器である。
