【入門編】【上級】Document.VBProjectの操作:VBAからVBAコードを自動生成・修正するメタプログラミング – Visio VBA解析バイブル

スポンサーリンク

こんにちは! Visio VBAの深淵なる世界へようこそ。
これまでにマクロの記録を使ったり、図形を自動で配置するコードを書いたりした経験がある方なら、「お、もう基本はバッチリだな」と感じている頃でしょう。

でもね、ここからが本当のエンジニアリングの領域です。
今日お話しするのは、「VBAで、VBAのコード自体を書き換える・生み出す」という、少し刺激的で強力なメタプログラミングの技術。

「VBAからVBAを操作する?一体何に使うの?」って思いますよね。
例えば、ユーザーがボタンを押したら、その図面の目的に合わせた専用のマクロコードを動的に生成して埋め込む「自己拡張型のテンプレート」や、配布先で自動的に初期設定を行う「インストーラー付き図面」を作る時に、この技術が不可欠になるんです。

ここをクリアすれば、あなたのVisio自動化スキルは間違いなく「プロのアーキテクト領域」に到達します。さあ、一緒にその扉を開けてみましょう!

—

1. そもそも `Document.VBProject` って何だ?

通常、私たちが書くVBAコードは、VBE(Visual Basic Editor)を開いて手動でモジュールを追加し、そこに書き込んでいきますよね。

しかし、Visioのドキュメント(`.vsd` や `.vsdm`)の裏側には、`VBProject` というVBAのプロジェクト全体を管理するオブジェクトが潜んでいます。これをコードから操作するのが今回のテーマです。

⚠️ まず最初に立ちはだかる「セキュリティの壁」

このメタプログラミングを始める前に、絶対に避けて通れない重要な関門があります。それがセキュリティ設定です。

VBAからVBAプロジェクトを操作(プログラムによるアクセス)することは、悪意あるマクロ(ウイルスなど)にとっても好都合なため、Officeのデフォルトでは厳重にブロックされています。

【事前準備:ここを必ずチェック!】
1. Visioを起動し、[ファイル] > [オプション] > [トラスト センター] を開きます。
2. [トラスト センターの設定] ボタンをクリックします。
3. [マクロの設定] で、「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」にチェックを入れます。

これをしておかないと、後述するコードを実行した瞬間に「プログラムによる Visual Basic プロジェクトへのアクセスは信頼されていません」というエラーで強制終了します。現場で一番ハマるポイントなので、最初に必ずクリアしておきましょう。

—

2. 【実践】VBAから新しいモジュールを作り、コードを書き込む

それでは、実際にVisioのイミディエイトウインドウや標準モジュールから実行して、「新しい標準モジュールを自動生成し、そこにコードを書き込む」プログラムを見てみましょう。

以下のコードを、適当なモジュールに貼り付けて実行してみてください。

Sub CreateDynamicModule()
Dim vbp As Object
Dim comp As Object
Dim codeMod As Object
Dim targetDoc As Visio.Document

‘ 操作対象のドキュメント(ここでは現在アクティブな図面)
Set targetDoc = ActiveDocument

‘ 1. ドキュメントにVBProjectが存在するか確認(マクロ有効形式か?)
On Error Resume Next
Set vbp = targetDoc.VBProject
On Error GoTo 0

If vbp Is Nothing Then
MsgBox “この図面はマクロ有効形式(.vsdm)ではありません。保存し直してください。”, vbCritical
Exit Sub
End If

‘ 2. 新しい標準モジュール(vbext_ct_StdModule = 1)を追加
‘ ※参照設定で「Microsoft Visual Basic for Applications Extensibility 5.3」を入れると定数が使えますが、
‘ 今回は遅延バインディング(Object型)を使用しているため、マジックナンバー「1」を指定しています。
Set comp = vbp.VBComponents.Add(1)

‘ 生成されたモジュールに分かりやすい名前を付ける
comp.Name = “AutoGeneratedModule”

‘ 3. モジュールのコードペイン(CodeModule)を取得
Set codeMod = comp.CodeModule

‘ 4. コードを動的に書き込む
Dim lineNum As Long
lineNum = codeMod.CountOfLines + 1

codeMod.InsertLines lineNum, “Sub DynamicHello()”
codeMod.InsertLines lineNum + 1, ” MsgBox “”こんにちは!これは自動生成されたコードです。””, vbInformation, “”メタプログラミング”””
codeMod.InsertLines lineNum + 2, “End Sub”

MsgBox “モジュールの自動生成とコードの書き込みに成功しました!”, vbInformation

End Sub

コードの解説とエンジニアの知見

  • 遅延バインディングの活用 (`As Object`)

コード内であえて `Microsoft Visual Basic for Applications Extensibility` の参照設定を行わず、`Object` 型で受けています。これにより、配布先のVisioのバージョンや環境差異による参照切れエラー(コンパイルエラー)をスマートに回避できます。

  • マジックナンバー `1` の意味

`vbp.VBComponents.Add(1)` の `1` は、VBAコンポーネントの種類(標準モジュール)を表す列挙体 `vbext_ct_StdModule` の値です。クラスモジュールなら `2`、ユーザーフォームなら `3` を指定します。

  • マクロ有効形式の罠

Visioのデフォルト形式(`.vsdx`)にはVBAプロジェクトを保持できません。必ず `.vsdm`(マクロ有効図面)として保存されている必要があります。ここを見落とすと `targetDoc.VBProject` が取得できずに沈黙するので注意してください。

—

3. 応用:既存のコードを書き換える・削除する

モジュールを作るだけでなく、すでにあるコードを書き換えたり、用事が済んだらモジュールごと消去することも可能です。

例えば、「インストールのたびに現在日付をコード内に埋め込んで更新する」といった処理も、文字列操作と組み合わせることで自在に行えます。

Sub ModifyOrRemoveModule()
Dim vbp As Object
Dim comp As Object

Set vbp = ActiveDocument.VBProject

‘ “AutoGeneratedModule” という名前のモジュールが存在するか探す
On Error Resume Next
Set comp = vbp.VBComponents(“AutoGeneratedModule”)
On Error GoTo 0

If Not comp Is Nothing Then
‘ パターンA: モジュールが存在する場合は、コードを一部書き換える
Dim codeMod As Object
Set codeMod = comp.CodeModule

‘ 2行目のメッセージ内容を書き換える
‘ ReplaceLine (行番号, 新しいコード文字列)
codeMod.ReplaceLine 2, ” MsgBox “”【更新版】コードが動的に書き換えられました!””, vbInformation”

MsgBox “既存のモジュールコードを書き換えました。”, vbInformation

‘ パターンB: 用事が済んだのでモジュール自体を削除したい場合(コメントアウトを外して実行)
‘ vbp.VBComponents.Remove comp
‘ MsgBox “モジュールを削除しました。”, vbInformation

Else
MsgBox “対象のモジュールが見つかりませんでした。”, vbExclamation
End If
End Sub

—

4. 現場で陥りやすい罠とデバッグの極意

このレイヤーのコードを書くようになると、通常のVBA開発では遭遇しない特有のエラーに出会います。チーフアーキテクトからのアドバイスとして、以下の2点を胸に刻んでおいてください。

1. 「信頼性」の壁で止まる

  • エラー番号 `-2147467259` あたりが返ってきたら、ほぼ間違いなくトラストセンターの「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」のチェックが外れています。インストーラー等で他人に配布する場合、この設定をユーザー自身に手動でやってもらう必要があるため、「このツールを使うにはトラストセンターの設定変更が必要です」というドキュメントや誘導を必ずセットで用意するのがプロの気配りです。

2. コンパイルエラーのあるコードを流し込まない

  • 文字列としてVBAコードを生成するため、スペルミスや構文エラー(Syntax Error)があっても、書き込み時にはエラーになりません。実際にその生成されたプロシージャを実行した瞬間に初めて爆発します。動的生成するコードの文字列構築は、イミディエイトウインドウに `Debug.Print` などで一度出力し、構文に誤りがないかを入念に確認する癖をつけましょう。

—

まとめ

今回は、Visio VBAの奥の院とも言える `Document.VBProject` を使ったメタプログラミングの世界を解説しました。

  • トラストセンターの設定でプログラムからのVBAアクセスを許可する。
  • `VBComponents.Add(1)` で標準モジュールを動的に生み出す。
  • `CodeModule.InsertLines` や `ReplaceLine` でコードを自在に紡ぎ出す。

この技術をマスターすれば、ただ図形を整えるだけのマクロから脱却し、「自分自身を環境に合わせて進化させるテンプレートツール」や、「高度なアドオンインストーラー」を構築できるようになります。

ぜひご自身の開発環境で試して、Visio VBAを完全につかみ取ってください。あなたのエンジニアリングの幅が、ここからさらに大きく広がること間違いなしです!

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