【AutoCAD VBA】ファイル名生成の「死角」を消す:OS互換性を完全制御するセーフ・セーブの極意
AutoCADの自動化において、最も軽視されがちだが、最も致命的なバグを誘発するのが「図面保存時のパス解決」だ。特にタイトルブロックから取得した文字列をそのままファイル名に流用する際、Windowsのファイルシステムが受け付けない文字(`/ : ? ” < > |`)によって、自動化プロセスが例外を吐き、深夜のバッチ処理が全滅する……そんな光景を幾度となく見てきた。
本稿では、シニアエンジニアとして、単なる置換処理に留まらない「堅牢なセーフ・セーブ機能」のアーキテクチャを提示する。
—
1. なぜ「単純な置換」では足りないのか
VBAで `Replace` 関数を重ねるだけのロジックは、初級者の甘えに過ぎない。実務では以下の3点を考慮しなければならない。
- OS/ファイルシステム制約: Windowsの禁止文字のみならず、パスの最大長(MAX_PATH)制限への配慮。
- メモリとオブジェクトのライフサイクル: `Database` オブジェクトを操作する際、開いたファイルを確実に閉じ、メモリリークを抑止する管理。
- 非同期・マルチユーザー環境: 読み取り専用で開かれている場合や、他者がアクセス中のケースに対する排他制御の考慮。
—
2. 極限のファイル名クレンジングロジック
以下に、再利用性を極限まで高めた関数を提示する。このロジックは単なる文字列置換ではなく、正規表現を用いて「制御不能な文字」を根こそぎ排除する設計だ。
‘ @brief ファイル名として安全な文字列を生成する
‘ @param rawString 図面タイトル等の元文字列
‘ @return OS互換性が保証されたファイル名
Public Function GetSafeFileName(ByVal rawString As String) As String
‘ Windowsの禁止文字: / : ? ” < > |
‘ これらをアンダースコアに置換する。正規表現オブジェクトを明示的に使用
Dim regEx As Object
Set regEx = CreateObject(“VBScript.RegExp”)
With regEx
.Global = True
.IgnoreCase = True
‘ 禁止文字のセット
.Pattern = “[/\\:\\?””<>|]”
End With
‘ 置換処理
Dim safeName As String
safeName = regEx.Replace(rawString, “_”)
‘ 念のため、末尾のスペースやピリオドも除去(Windowsの仕様トラブル回避)
safeName = Trim(safeName)
‘ メモリ最適化:オブジェクトの明示的解放
Set regEx = Nothing
GetSafeFileName = safeName
End Function
—
3. AutoCADデータベースの安全な保存手法
単に `SaveAs` を呼ぶだけでは不十分だ。特に古いバージョンのDWG形式への変換(レガシー互換)を行う場合、`AcSaveAsType` の定数を正しく制御する必要がある。
‘ @brief 図面を安全に指定パスへ保存する
‘ @param targetPath 保存先のフルパス
‘ @param saveAsType AutoCADの保存フォーマット (例: ac2018_dwg)
Public Sub SecureSave(ByVal targetPath As String, ByVal saveAsType As Integer)
On Error GoTo ErrorHandler
Dim doc As AcadDocument
Set doc = ThisDrawing
‘ 保存処理の実行
‘ 注:パスが長すぎる場合などの例外ハンドリングをここで行う
doc.SaveAs targetPath, saveAsType
Exit Sub
ErrorHandler:
‘ 致命的なエラーログを出力し、システムを安全に停止させる
MsgBox “保存失敗: ” & Err.Description, vbCritical
Err.Clear
End Sub
—
4. チーフアーキテクトからの助言:現場の知見
1. レガシー環境の保守
AutoCAD VBAは `32bit` と `64bit` の混在環境に晒されることが多い。特にWindows APIを使用する場合、`PtrSafe` 属性と `LongPtr` 型の使用を徹底せよ。これを怠ると、次期OSアップデート時にシステム全体がクラッシュする。
2. パス長制限(MAX_PATH)の回避
260文字を超えるパスは、OSレベルで弾かれる。もし複雑な階層構造のサーバーで運用しているなら、`\\?\` プレフィックスを付けてパスを絶対パス化することで、拡張パス(最大32,767文字)を利用可能にする手法を検討すべきだ。
3. オブジェクトのライフサイクル
VBAの `Set = Nothing` は、現代のガベージコレクション環境では「気休め」と言われることもあるが、AutoCADのCOMインターフェースを扱う上では必須の儀式だ。特に `AcadApplication` や `AcadDatabase` のような重いオブジェクトは、スコープを抜ける前に必ず解放し、COMサーバーへの参照を明示的に断つこと。これが、長時間稼働する設計システムにおける安定性の礎となる。
—
最後に
コードを書くことは誰にでもできる。しかし、「将来発生しうる例外を、コードの構造そのもので殺す」ことが、シニアエンジニアの仕事だ。今回の「セーフ・セーブ」の実装は、その第一歩に過ぎない。
システムは生き物だ。常に保守性の高い、クリーンな設計を心がけてほしい。健闘を祈る。
