【設計思想】SQL Serverと連動した「権限制御型」図面オープンシステムの構築術
業務自動化の現場において、多くの開発者が陥る「罠」がある。それは、「AutoCADの操作」と「データの整合性」を切り離して考えてしまうことだ。
単に `Documents.Open` を実行して図面を開く。それは「スクリプト」であって「システム」ではない。真のプロフェッショナルが構築すべきは、図面ファイルそのものではなく、「図面がどのような状態にあるべきか」というビジネスルールを強制する制御レイヤーである。
本記事では、SQL Server上の図面ステータス(承認済み/編集可)と連動し、ADODBを用いて動的に読み取り専用モードを切り替える、堅牢なPLM(Product Lifecycle Management)連携システムの設計と実装について解説する。
1. なぜ「ファイル操作」ではなく「ステータス管理」なのか
設計者やエンジニアが誤ったステータスの図面を編集し、そのまま上書き保存してしまう。これは製造業における設計変更管理において致命的な事故だ。
「ファイルが書き込み可能だから開く」というロジックは、Windowsのファイルロックには対応できても、「組織としての承認プロセス」には対応できない。
理想的なアーキテクチャ
我々が目指すべきは、以下の3層構造である。
1. Data Layer (SQL Server): 図面の「真実(Single Source of Truth)」を保持する。パス、ステータス(Draft, Approved, Released)、最終更新者などを管理。
2. Logic Layer (VBA Class): DBからステータスを読み取り、AutoCADへ渡す「命令」を生成する。
3. Presentation Layer (AutoCAD): 命令に従い、`ReadOnly` フラグを制御して図面を展開する。
2. 陥りやすい設計上の落とし穴:リソースの管理
実装に入る前に、設計者が絶対に避けるべき2つの致命的なミスを伝えておく。
① ADODB接続の「開きっぱなし」
DBへの接続(Connection)は、クエリが終わるたびに即座に閉じる必要がある。VBAはメモリ管理が甘いため、接続を保持し続けると、サーバー側のコネクションプールを食いつぶし、最終的にシステム全体を停止させる。
② 例外処理の欠如による「ゾンビプロセス」
DB接続エラーやネットワーク切断が発生した際、適切にエラーハンドリングが行われていないと、AutoCADはフリーズするか、あるいは「図面は開いていないが、VBAのメモリ上には接続情報だけが残る」という中途半端な状態に陥る。
3. プロダクションクオリティのコード実装
ここでは、保守性と再利用性を極限まで高めるため、標準モジュールにコードを羅列するのではなく、クラスモジュールを用いたカプセル化を採用する。
クラスモジュール: `clsDrawingManager`
このクラスは、DBとの通信と権限判定の責務を一身に担う。
' Class Module: clsDrawingManager
Option Explicit
' 列挙型によるステータスの定義(マジックナンバーを排除)
Public Enum DrawingStatus
dsUnknown = 0
dsDraft = 1 ' 編集可能
dsApproved = 2 ' 読み取り専用
dsReleased = 3 ' 読み取り専用(ロック)
End Enum
Private pConnectionString As String
Private pFilePath As String
' 初期化メソッド
Private Sub Class_Initialize()
' 本来は設定ファイルや環境変数から取得すべき
pConnectionString = "Provider=SQLOLEDB;Data Source=YOUR_SERVER;Initial Catalog=YOUR_DB;Integrated Security=SSPI;"
End Sub
' 図面パスの設定
Public Property Let TargetFilePath(ByVal Value As String)
pFilePath = Value
End Property
' 図面のステータスを取得し、権限を判定するメインロジック
' Returns: True if ReadOnly mode is required
Public Function IsReadOnlyRequired() As Boolean
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String
Dim statusValue As Integer
IsReadOnlyRequired = False ' デフォルトはFalse
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
On Error GoTo ErrorHandler
' 1. DB接続
conn.Open pConnectionString
' 2. ステータス照会 (図面パスをキーに検索)
' ※ SQLインジェクション対策として、実務ではパラメータ化クエリを推奨
sql = "SELECT Status FROM DrawingTable WHERE FilePath = '" & Replace(pFilePath, "'", "''") & "'"
rs.Open sql, conn, adOpenForwardOnly, adLockReadOnly
If Not rs.EOF Then
statusValue = rs.Fields("Status").Value
' 3. ステータスに基づいた権限判定
Select Case statusValue
Case dsDraft
IsReadOnlyRequired = False
Case dsApproved, dsReleased
IsReadOnlyRequired = True
Case Else
' 不明なステータスの場合は安全側に倒してReadOnlyにする
IsReadOnlyRequired = True
End Select
Else
' DBに存在しない図面は、安全のためにReadOnlyで開くか、エラーを出す
Err.Raise vbObjectError + 513, "clsDrawingManager", "図面情報がDBに見つかりません。"
End If
CleanUp:
' リソースの確実な解放(重要!)
If Not rs Is Nothing Then
If rs.State = adStateOpen Then rs.Close
End If
Set rs = Nothing
If Not conn Is Nothing Then
If conn.State = adStateOpen Then conn.Close
End If
Set conn = Nothing
Exit Function
ErrorHandler:
MsgBox "【DBエラー】" & vbCrLf & Err.Description, vbCritical, "System Error"
IsReadOnlyRequired = True ' エラー時は安全のためにReadOnly
Resume CleanUp
End Function
標準モジュール: 実行制御
クラスを利用して、実際にAutoCADのドキュメントを開く処理を行う。
' Standard Module
Option Explicit
Sub OpenDrawingWithPermissionCheck()
Dim acadApp As Object ' AutoCAD.Application
Dim targetDoc As Object ' AutoCAD.Document
Dim dwgManager As clsDrawingManager
Dim targetPath As String
Dim isReadOnly As Boolean
' ターゲット図面のパス(実際にはダイアログ等から取得)
targetPath = "C:\Projects\Design_A_001.dwg"
On Error GoTo FatalError
' AutoCADオブジェクトの取得
Set acadApp = GetObject(, "AutoCAD.Application")
' 1. 管理クラスのインスタンス化と設定
Set dwgManager = New clsDrawingManager
dwgManager.TargetFilePath = targetPath
' 2. DB連携による権限チェック
Debug.Print "Checking permission for: " & targetPath
isReadOnly = dwgManager.IsReadOnlyRequired()
' 3. AutoCADでのオープン実行
' Documents.Open(Name, ReadOnly)
' ※ 第2引数のReadOnlyが、我々の設計の肝となる
Set targetDoc = acadApp.Documents.Open(targetPath, isReadOnly)
If isReadOnly Then
MsgBox "この図面は承認済みのため、「読み取り専用」で開いています。", vbInformation, "Status: Approved"
Else
MsgBox "編集権限を確認しました。通常モードで開きます。", vbInformation, "Status: Draft"
End If
Set dwgManager = Nothing
Exit Sub
FatalError:
MsgBox "図面を開けませんでした。" & vbCrLf & Err.Description, vbCritical
Set dwgManager = Nothing
End Sub
4. プロフェッショナルのための追加知見
このシステムを実戦投入するにあたり、以下の3点についても検討しておくべきだ。
A. ファイルロックの競合(Race Condition)
DB上で「編集可」となっていても、他のユーザーがWindowsレベルでファイルを開いている場合、AutoCADは「読み取り専用」として開くか、エラーを返す。DBのステータスとOSのファイルロック状態は必ずしも一致しない。`Documents.Open` の戻り値や、エラーハンドリングをさらに精緻化する必要がある。
B. SQLインジェクションへの配慮
上記のサンプルコードでは、簡略化のために文字列結合でSQLを生成している。しかし、ファイルパスに `’`(シングルクォート)が含まれる場合や、悪意のある入力があった場合に備え、実務では `ADODB.Command` オブジェクトを使用したパラメータ化クエリを徹底すること。
C. バージョン互換性の考慮
もし、DBに「図面バージョン」の概念があるなら、`Documents.Open` の前に、ファイル自体のバージョン(DWG形式)をチェックするロジックを組み込むべきだ。古いバージョンのAutoCADで新しい形式を開こうとしてクラッシュする、といった事態を防ぐためである。
結びに代えて
自動化エンジニアの価値は、「コードが動くこと」ではなく、「運用が破綻しない仕組みを作ること」にある。
単なるファイル操作を、データベースという「規律」に基づいたシステムへと昇華させる。この設計思想こそが、現場のエンジニアから信頼されるアーキテクトへの第一歩である。
