破壊的エラーを未然に防ぐ:PowerPoint VBAにおけるファイル名バリデーションの極致
プレゼンテーションの自動生成において、最も無様で、かつ最も頻発するエラーをご存じだろうか。それは「ファイルシステムが受け付けない文字列」による保存時の実行時エラーだ。
ユーザーがフォームに入力した「会議名」や「プロジェクト名」をそのままファイル名に流し込む。その安易な実装が、ある日突然、環境依存文字や禁止文字(`/ \ : ? ” < > |`)という地雷を踏み、業務を停止させる。
今日は、場当たり的な `Replace` 関数の羅列を卒業し、堅牢なシステムアーキテクチャの視点から「安全なファイル名生成」を実装する。
—
1. なぜ「単純な置換」では足りないのか
多くのエンジニアは、禁止文字を単純な空白に置換して満足する。だが、それで十分だろうか?
- 制御文字の混入: 目に見えない改行やタブがファイル名に紛れ込むケース。
- 長すぎるパス: Windowsの `MAX_PATH`(260文字)制限を超えた場合の黙殺されるエラー。
- 末尾のスペース/ドット: Windows APIの仕様により、末尾にこれらがあるファイルは作成直後にアクセス不能になるという罠。
これらを「運用でカバー」するのは、エンジニアの敗北を意味する。
—
2. 堅牢なファイル名生成エンジンの実装
以下は、私が長年蓄積してきた「安全な文字列生成」のコアロジックだ。正規表現を用いて禁止文字を排除し、かつWindowsの制約を考慮した設計としている。
‘ —————————————————————————
‘ @Title: SafeFileNameGenerator
‘ @Desc: 不正文字を排除し、Windowsの仕様に準拠した安全なファイル名を生成する
‘ @Author: Chief Architect
‘ —————————————————————————
Public Function GetSafeFileName(ByVal inputStr As String) As String
Dim regEx As Object
Set regEx = CreateObject(“VBScript.RegExp”)
‘ 禁止文字と制御文字(0-31)を正規表現で定義
‘ [\\/:?”<>|] は禁止文字、 [\x00-\x1F] は制御文字
regEx.Pattern = “[\\/:?””<>|\x00-\x1F]”
regEx.Global = True
‘ 不正文字をアンダースコアに置換
Dim safeName As String
safeName = regEx.Replace(inputStr, “_”)
‘ 末尾のスペースとドットはWindows仕様で削除対象になるため、事前に置換
Do While Right(safeName, 1) = ” ” Or Right(safeName, 1) = “.”
safeName = Left(safeName, Len(safeName) – 1)
Loop
‘ 最大文字数制限(念のため200文字以内に抑制)
If Len(safeName) > 200 Then
safeName = Left(safeName, 200)
End If
GetSafeFileName = safeName
‘ オブジェクトの明示的解放(メモリ管理の基本)
Set regEx = Nothing
End Function
—
3. 保存処理における「墓穴」を掘らないために
VBAにおけるオブジェクト操作で忘れがちなのが、`Presentation` オブジェクトのライフサイクル管理だ。保存処理の前後でメモリリークを防ぐための定石を提示する。
Public Sub SavePresentationSafely(ByVal targetPres As Presentation, ByVal folderPath As String, ByVal rawTitle As String)
Dim safeFileName As String
Dim fullPath As String
‘ 1. 名前を安全化
safeFileName = GetSafeFileName(rawTitle)
fullPath = folderPath & “\” & safeFileName & “.pptx”
‘ 2. ファイル存在チェック(上書き確認のロジック)
On Error Resume Next
If Dir(fullPath) <> “” Then
‘ ここでエラーハンドリングを挟むのがプロの矜持
Debug.Print “Warning: File already exists. Overwriting.”
End If
On Error GoTo 0
‘ 3. 確実な保存
‘ ファイル形式を指定することで、変換エラーを最小化する
targetPres.SaveAs Filename:=fullPath, FileFormat:=ppSaveAsOpenXMLPresentation
‘ 注意:保存後のオブジェクトは明示的に解放せず、
‘ Closeメソッドで適切にメモリを解放するライフサイクル管理を徹底すること
End Sub
—
4. チーフアーキテクトからの助言
- 環境依存文字の罠: Unicode文字(絵文字や特殊記号)が含まれる場合、VBAの `String` 型(UTF-16)は耐えられるが、保存先のファイルシステム(FAT32など)が対応していないケースがある。本気でグローバル環境を考慮するなら、最終的に `ADODB.Stream` を介したエンコード変換が必要になる。
- エラーハンドリングの哲学: `On Error Resume Next` は毒薬だ。必要な箇所(ファイルシステムへのアクセス)以外では決して使用してはならない。エラーが発生した場合は、ユーザーに「なぜ保存できなかったのか」を論理的に提示するログを出力せよ。
システムは「動く」ことよりも「壊れない」ことの方が価値が高い。今回提示したコードは、あなたの自動化ツールが「信頼できるインフラ」へと進化するための最小構成だ。
明日からの開発において、安易な `Replace` に頼ることはやめなさい。コードはあなたの思考の鏡であるべきだ。
