【実務・中級編】VBAモジュールの自動インポート/エクスポート:Document.VBProjectによるコード管理の自動化 – Visio VBA解析バイブル

スポンサーリンク

【Visio VBA極限活用】Document.VBProjectを完全制御し、VBAコードの自動インポート/エクスポート基盤を構築する

開発プロジェクトの現場において、Visioのステンシルや図面ファイル(.vsdm)に埋め込まれたVBAコードの管理に頭を悩ませたことはないだろうか。

「複数のVisioファイルに散らばるマクロを一斉に修正したい」
「Gitなどのバージョン管理システムでVBAの差分を追いたいのに、バイナリだから中身が見えない」
「GUIでちまちまVBEを開いてコードをインポート・エクスポートする作業を、いい加減自動化したい」

この課題に対する答えは一つしかない。`Document.VBProject`オブジェクトをプログラムから直接叩き、外部の `.bas` / `.cls` ファイルとVBAプロジェクトを完全に同期させる仕組みを構築することだ。

今回は、数々のエンタープライズ環境で自動化基盤を構築してきたチーフアーキテクトの視点から、VisioにおけるVBAコード自動管理の極意と、現場でそのまま使えるプロダクションコードを授けよう。

1. 開発前に立ちはだかる「マクロセキュリティの壁」を突破する

`Document.VBProject` を操作するコードを書く前に、必ずクリアしなければならないハードルがある。それが Officeのマクロセキュリティ設定 だ。

デフォルトのセキュリティ設定のままプログラムを実行すると、以下のエラーに直面する。
> 「VBA プロジェクトへのプログラムによるアクセスは信頼されていません」

このエラーを回避するためには、ExcelやWordと同様に、Visio側でも設定が必要となる。

事前準備:設定手順

1. Visioを起動し、「ファイル」>「オプション」>「トラスト センター」>「トラスト センターの設定」 を開く。
2. 「マクロの設定」 カテゴリを選択する。
3. 「VBA プロジェクトへのプログラムによるアクセスを信頼する」 にチェックを入れる。

※エンタープライズ環境において、この設定をグループポリシー(GPO)やレジストリで一括制御している場合は、情報システム部門との調整が必要になる点に留意してほしい。ここをクリアしない限り、いかなる高度なVBAコードもただのゴミと化す。

2. アーキテクチャ設計:なぜ「野良マクロ」の管理は破綻するのか?

多くの開発者は、図面ファイルとコードが一体化しているVisioの特性に甘え、各図面の中に直接コードを書き込む。これは保守性において最悪のアンチパターンだ。

真にスケーラブルな設計とは、「コードの本体は外部のテキスト(`.bas`/`.cls`)としてGit等で厳格にバージョン管理し、リリースやビルドのタイミングでVisioドキュメントへ流し込む(インポートする)」 という単一方向のパイプラインを確立することである。

そのためには、以下の2つの処理を自動化する汎用モジュールが必要になる。
1. エクスポート機能:既存のVisioからコードを抜き出し、テキスト資産化する。
2. インポート機能(一括更新):最新のテキスト資産をVisioに流し込み、既存モジュールを上書きする。

3. 【プロダクションコード】VBAモジュールの自動インポート/エクスポート

以下のコードは、エラーハンドリング、既存モジュールの安全な削除、そしてファイルI/Oの確実性を担保した、現場でそのまま使える実用コードである。

このコード自体は、制御用のマスタVisioファイル(またはExcelマクロ)に配置し、対象となる`.vsdm`ファイルを操作する想定で記述している。

Option Explicit

‘ =========================================================================
‘ módulo名: modVBProjectManager
‘ 概要: VisioドキュメントのVBAプロジェクトと外部ファイル間の
‘ インポート・エクスポートを自動制御するモジュール
‘ =========================================================================

‘ — 早期バインディングのために Microsoft Visual Basic for Applications Extensibility 5.3 を参照設定すること —
‘ ※参照設定ができない場合は、Object型を用いた遅延バインディングに変更してください。

”’

”’ 指定したVisioファイルのVBAモジュールを外部フォルダへ一括エクスポートする
”’

”’ 対象のVisioファイルパス (.vsdm) ”’ 出力先フォルダパス Public Sub ExportVbaModules(ByVal targetVisioPath As String, ByVal outputDir As String)
Dim appVisio As Visio.Application
Dim doc As Visio.Document
Dim vbProj As Object ‘ VBIDE.VBProject
Dim vbComp As Object ‘ VBIDE.VBComponent
Dim ext As String
Dim filePath As String

On Error GoTo ErrorHandler

‘ Visioインスタンスの起動(バックグラウンド処理)
Set appVisio = New Visio.Application
appVisio.Visible = False

Set doc = appVisio.Documents.Open(targetVisioPath)
Set vbProj = doc.VBProject

‘ 出力先ディレクトリの存在確認(なければ作成する簡易処理)
If Dir(outputDir, vbDirectory) = “” Then
MkDir outputDir
End If

‘ プロジェクト内の全コンポーネントを走査
For Each vbComp In vbProj.VBComponents
‘ 標準モジュール(1) と クラスモジュール(2) のみを対象とする
If vbComp.Type = 1 Or vbComp.Type = 2 Then
Select Case vbComp.Type
Case 1: ext = “.bas”
Case 2: ext = “.cls”
End Select

filePath = outputDir & “\” & vbComp.Name & ext

‘ 既にファイルが存在する場合は上書きのために削除
If Dir(filePath) <> “” Then Kill filePath

‘ エクスポート実行
vbComp.Export filePath
Debug.Print “Exported: ” & vbComp.Name & ext
End If
Next vbComp

CleanUp:
On Error Resume Next
If Not doc Is Nothing Then doc.Close False
If Not appVisio Is Nothing Then appVisio.Quit
Exit Sub

ErrorHandler:
MsgBox “エクスポート中にエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanUp
End Sub

”’

”’ 指定したVisioファイルのVBAモジュールを外部フォルダのファイル群で一括更新(インポート)する
”’

”’ 対象のVisioファイルパス (.vsdm) ”’ ソースコードが格納されているフォルダパス Public Sub ImportVbaModules(ByVal targetVisioPath As String, ByVal sourceDir As String)
Dim appVisio As Visio.Application
Dim doc As Visio.Document
Dim vbProj As Object ‘ VBIDE.VBProject
Dim vbComp As Object ‘ VBIDE.VBComponent
Dim fileName As String
Dim filePath As String
Dim moduleName As String

On Error GoTo ErrorHandler

Set appVisio = New Visio.Application
appVisio.Visible = False

Set doc = appVisio.Documents.Open(targetVisioPath)
Set vbProj = doc.VBProject

‘ 1. 既存の標準モジュールとクラスモジュールを完全に削除(クリーンインポートの鉄則)
Dim i As Long
For i = vbProj.VBComponents.Count To 1 Step -1
Set vbComp = vbProj.VBComponents(i)
‘ 標準モジュール(1), クラスモジュール(2) のみを削除対象とする
‘ ※ Documentモジュール(100)などは削除してはいけないため除外
If vbComp.Type = 1 Or vbComp.Type = 2 Then
vbProj.VBComponents.Remove vbComp
End If
Next i

‘ 2. ソースディレクトリから .bas および .cls ファイルを読み込んでインポート
‘ .basファイルのインポート
fileName = Dir(sourceDir & “\.bas”)
Do While fileName <> “”
filePath = sourceDir & “\” & fileName
vbProj.VBComponents.Import filePath
Debug.Print “Imported: ” & fileName
fileName = Dir
Loop

‘ .clsファイルのインポート
fileName = Dir(sourceDir & “\.cls”)
Do While fileName <> “”
filePath = sourceDir & “\” & fileName
vbProj.VBComponents.Import filePath
Debug.Print “Imported: ” & fileName
fileName = Dir
Loop

‘ 変更を保存して閉じる
doc.Save

CleanUp:
On Error Resume Next
If Not doc Is Nothing Then doc.Close False
If Not appVisio Is Nothing Then appVisio.Quit
Exit Sub

ErrorHandler:
MsgBox “インポート中にエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanUp
End Sub

4. プロフェッショナルが教える実装上の重要注意点

上記のコードを実務のパイプラインに組み込む際、ハマりやすい罠がいくつか存在する。プロフェッショナルとして、これらについても言及しておこう。

① `Visio.Document` の保存形式の罠

マクロを含むVisioファイルを操作する場合、ファイル形式は必ず マクロ有効図面(`.vsdm`) でなければならない。通常の `.vsdx` に対してコードをインポートしようとすると、VBAプロジェクト自体が存在しないため、`doc.VBProject` 呼び出し時に実行時エラーが発生する。自動化スクリプト側で拡張子のバリデーションを必ず実装すること。

② 参照設定(Extensibilityライブラリ)の回避テクニック

先ほどのコードでは `VBIDE.VBProject` や `VBIDE.VBComponent` を扱っている。これを正確に動かすには、VBEの「ツール」>「参照設定」から 「Microsoft Visual Basic for Applications Extensibility 5.3」 にチェックを入れる必要がある。
もし、配布するツール側で参照設定の手間を省きたい場合は、型宣言を `Object` にし(上記のサンプルコードは既にこの方針をとっている)、定数(`vbComp.Type = 1` など)をリテラル値に置き換える「遅延バインディング」を徹底すること。これにより、環境依存のエラーを完全に排除できる。

③ 削除のループ処理における「逆順ループ」の鉄則

インポート処理の冒頭で既存モジュールを削除しているが、ここにはVBA特有のトラップがある。

‘ 駄目な例:前から順番に削除するとインデックスがずれてバグる
For i = 1 To vbProj.VBComponents.Count
‘…
Next i

‘ 正しい例:後ろから順番に削除する
For i = vbProj.VBComponents.Count To 1 Step -1
‘…
Next i

コレクションの要素を削除しながらループを回す場合、後ろから前へ(降順) カウンターを回すのはVBA自動化における基本中の基本である。これを怠ると、一部のモジュールが削除されずに残るか、予期せぬインデックスエラーを引き起こす。

5. おわりに:自動化の先にある「真のコード管理」へ

今回紹介した `Document.VBProject` を用いたコードの自動インポート/エクスポート手法をマスターすれば、もはや「どれが最新版のマクロかわからない」というカオスな状況とはお別れだ。

外部テキストとして管理されたVBAコードは、Gitなどのバージョン管理システムに乗せることができ、誰がいつ何の変更を加えたのかを完全に追跡できるようになる。さらに、CI/CDパイプラインやJenkins等のタスクランナーと組み合わせることで、マスターデータから最新のマクロを組み込んだVisio成果物を完全自動でビルドすることも夢ではない。

設計の美しさと堅牢さを追求し、退屈で非効率な手作業をコードで駆逐せよ。それこそが、真の業務自動化エンジニアの仕事である。

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