【入門編】【上級者向け】SQL Server上の図面メタデータとVSDXのプロパティを同期し、保存時に自動更新する双方向連携 – Visio VBA解析バイブル

スポンサーリンク

こんにちは!Visio VBAの世界へようこそ。
マクロの記録ボタンを押して図形を動かすだけのステージは、もう卒業しましたね。今日私たちが挑むのは、「Visioの図面ファイル(VSDX)と、外部のSQL Serverデータベースを完全に同期させる」という、エンタープライズ領域の超実戦的なテーマです。

「図面を保存した瞬間、DBの最新ステータスがプロパティに書き込まれる」
「図面を開くたびに、プロジェクトの進捗が自動で同期される」

こんな魔法のような仕組みが、Visio VBAとADO(ActiveX Data Objects)を組み合わせることで実現できます。初学者の方にとっては少し背伸びした技術に見えるかもしれませんが、安心してください。一つひとつの歯車を噛み砕いて、優しく、そして本質的な部分まで徹底的に解説していきます。

ここをクリアすれば、あなたのVisio自動化スキルは間違いなくプロの領域に到達します。さあ、一緒に極限の知見を覗いてみましょう!

—

なぜ「VisioとDBの連携」が必要なのか?

実務の現場では、こんな課題に直面したことはありませんか?

  • 「ネットワーク構成図」や「プラント図」を描いたものの、機器の仕様変更(IPアドレスや担当者など)がDB側の変更とズレてしまう。
  • 図面のプロパティ(タイトルや作成者など)を毎回手動で更新するのが面倒で、どれが最新のVSDXファイルか分からなくなる。

これを解決するのが「双方向メタデータ同期」です。Visioのファイル自体をただの「絵」として扱うのではなく、「生きたデータコンテナ」としてデータベースに直結させるのです。

本記事で実装するアーキテクチャ

1. 保存イベントのフック (`ThisDocument.BeforeDocumentSave`)
ユーザーが「上書き保存」または「名前を付けて保存」を実行した瞬間をVBAでキャッチします。
2. SQL Serverへの接続とデータ取得 (ADODB)
VBAからSQL Serverに安全に接続し、対応するプロジェクトの最新メタデータを取得します。
3. カスタムプロパティ(図面プロパティ)への書き込み
取得したデータを、Visioの「ドキュメント プロパティ(Document.DocumentProperties)」に流し込みます。

—

開発の全体像:実装コードの全貌

まずは、VisioのVBE(Visual Basic Editor)を開き、`ThisDocument` モジュールに貼り付ける実用コードの全体像をお見せします。

> 💡 エンジニアの知見:どこにコードを書くべきか?
> 通常の標準モジュールではなく、必ずプロジェクトウィンドウの `ThisDocument` に記述してください。イベントプロシージャ(ファイル保存時などのトリガー)は、ドキュメントオブジェクトのスコープでしか受け取れないからです。

Option Explicit

‘ =================================================================================
‘ 1. ドキュメント保存イベントのフック
‘ =================================================================================
Private Sub Document_BeforeDocumentSave(ByVal Doc As IVDocument)
On Error GoTo ErrorHandler

‘ 二重発火や不要なシステム図面の保存をガード
If Doc.Saved Then Exit Sub

Dim projectID As String
‘ 図面のカスタムプロパティから「プロジェクトID」を取得する
projectID = GetCustomDocumentProperty(Doc, “ProjectID”)

If projectID = “” Then
‘ まだIDが紐づいていない場合はスキップ(または新規割当処理へ)
Exit Sub
End If

‘ SQL Serverから最新データを取得し、プロパティを更新する
Call SyncMetadataFromSQLServer(Doc, projectID)

Exit Sub

ErrorHandler:
MsgBox “メタデータの同期中にエラーが発生しました: ” & Err.Description, vbCritical, “Visio DB Sync”
End Sub

‘ =================================================================================
‘ 2. ADODBを用いたSQL Serverからのデータ取得とプロパティ更新
‘ =================================================================================
Private Sub SyncMetadataFromSQLServer(ByVal Doc As IVDocument, ByVal projectID As String)
Dim conn As Object
Dim rs As Object
Dim connString As String
Dim query As String

‘ ADODBオブジェクトの生成(レイトバインディングで参照設定のトラブルを回避)
Set conn = CreateObject(“ADODB.Connection”)
Set rs = CreateObject(“ADODB.Recordset”)

‘ 接続文字列の設定(環境に合わせてSQL Serverの認証情報を書き換えてください)
connString = “Provider=MSOLEDBSQL;Server=YOUR_SERVER_NAME;Database=YOUR_DB_NAME;Trusted_Connection=yes;”

On Error GoTo DBError
conn.Open connString

‘ パラメータ化クエリでSQLインジェクションを防御
query = “SELECT ProjectName, Status, UpdatedDate, Manager FROM T_ProjectMaster WHERE ProjectID = ?”

Dim cmd As Object
Set cmd = CreateObject(“ADODB.Command”)
Set cmd.ActiveConnection = conn
cmd.CommandText = query
cmd.CommandType = 1 ‘ adCmdText

‘ パラメータの追加
cmd.Parameters.Append cmd.CreateParameter(“pID”, 200, 1, 50, projectID) ‘ 200 = adVarChar

Set rs = cmd.Execute

If Not rs.EOF Then
‘ データベースから取得した最新値でVisioのドキュメントプロパティを上書き更新
Call SetCustomDocumentProperty(Doc, “Title”, rs.Fields(“ProjectName”).Value)
Call SetCustomDocumentProperty(Doc, “Status”, rs.Fields(“Status”).Value)
Call SetCustomDocumentProperty(Doc, “LastSynced”, Format(Now, “yyyy-mm-dd hh:nn:ss”))
Call SetCustomDocumentProperty(Doc, “Manager”, rs.Fields(“Manager”).Value)

‘ 変更がプロパティに加えられたため、ドキュメントのDirtyフラグを立てる(保存を確実にするため)
‘ ※BeforeDocumentSave内でのプロパティ変更時は無限ループに注意が必要ですが、
‘ カスタムプロパティの変更のみであれば通常Savedステートは安全に維持されます。
End If

rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
Exit Sub

DBError:
MsgBox “データベース接続エラー: ” & Err.Description, vbExclamation, “SQL Server Error”
If Not conn is Nothing Then
If conn.State = 1 Then conn.Close
End If
Set rs = Nothing
Set conn = Nothing
End Sub

‘ =================================================================================
‘ 3. Visioドキュメントプロパティのヘルパー関数(取得・設定)
‘ =================================================================================
Private Function GetCustomDocumentProperty(ByVal Doc As IVDocument, ByVal propName As String) As String
On Error Resume Next
Dim propValue As String
propValue = Doc.DocumentProperties.Item(propName).Value
If Err.Number <> 0 Then
propValue = “” ‘ プロパティが存在しない場合は空文字を返す
End If
On Error GoTo 0
GetCustomDocumentProperty = propValue
End Function

Private Sub SetCustomDocumentProperty(ByVal Doc As IVDocument, ByVal propName As String, ByVal propValue As String)
On Error Resume Next
‘ 既存のプロパティが存在する場合は値を更新
Doc.DocumentProperties.Item(propName).Value = propValue

‘ 存在しない場合は新規追加を試みる
If Err.Number <> 0 Then
Err.Clear
Doc.DocumentProperties.Add propName, propValue
End If
On Error GoTo 0
End Sub

—

コードの急所を解剖する!知っておくべき3つのポイント

初学者のうちから意識してほしい、プロフェッショナルな設計思想を3つに絞って解説します。

1. レイトバインディング(`CreateObject`)の採用

コード内で `Dim conn As Object` とし、`CreateObject(“ADODB.Connection”)` を使っている点に注目してください。

  • 理由: 参照設定(「ツール」>「参照設定」から `Microsoft ActiveX Data Objects x.x Library` にチェックを入れる作業)を省略するためです。
  • メリット: このVSDXファイルを他のメンバーのPCに配った際、「参照設定の欠落(Missing)」によるコンパイルエラーを防ぐことができます。実務で最も恐ろしい「環境依存のバグ」を回避する定石です。

2. イベントの無限ループ・多重発火の防止

`Document_BeforeDocumentSave` イベント内でファイルを操作する際、うっかり「保存する」ような処理を書いてしまうと、「保存しようとする ➔ イベント発火 ➔ 中でさらに保存 ➔ 無限ループ」という悲惨なクラッシュを引き起こします。
今回はプロパティの書き換え(メモリ上のドキュメントオブジェクトの操作)に留めているため安全ですが、イベントを扱う際は「今、何が起きているか」のコンテキストを常に意識しましょう。

3. パラメータ化クエリによるセキュリティ担保

SQL Serverへクエリを投げる際、文字列を `+` で直結合するのは絶対にNGです(SQLインジェクションの温床になります)。
コード内では `Command` オブジェクトと `CreateParameter` を使って変数を安全にバインドしています。この「セキュリティに対する妥協のない姿勢」こそが、エンタープライズエンジニアの証です。

—

陥りやすいエラーとトラブルシューティング

実際にこの仕組みを導入する際、初心者が必ずと言っていいほどハマる壁を先回りして解説します。

Q1. 「ActiveX コンポーネントはオブジェクトを作成できません」というエラーが出る

  • 原因: 32bit版 / 64bit版のOfficeと、ODBC/OLEDBドライバーのミスマッチが原因の大半です。
  • 対策: 接続文字列の `Provider=MSOLEDBSQL;` は、Microsoft OLE DB Driver for SQL Serverが必要です。環境によっては古い `Provider=SQLOLEDB;` に変更するか、ODBCドライバー (`Provider=MSDASQL;…`) を利用してください。

Q2. 保存時に動作が重くなったり、固まる

  • 原因: SQL Serverへのネットワーク接続がタイムアウトを起こしている可能性があります。
  • 対策: ADOの `ConnectionTimeout` プロパティにあらかじめ短い秒数(例: `conn.ConnectionTimeout = 3`)を設定し、社内LANやVPNが切断されている状態でもVisioがフリーズしないようなフェイルセーフを組み込みましょう。

—

ここをクリアすれば、Visio VBAの基本はバッチリ!

お疲れ様でした!少し高度な内容でしたが、ここまでついて来られたあなたは、単なる「マクロ記録の使用者」から「Visioソリューション・アーキテクト」へと確実にステップアップしています。

  • 図面の保存というライフサイクルイベントをフックし、
  • 外部データベース(SQL Server)とADOでセキュアに対話し、
  • 図面のメタデータをプログラムから意のままにコントロールする。

このパターンをマスターすれば、図面管理システムや、社内ニッチなERP・工程管理ツールのフロントエンドとしてVisioを組み込むことが可能です。ぜひ、ご自身の開発環境やテスト用DBで試してみてください。

あなたの自動化ライフが、より知的でエキサイティングなものになりますように。それではまた、次の極限の知見でお会いしましょう!

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