こんにちは!Visio VBAの自動化の世界へようこそ。
マクロの記録ボタンを押して「なんだか動いたけれど、中身がよくわからない……」という状態から一歩抜け出し、自分の手で図面を意のままに操りたいあなたへ。
今回は、実務で絶対に直面する「図面のバージョン管理と履歴の整理」をテーマに、プロの現場でも通用する本格的なVBAコードを一緒に作っていきます。
ここをクリアすれば、Visio VBAのオブジェクト構造の基本はバッチリです。背伸びせず、一つひとつ丁寧に紐解いていきましょう!
—
現場でよくある悩み:図面のバージョン管理、どうしていますか?
設計やレイアウトの作業をしていると、こんな課題にぶつかりませんか?
- 「修正前の状態も残しておきたいから、ページを複製して `layout_v1`, `layout_v2`……と手動で名前を変えている」
- 「古いページが溜まってきて、どれが最新の図面なのか一目でわからない」
- 「かといって古いページを消してしまうと、後から『あの時の構成はどうだったっけ?』と言われた時に困る」
これを手作業でやっていると、名前の付け忘れや、レイヤーの切り替え忘れといったヒューマンエラーの温床になります。
ならば、「ボタン一つで今日の日付を組み込んだページ名を自動生成し、古いページは『アーカイブ専用レイヤー』へそっと退避させる」仕組みをVBAで作り上げてしまいましょう!
—
Visio VBAを掌握するための「3つの基本原則」
コードを書く前に、Visioの心臓部であるオブジェクト構造の考え方を頭に入れておきましょう。ここが分かると、エラーに怯えなくなります。
1. ActiveDocument(今、触っているファイル)からすべてが始まる
Visioでは、現在アクティブなドキュメント、その中にある「Pages(ページたち)」、そして各ページの中にある「Shapes(図形たち)」や「Layers(レイヤーたち)」という階層構造になっています。
2. ページ名は「名前の衝突」に気を付ける
Visioでは、同じファイル内に全く同じ名前のページを作ることはできません。だからこそ、「日付や連番」を組み込んだ自動命名規則が強力な武器になります。
3. レイヤーは「透明なフィルム」のようなもの
Visioのレイヤー機能は、絵の上に何枚も透明なフィルムを重ねる感覚です。図形を消去(Delete)するのではなく、古いページの図形たちを「Archive(非表示・ロック用)」のレイヤーに割り当てることで、データを保持したまま視界から綺麗に消すことができます。
—
実装コード:全自動アーカイブ&命名規則マクロ
それでは、開発環境(Alt + F11キーでVBAエディタを開き、標準モジュールを追加)に、以下のコードをそのまま貼り付けてみてください。
実務でそのままコピペして動かせるよう、細かくコメントを入れています。
Option Explicit
‘ ==============================================================================
‘ 【メイン処理】現在ページを複製・日付リネームし、元の古いページをアーカイブする
‘ ==============================================================================
Sub ArchiveAndCreateNewPage()
Dim vsoCurrentPage As Visio.Page
Dim vsoNewPage As Visio.Page
Dim archiveLayer As Visio.Layer
Dim shp As Visio.Shape
Dim baseName As String
Dim dateStr As String
Dim newPageName As String
‘ 1. エラーハンドリングの準備
On Error GoTo ErrorHandler
‘ 2. 現在アクティブなページを取得
Set vsoCurrentPage = ActivePage
‘ ベースとなるページ名を取得(もし “Layout” のような名前ならそれを流用)
baseName = vsoCurrentPage.Name
‘ もしすでに日付がついている場合は、ベース部分を綺麗に切り出すなどの処理も可能ですが、
‘ 今回はシンプルに現在のページ名をベースとします。
‘ 3. 「YYYYMMDD」形式の日付文字列を生成
dateStr = Format(Date, “yyyymmdd”)
‘ 4. 新しいページ名を決定(例: 20231024_Layout)
newPageName = dateStr & “_” & baseName
‘ 【重要】同名ページが存在する場合のエラーを防ぐための簡易チェック
If CheckPageExists(newPageName) Then
newPageName = newPageName & “_” & Format(Time, “hhmmss”)
End If
‘ 5. 現在のページを複製して新しいページを作成
‘ Visioの Duplicate メソッドは、ページ自体の複製ではなく図形の複製に使われるため、
‘ 正しくは「ActiveDocument.Pages.Add」で新規作成し、図形をコピペするか、
‘ もしくはシンプルに「現在ページを複製するAPI」を使います。
‘ ※VisioのUI上の「ページの複製」に相当するのは vsoCurrentPage.Duplicate です。
Set vsoNewPage = vsoCurrentPage.Duplicate
‘ 複製されたページ(新しくアクティブになったページ、または複製されたオブジェクト)の名前を変更
‘ 通常、Duplicateを実行すると、複製されたページがアクティブになります。
Set vsoNewPage = ActivePage
vsoNewPage.Name = newPageName
‘ 6. 【古いページの処理】元のページに戻ってアーカイブ作業を行う
‘ 複製元のページを名前で再取得(あるいはあらかじめ変数に保持)
‘ ここでは分かりやすく、名前(baseName)で元のページをアクティブにします。
ActiveDocument.Pages(baseName).Activate
Set vsoCurrentPage = ActivePage
‘ 7. 古いページ側に「Archive_Layer」が存在するか確認し、なければ作成する
Set archiveLayer = GetOrCreateLayer(vsoCurrentPage, “Archive_Layer”)
‘ 8. 古いページにあるすべての図形を、アーカイブレイヤーに割り当てる
For Each shp In vsoCurrentPage.Shapes
archiveLayer.Add shp
Next shp
‘ 9. アーカイブレイヤーを「非表示」かつ「ロック(編集不可)」にする
‘ Cell物件やLayerのプロパティを操作します
archiveLayer.CellsC(visLayerVisible).FormulaU = 0 ‘ 0 = 非表示
archiveLayer.CellsC(visLayerLock).FormulaU = 1 ‘ 1 = ロック
‘ 10. 仕上げに、新しく作成した作業用ページに移動する
ActiveDocument.Pages(newPageName).Activate
MsgBox “見事にお引越し完了しました!” & vbCrLf & _
“新ページ名: ” & newPageName & vbCrLf & _
“旧ページは「Archive_Layer」に退避されました。”, vbInformation, “自動化完了”
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “予期せぬエラー”
End Sub
‘ ==============================================================================
‘ 【補助関数】指定した名前のページがすでに存在するかチェックする
‘ ==============================================================================
Private Function CheckPageExists(ByVal pName As String) As Boolean
Dim p As Visio.Page
CheckPageExists = False
For Each p In ActiveDocument.Pages
If p.Name = pName Then
CheckPageExists = True
Exit Function
End If
Next p
End Function
‘ ==============================================================================
‘ 【補助関数】指定したレイヤーが存在すれば取得し、なければ新規作成する
‘ ==============================================================================
Private Function GetOrCreateLayer(ByVal targetPage As Visio.Page, ByVal layerName As String) As Visio.Layer
Dim lyr As Visio.Layer
Dim foundLyr As Visio.Layer
Set foundLyr = Nothing
‘ 既存のレイヤーから探す
For Each lyr In targetPage.Layers
If lyr.Name = layerName Then
Set foundLyr = lyr
Exit For
End If
Next lyr
‘ なければ新規作成
If foundLyr Is Nothing Then
Set foundLyr = targetPage.Layers.Add(layerName)
End If
Set GetOrCreateLayer = foundLyr
End Function
—
コードのポイント:ここが分かれば怖くない!
初心者の方が「おっ」とつまずきやすいポイントを、先輩エンジニアの視点で解説します。
1. `Format(Date, “yyyymmdd”)` で日付を美しくハックする
VBAの `Date` 関数はシステムの日付を取ってきますが、そのまま使うと `2023/10/24` のようにスラッシュが入ってしまい、ファイル名やページ名としては使えない(エラーになる)ことがあります。
`Format` 関数を使って `yyyymmdd` という文字列に整形することで、ファイルソート(日付順の並び替え)もしやすい綺麗な命名規則を実現しています。
2. 図形を消さずに「レイヤー」に封印する
古い図面を `Delete` で消してしまうと、「やっぱりあの時のパーツの配置を確認したい」という時に復元できません。
コードの後半(ステップ7〜9)では、
1. `Archive_Layer` という名前のレイヤーを作る
2. ページ上の全図形 (`For Each shp In vsoCurrentPage.Shapes`) をそのレイヤーに所属させる
3. レイヤー自体のプロパティを 「非表示(Visible = 0)」 かつ 「ロック(Lock = 1)」 に書き換える
という離れ業をやっています。これなら、データは安全にファイル内に保持されつつ、画面上からはスッキリ消えて誤操作も防げます。
—
陥りやすいエラーと対策
- 「この名前のページはすでに存在します」というエラーが出る
- 原因: 同一日に2回以上このマクロを実行すると、全く同じページ名(例: `20231024_Layout`)を作ろうとしてVisioが怒ります。
- 対策: 今回のコードには、重複を検知したら自動で「時分秒(`hhmmss`)」を末尾に付与して衝突を防ぐガード(`CheckPageExists` 関数)を組み込んでいますので安心してください。
—
おわりに:ここをクリアすれば、Visio VBAの基本はバッチリです!
お疲れ様でした!今回は「ページ名の日付自動命名」と「レイヤーを活用した安全なアーカイブ手法」という、実務で今すぐ使える強力なテクニックをご紹介しました。
オブジェクトの取得、条件分岐、レイヤー操作、そしてエラー回避の工夫。このコードの中には、Visio VBAをマスターするためのエッセンスがぎっしり詰まっています。
ぜひご自身の環境で動かしてみて、業務効率化の爽快感を味わってください。
「もっとこんな自動化がしたい!」というリクエストがあれば、いつでもまたエンジニア仲間として相談に乗りますよ。それでは、快適な自動化ライフを!
