【入門編】【上級プロフェッショナル向け】SQL Serverと連携した「図面チェックアウト管理」:オープン時にDBの編集ロックを更新 – AutoCAD VBA解析バイブル

スポンサーリンク

こんにちは!いつも業務自動化や図面データの扱いに奮闘している皆さん、本当にお疲れ様です。

複数人のチームでAutoCADを使っていると、一度はこんな悲劇を経験したことがありませんか?

  • 「Aさんが修正した図面を、Bさんが知らずに上書き保存してしまい、数時間分の作業が吹き飛んだ……(いわゆる先祖返り)」
  • 「Windowsの標準機能でファイルが読み取り専用になっていたけれど、誰が開いているのか分からず社内チャットで捜索願いを出した……」

こうしたファイル共有サーバー特有の競合トラブルは、設計現場の生産性を大きく奪ってしまいます。そこで今回は、AutoCAD VBAからADO(ActiveX Data Objects)を使ってSQL Serverと直接通信し、図面を開いた瞬間にDBへ編集ロック(チェックアウト)をかける仕組みを作ってみましょう。

「SQL Server連携なんて難しそう……」と思うかもしれませんが、大丈夫です。基礎から仕組みを噛み砕いて、ステップ・バイ・ステップで解説します。ここをクリアすれば、AutoCAD VBAの基本だけでなく、外部システムと連携する本格的なエンタープライズ開発への扉がバッチリ開きますよ!

—

1. 仕組みの全体像:図面チェックアウト管理とは?

まずは頭の中にイメージを作っておきましょう。今回のアーキテクチャは非常にシンプルです。

[ 設計者のPC (AutoCAD) ]
│
├─① DWGファイルをオープン!
│ └─ AutoCADイベントが発火
│
▼
[ VBAマクロ (ADO通信) ]
│
├─② SQL Serverへ問い合わせ
│ 「この図面、いま誰かロックしてる?」
│
├─③ 判定
│ ├─ [未ロック] 自分の名前・PC名でロックを書き込み → 編集許可!
│ └─ [ロック中] 「〇〇さんが編集中です」と警告 → 読み取り専用に強制変更
│
▼
[ SQL Server (管理テーブル) ]

ファイルサーバー上の「.dwl」「.dwl2」といった隠しロックファイルだけに頼るのではなく、中央のデータベース(SQL Server)に「誰が・いつ・どの図面を・どのマシンで」開いているかを明示的に記録します。これによって、社内の誰もがリアルタイムに編集状態を把握できるようになります。

—

2. 事前準備:VBAの参照設定

まずはAutoCAD VBAからデータベースを操作するために、ADO(Microsoft ActiveX Data Objects) という外部ライブラリを有効化します。

1. AutoCAD上で `VBAIDE` コマンドを実行し、VBAエディタを開きます。
2. メニューの [ツール] > [参照設定] をクリックします。
3. リストから `Microsoft ActiveX Data Objects 6.1 Library`(環境によっては 2.8 などでも可)にチェックを入れ、[OK] を押します。

[参照設定ダイアログ]
[x] Microsoft ActiveX Data Objects 6.1 Library

これで、データベースへ高速にアクセスするための `ADODB.Connection` や `ADODB.Recordset` といったオブジェクトが扱えるようになります。

—

3. SQL Server側のテーブル設計

連携先となるSQL Server側に、排他制御を記録するシンプルなテーブルを1つ用意します。DB管理者にお願いするか、開発用のローカル環境で次のクエリを実行してください。

CREATE TABLE DrawingLock (
DrawingPath NVARCHAR(400) NOT NULL PRIMARY KEY, — フルパス(ユニークキー)
LockedBy NVARCHAR(100) NOT NULL, — ロック保持者のWindowsユーザー名
MachineName NVARCHAR(100) NOT NULL, — 開いているPC名
LockedAt DATETIME NOT NULL — チェックアウト日時
);

主キー(PRIMARY KEY)を `DrawingPath` に設定しておくのがポイントです。これにより、同じ図面パスに対して二重にロックレコードが作成されるのをDBのレベルで完全に弾くことができます。

—

4. VBAによる排他制御モジュールの実装

それでは、標準モジュールを作成し、排他チェックを行う中心的なロジックを実装しましょう。

コードの中に出てくる接続文字列(`SERVER=…;` など)は、お使いの環境に合わせて書き換えてください。Windows認証を使用する構成にしているため、個別のIDやパスワードをコード内に埋め込む必要がなく安全です。

標準モジュール(Module_LockManager)

Option Explicit

‘ SQL Server接続文字列(環境に合わせて変更してください)
Private Const DB_CONN_STRING As String = _
“Provider=MSOLEDBSQL;” & _
“Server=YOUR_SERVER_NAME;” & _
“Database=DrawingManagementDB;” & _
“Integrated Security=SSPI;”

”’

”’ 図面の排他ロックを試行するメイン関数
”’

”’ 対象のAcadDocument ”’ True: ロック獲得成功(編集可), False: ロック失敗(他者が編集中など)
Public Function TryCheckOutDrawing(ByRef doc As AcadDocument) As Boolean
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String
Dim dwgPath As String
Dim userName As String
Dim pcName As String

‘ 新規作成された未保存図面はパスが空なのでスキップ
dwgPath = doc.FullName
If dwgPath = “” Then
TryCheckOutDrawing = True
Exit Function
End If

‘ ユーザー名とPC名の取得
userName = Environ(“USERNAME”)
pcName = Environ(“COMPUTERNAME”)

On Error GoTo ErrorHandler

‘ 1. DBへの接続を確立
Set conn = New ADODB.Connection
conn.Open DB_CONN_STRING

‘ 2. 現在のロック状況を問い合わせる
‘ ※SQLインジェクション対策としてパスのシングルクォーテーションをエスケープ
sql = “SELECT LockedBy, MachineName, LockedAt FROM DrawingLock WHERE DrawingPath = ‘” & Replace(dwgPath, “‘”, “””) & “‘”

Set rs = New ADODB.Recordset
rs.Open sql, conn, adOpenStatic, adLockReadOnly

‘ 3. 判定ロジック
If Not rs.EOF Then
‘ すでに誰かがロックを保持している場合
Dim currentHolder As String
Dim currentMachine As String
Dim lockTime As String

currentHolder = rs.Fields(“LockedBy”).Value
currentMachine = rs.Fields(“MachineName”).Value
lockTime = CStr(rs.Fields(“LockedAt”).Value)

If StrComp(currentHolder, userName, vbTextCompare) = 0 And _
StrComp(currentMachine, pcName, vbTextCompare) = 0 Then
‘ 自分が以前開いたままのゴーストロック等の場合は再利用を許可
MsgBox “ご自身の前回のセッションが残っていたため、編集権限を継続します。”, vbInformation, “ロック継続”
TryCheckOutDrawing = True
Else
‘ 他のユーザーが編集中!
MsgBox “【警告: 編集ロックされています】” & vbCrLf & vbCrLf & _
“ユーザー: ” & currentHolder & vbCrLf & _
“PC端末 : ” & currentMachine & vbCrLf & _
“開始日時: ” & lockTime & vbCrLf & vbCrLf & _
“この図面は現在編集できません。読み取り専用として利用してください。”, _
vbExclamation, “排他制御アラート”

TryCheckOutDrawing = False
End If
Else
‘ 4. 未ロック状態の場合:新規にチェックアウトレコードをINSERT
sql = “INSERT INTO DrawingLock (DrawingPath, LockedBy, MachineName, LockedAt) ” & _
“VALUES (‘” & Replace(dwgPath, “‘”, “””) & “‘, ” & _
“‘” & userName & “‘, ” & _
“‘” & pcName & “‘, ” & _
“GETDATE())”

conn.Execute sql
TryCheckOutDrawing = True
End If

CleanUp:
‘ 5. オブジェクトの明示的な解放(リソースリークの徹底防止)
On Error Resume Next
If Not rs Is Nothing Then
If rs.State = adStateOpen Then rs.Close
Set rs = Nothing
End If
If Not conn Is Nothing Then
If conn.State = adStateOpen Then conn.Close
Set conn = Nothing
End If
Exit Function

ErrorHandler:
MsgBox “データベース接続中にエラーが発生しました。” & vbCrLf & _
“エラー詳細: ” & Err.Description, vbCritical, “システムエラー”
TryCheckOutDrawing = False
Resume CleanUp
End Function

”’

”’ 図面クローズ時にロックを解放する関数
”’

Public Sub CheckInDrawing(ByRef doc As AcadDocument)
Dim conn As ADODB.Connection
Dim sql As String
Dim dwgPath As String

dwgPath = doc.FullName
If dwgPath = “” Then Exit Sub

On Error GoTo ErrorHandler

Set conn = New ADODB.Connection
conn.Open DB_CONN_STRING

‘ 自分の保持しているロックを解放
sql = “DELETE FROM DrawingLock WHERE DrawingPath = ‘” & Replace(dwgPath, “‘”, “””) & “‘ ” & _
“AND LockedBy = ‘” & Environ(“USERNAME”) & “‘”

conn.Execute sql

CleanUp:
On Error Resume Next
If Not conn Is Nothing Then
If conn.State = adStateOpen Then conn.Close
Set conn = Nothing
End If
Exit Sub

ErrorHandler:
‘ 解放失敗時のログ出力などを必要に応じて記述
Resume CleanUp
End Sub

—

5. AutoCADイベントとの結合(ThisDrawing)

作成したDB制御ロジックを、ユーザーが意識せずに「図面を開いた瞬間」「閉じた瞬間」に自動で走らせるために、イベントを利用します。

VBAプロジェクトの `ThisDrawing` に、以下のイベントプロシージャを記述します。

Option Explicit

‘ 図面が開かれたときに自動実行(AutoCADのバージョンにより動作が異なる場合があります)
Private Sub AcadDocument_Activate()
Static isFirstActivation As Boolean

‘ 初回アクティブ化(=オープン直後)のみチェックアウトを実行
If Not isFirstActivation Then
isFirstActivation = True

Dim isSuccess As Boolean
isSuccess = TryCheckOutDrawing(ThisDrawing)

If Not isSuccess Then
‘ 他者が編集中、あるいはエラー時は図面を「読み取り専用」として扱う
‘ ※AutoCAD VBA単体でオープン直後にRead-Only化する際、
‘ 警告を出した上で保存コマンドを無効化する運用が最も安全です。
ThisDrawing.Utility.Prompt vbCrLf & “>> [警告] 排他制御により、この図面は閲覧モードです。” & vbCrLf
Else
ThisDrawing.Utility.Prompt vbCrLf & “>> [成功] 図面のチェックアウトが完了しました。編集可能です。” & vbCrLf
End If
End If
End Sub

‘ 図面が閉じられる直前に自動実行
Private Sub AcadDocument_BeginDocClose(Cancel As Boolean)
‘ 編集セッションを解放する
CheckInDrawing ThisDrawing
End Sub

—

6. プロが現場で意識する「運用の落とし穴」と対策

ここまで実装できれば基本は完成ですが、エンタープライズな現場ではもう一歩先の考慮が求められます。よくある落とし穴を2つ紹介します。

① 「AutoCADが強制終了したとき」のゴーストロック問題

PCがフリーズしたり、タスクマネージャーからAutoCADを強制終了した場合、`BeginDocClose` イベントは走りません。その結果、DBにロックレコードが残り続けてしまい、誰も開けなくなる「ゴーストロック」が発生します。

  • プロの対策アプローチ:
  • 毎朝の特定時刻に「24時間以上経過したロックレコード」を自動クリアするSQL Server Agentジョブを組む。
  • チェックアウト処理内で、「もしロック日時が半日以上前なら警告を出した上で上書き取得を許可する」といった例外ルールを設ける。

② ADO接続の解放漏れによるメモリリーク

VBAで最も多い障害が、「エラー時に `conn.Close` を通らずにプロシージャを抜けてしまい、接続セッションがサーバー側に溜まり続ける」ケースです。

コード例にあるように、`ErrorHandler` の先に必ず `CleanUp` ラベルを用意し、正常時も異常時も確実に `Close` と `Set … = Nothing` を経由する構造を徹底しましょう。このお作法を守るだけで、マクロの安定性は格段に向上します。

—

まとめ:マクロから「業務プラットフォーム」へ

今回は、AutoCAD VBAとSQL Server(ADO)を組み合わせて、図面の先祖返りを防ぐ排他制御システムを構築しました。

1. ActiveX Data Objects (ADO) を使えば、VBAから外部DBの操作は自由自在。
2. AutoCADのドキュメントイベントと連動させることで、作業者の負担ゼロで自動実行できる。
3. リソースのクローズ処理を徹底することが、止まらない安定したシステムを作る鍵。

AutoCADの中で完結するマクロから一歩踏み出し、社内インフラやデータベースと繋がる仕組みを作れるようになると、自動化できる領域は一気に何倍にも広がります。

焦らず1行ずつコードを追っていけば、必ず自由自在に操れるようになりますよ。ここをクリアできれば、AutoCAD VBAの基本とデータ連携はバッチリです!ぜひ自信を持って現場のカイゼンに挑戦してみてくださいね。

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