Visio VBAを掌握する極限の知見:タイムスタンプ付き「名前を付けて保存」の完全自動化
開発プロジェクトの現場において、図面ファイルの世代管理は業務効率化の根幹をなす。手動で「名前を付けて保存」を繰り返し、ファイル名に日付を打ち込むような作業は、ヒューマンエラーの温床であり、エンジニアが最も排除すべき無駄な工数だ。
しかし、単に `ActiveDocument.SaveAs` を叩くだけのコードでは、実務の現場ではすぐに破綻する。
「ファイル名に使えない文字(`/` や `:` など)」による実行時エラー、「保存先フォルダが存在しない」という致命的な例外、そして意図しない上書きによるデータ消失――。
今回は、Visio VBAにおいて「堅牢に、安全に、そして美しく」タイムスタンプ付きのファイル保存を自動化する極意を伝授する。
—
なぜその書き方は危険なのか?(よくあるアンチパターン)
初心者がやりがちなコードを見てみよう。
‘ 【悪例】絶対に真似してはいけないコード
Sub BadSave()
Dim timeStr As String
timeStr = Now() ‘ そのまま文字列に変換しようとする
‘ 問題1: Now()には “/” や “:” が含まれるため、Windowsのファイル名規則違反でクラッシュする
‘ 問題2: フォルダの存在確認をしていないため、パスが存在しないと即死する
‘ 問題3: エラーハンドリングがないため、ファイルが開いている等の理由で強制終了する
ActiveDocument.SaveAs “C:\Works\図面_” & timeStr & “.vsdx”
End Sub
このコードは、実行した瞬間にWindowsのファイルシステム制約に阻まれてエラーを起こす。プロが書くべきコードは、環境の変化やユーザーの操作ミスに対して鉄壁のガードを持つものでなければならない。
—
堅牢なファイル保存を実現する3つの設計思想
プロダクションコードとして通用するマクロを構築するため、以下の3点にこだわる。
1. 完全な文字列サニタイズ(不可視文字・禁止文字の排除)
`Format`関数を駆使し、ファイル名として安全な `YYYYMMDD_HHMMSS` 形式へ強制変換する。
2. ディレクトリの動的生成(FSOの活用)
保存先フォルダが存在しない場合、エラーを吐くのではなく、コード側で自動生成する。
3. トランザクション的思考(エラーハンドリング)
万が一のディスク容量不足やファイルロックに対し、マクロが静かに、かつ安全に処理を中断・通知できるようにする。
—
【コピペ即稼働】プロダクション品質のVBAコード
以下のコードをVisioのVBAエディタ(`Alt + F11`)に実装し、標準モジュールに貼り付けてほしい。実務でそのまま使えるレベルの堅牢性を持たせてある。
Option Explicit
‘ ==============================================================================
‘ 処理名 : SaveWithTimestamp
‘ 概要 : アクティブなVisio図面にタイムスタンプを付与して保存する
‘ 備考 : 保存先フォルダが存在しない場合は自動生成する
‘ ==============================================================================
Public Sub SaveWithTimestamp()
‘ 1. ドキュメントが開かれているか(未保存の新規図面対策など)のチェック
If ActiveDocument.Path = “” Then
‘ 一度も保存されていないドキュメントは、まず任意の場所で初期保存させるか、
‘ デフォルトのパスを設定する必要があります。ここでは安全のため警告して終了します。
MsgBox “この図面はまだ一度も保存されていません。” & vbCrLf & _
“一度手動で保存してから実行してください。”, vbCritical, “保存エラー”
Exit Sub
End Sub
On Error GoTo ErrorHandler
‘ 2. 保存先ディレクトリの定義(実務に合わせて変更してください)
Dim targetDir As String
targetDir = ActiveDocument.Path & “\Archive\” ‘ 同一階層の Archive フォルダを想定
‘ 3. FileSystemObjectを用いた堅牢なフォルダ存在確認・生成
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(targetDir) Then
fso.CreateFolder targetDir
Debug.Print “フォルダを新規作成しました: ” & targetDir
End If
‘ 4. ファイル名に使用できない文字を排除したタイムスタンプの生成
‘ 例: 20231024_153045 (スラッシュやコロンは一切含めない)
Dim timeStamp As String
timeStamp = Format(Now, “YYYYMMDD_HHMMSS”)
‘ 5. 拡張子を除いたファイル名の取得
Dim originalName As String
originalName = fso.GetBaseName(ActiveDocument.Name)
‘ 6. 最終的な保存パスの組み立て
Dim fullPath As String
fullPath = targetDir & originalName & “_” & timeStamp & “.vsdx”
‘ 7. 保存実行
ActiveDocument.SaveAs fullPath
‘ 8. 成功通知(実務ではログ出力やステータスバー表示に置き換えても良い)
MsgBox “図面のバックアップ保存が完了しました。” & vbCrLf & fullPath, vbInformation, “保存成功”
‘ クリーンアップ
Set fso = ExitRoutine(fso)
Exit Sub
ErrorHandler:
‘ 異常系ハンドリング
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
If Not fso Is Nothing Then Set fso = Nothing
End Sub
‘ 補助関数:オブジェクトの安全な解放
Private Function ExitRoutine(ByRef fsoObj As Object) As Object
If Not fsoObj Is Nothing Then Set fsoObj = Nothing
Set ExitRoutine = Nothing
End Function
—
チーフアーキテクトからの実務アドバイス
1. `ActiveDocument.Path` の罠に注意せよ
新規作成した直後のドキュメント(まだ一度もディスクに保存されていない状態)では、`ActiveDocument.Path` は長さゼロの文字列 (`””`)を返す。この状態でパス結合を行うと、予期せぬカレントディレクトリへの保存やエラーを引き起こす。上記のコードでは、このガードを最初に突破条件として組み込んでいるため、安全に弾くことができる。
2. データベースや外部連携への発展
このタイムスタンプ付き保存のロジックをマスターすれば、次は「保存したファイルパスをExcelやAccess、あるいは社内DB(SQL Serverなど)に自動記録する」というフェーズへ進むことができる。
`fullPath` 変数に格納された文字列をそのままADOやDAO経由でインサートすれば、図面の完全な世代管理台帳がノータイムで完成する。
手作業の自動化は、単なる「手間の削減」ではなく、「ヒューマンエラーの根絶」のためのエンジニアリングだ。このコードをベースに、あなたの現場の業務をさらに強固なものへとアップデートしてほしい。
