マクロの先へ:SQL Serverと連携する「図面管理ゲートキーパー」の実装術
こんにちは。現場の自動化を支えるエンジニアの皆さん。
日々、AutoCADの作業を効率化するためにVBAと格闘していることと思います。「マクロの記録」から一歩踏み出し、コードを書き始めた皆さんは、すでに素晴らしいエンジニアへの第一歩を踏み出しています。
しかし、業務が大規模になり、設計チームが10人、20人と増えてくると、単なる「便利なツール」だけでは解決できない「設計データの整合性」という巨大な壁にぶつかることがあります。
「誰かが開いている図面を、別の誰かが上書きしてしまった……」
「最新版がどれなのか、ファイル名を見るだけでは判断できない……」
こうした悲劇を防ぐための究極の解決策が、今回解説する「データベース(SQL Server)を用いたチェックイン・チェックアウト制御」です。これは、単なるAutoCADの操作を自動化するのではなく、「図面という資産のライフサイクルを管理する」という、アーキテクトの視点に立った設計思想です。
少し難しく感じるかもしれませんが、大丈夫。一歩ずつ、本質を噛み砕いて進めていきましょう。
1. コンセプト:図面を開く前に「許可」を得る
一般的な図面の開き方は、AutoCADの `Documents.Open` メソッドを叩くだけです。しかし、プロフェッショナルな管理システムでは、その前に「門番(ゲートキーパー)」を置きます。
制御の流れ(ワークフロー)
1. 【チェックアウト】
- ユーザーが「図面を開く」ボタンを押す。
- VBAがSQL Serverへ「この図面は今、誰かが使っていますか?」と問い合わせる。
- 使用中なら: 「〇〇さんが編集中です」と警告し、読み取り専用で開く。
- 空いていたら: SQL Serverのステータスを「使用中(自分)」に書き換え、通常モードで開く。
2. 【チェックイン】
- ユーザーが「保存して終了」ボタンを押す。
- VBAが図面を保存し、同時にSQL Serverのステータスを「空き」に戻し、更新日時を書き込む。
この仕組みにより、「二人が同時に同じファイルを編集して、片方の変更が消える」という事故を物理的に不可能にします。
2. 準備するもの:データベースの設計
まずは、SQL Server側に管理用のテーブルが必要です。極めてシンプルで構いません。
テーブル名: `DrawingManagement`
| カラム名 | 型 | 説明 |
|---|---|---|
| `DrawingID` | INT (PK) | 図面の固有ID |
| `FilePath` | NVARCHAR(500) | DWGファイルのフルパス |
| `Status` | INT | 0: 空き, 1: 使用中 |
| `LockedBy` | NVARCHAR(100) | 現在ロックしているユーザー名 |
| `LastUpdate` | DATETIME | 最終更新日時 |
3. 実装コード:魂を込めたプロフェッショナル・コード
ここでは、AutoCAD VBAから `ADODB` (ActiveX Data Objects) を使用してSQL Serverを操作するコード例を示します。
> 重要: VBAエディタの [ツール] -> [参照設定] から 「Microsoft ActiveX Data Objects x.x Library」 にチェックを入れておいてください。これがないとデータベース通信はできません。
モジュール1:データベース操作(DBModule)
データベースとの通信を専門に行う「部品」を作ります。役割を分けることで、コードの保守性が劇的に上がります。
Option Explicit
' SQL Serverへの接続文字列(環境に合わせて書き換えてください)
Private Const CONN_STR As String = "Provider=SQLOLEDB;Data Source=YOUR_SERVER_NAME;Initial Catalog=YOUR_DB_NAME;Integrated Security=SSPI;"
''' <summary>
''' 図面のステータスを確認する関数
''' </summary>
''' <returns>0: 空き, 1: 使用中, -1: エラー</returns>
Public Function GetDrawingStatus(ByVal filePath As String, ByRef currentLockUser As String) As Integer
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String
On Error GoTo ErrHandler
Set conn = New ADODB.Connection
conn.Open CONN_STR
' ファイルパスを条件にステータスを取得
sql = "SELECT Status, LockedBy FROM DrawingManagement WHERE FilePath = '" & Replace(filePath, "'", "''") & "'"
Set rs = New ADODB.Recordset
rs.Open sql, conn, adOpenStatic, adLockReadOnly
If Not rs.EOF Then
GetDrawingStatus = rs!Status
currentLockUser = Nz(rs!LockedBy, "")
Else
' テーブルに登録がない場合は、新規登録対象として扱う等の処理が必要
GetDrawingStatus = -1
End If
rs.Close
conn.Close
Exit Function
ErrHandler:
MsgBox "DB接続エラー: " & Err.Description, vbCritical
GetDrawingStatus = -1
End Function
''' <summary>
''' 図面のステータスを更新する関数(チェックイン・チェックアウト用)
''' </summary>
Public Sub UpdateDrawingStatus(ByVal filePath As String, ByVal status As Integer, ByVal userName As String)
Dim conn As ADODB.Connection
Dim sql As String
On Error GoTo ErrHandler
Set conn = New ADODB.Connection
conn.Open CONN_STR
' ステータスとロックユーザー、更新日時を同時に更新
sql = "UPDATE DrawingManagement SET Status = " & status & _
", LockedBy = '" & Replace(userName, "'", "''") & "'" & _
", LastUpdate = GETDATE() " & _
"WHERE FilePath = '" & Replace(filePath, "'", "''") & "'"
conn.Execute sql
conn.Close
Exit Sub
ErrHandler:
MsgBox "DB更新エラー: " & Err.Description, vbCritical
End Sub
' Null値を安全に扱うための補助関数
Private Function Nz(val As Variant, valueIfNull As String) As String
If IsNull(val) Then Nz = valueIfNull Else Nz = CStr(val)
End Function
モジュール2:AutoCAD制御(MainModule)
ユーザーが実際に触れるメインロジックです。
Option Explicit
''' <summary>
''' スマート・オープン処理
''' </summary>
Public Sub SmartOpenDWG()
Dim targetPath As String
Dim userName As String
Dim dbStatus As Integer
Dim lockUser As String
Dim acadDoc As AcadDocument
' 1. ユーザー情報の取得(Windowsログイン名)
userName = Environ("USERNAME")
' 2. ファイル選択ダイアログ(本来はここでパスを取得)
targetPath = "C:\Projects\Design_A.dwg" ' サンプルパス
' 3. DBにステータスを確認
dbStatus = GetDrawingStatus(targetPath, lockUser)
If dbStatus = -1 Then
MsgBox "データベースとの通信に失敗しました。", vbCritical
Exit Sub
End If
If dbStatus = 1 Then
' --- 【他者が使用中の場合】 ---
If LCase(lockUser) <> LCase(userName) Then
Dim ans As VbMsgBoxResult
ans = MsgBox("現在、" & lockUser & " さんが編集中です。" & vbCrLf & _
"読み取り専用で開きますか?", vbQuestion + vbYesNo)
If ans = vbYes Then
' 読み取り専用で開く(Openメソッドの引数を利用)
Set acadDoc = Documents.Open(targetPath, True) ' True = ReadOnly
MsgBox "読み取り専用で開きました。保存はできません。", vbInformation
End If
Exit Sub
End If
End If
' --- 【自分が使用可能な場合】 ---
' DBを「使用中」に更新
UpdateDrawingStatus targetPath, 1, userName
' 通常モードで開く
Set acadDoc = Documents.Open(targetPath, False)
MsgBox "チェックアウトに成功しました。作業を開始してください。", vbInformation
End Sub
''' <summary>
''' スマート・チェックイン処理(保存して閉じる)
''' </summary>
Public Sub SmartCheckIn()
Dim targetPath As String
Dim userName As String
Dim acadDoc As AcadDocument
On Error Resume Next
Set acadDoc = ThisDrawing
On Error GoTo 0
If acadDoc Is Nothing Then Exit Sub
targetPath = acadDoc.FullName
userName = Environ("USERNAME")
' 1. 図面を保存
acadDoc.Save
' 2. DBのステータスを「空き(0)」に戻す
UpdateDrawingStatus targetPath, 0, ""
' 3. 図面を閉じる
acadDoc.Close
MsgBox "チェックインが完了しました。お疲れ様でした!", vbInformation
End Sub
4. アーキテクトからの助言:陥りやすい「落とし穴」
ここまで読んで「よし、これで完璧だ!」と思ったあなた。少しだけ立ち止まってください。実戦では、コードが正しくても「運用」で死ぬことがあります。
① 「ゾンビ・ロック」問題
これが最大の課題です。「作業中にPCがフリーズした」「AutoCADがクラッシュした」「ユーザーが強制終了した」場合、DBのステータスは「使用中」のまま残ってしまいます。
- 対策: 管理者権限で「強制ロック解除」ができるツールを別途用意するか、DBに「最終生存確認時間(Heartbeat)」を持たせ、一定時間更新がないロックを自動解除するロジックを検討してください。
② ネットワーク遅延とトランザクション
DBへの書き込みは、ネットワークの状態に左右されます。
- 対策: `UpdateDrawingStatus` が成功したことを確認してから `Documents.Open` を行う、という「順序の厳守」を徹底してください。DB更新に失敗したのに図面だけ開いてしまうと、整合性が崩れます。
③ エラーハンドリングの徹底
VBAにおいて、エラーを無視することは「爆弾を抱えて歩くこと」と同じです。
- 対策: `On Error GoTo` を使い、エラーが発生した場合には必ず「ユーザーに状況を伝え、中途半端な状態(DBだけ更新された状態など)を防ぐ」設計にしてください。
最後に
「単に図面を開く」動作を、「データベースと同期して管理する」動作へと昇華させる。この考え方こそが、プログラミングを「作業の自動化」から「業務のシステム化」へと進化させる鍵です。
最初はエラーに泣かされることもあるでしょう。しかし、そのエラーを一つずつ潰していく過程こそが、あなたを真のエンジニアへと成長させます。
ここをクリアすれば、AutoCAD VBAの基本、そして一歩先のシステム設計の基礎はバッチリですよ。応援しています!
