AutoCAD VBAを掌握する極限の知見
第1回:堅牢な設計でリスクヘッジを完結させる — 編集前バックアップ自動化の極意
こんにちは。チーフアーキテクトの私だ。
AutoCAD VBAの実務における最大の悲劇をご存じか? それは、「上書き保存した瞬間に、欲しかった前のバージョンが永遠に消え去る」という現場の絶望だ。
「さっきの設計に戻したい」と思った時にはすでに遅く、Tempファイルを探しても影も形もない。手動で別名保存を忘れる人間を責めても、失われた時間は戻らない。
だからこそ、我々プログラマが立ち上がる必要がある。
今回は、図面が上書き保存(あるいは保存)されるタイミングをフックし、`AcadDocument.Name`と`Path`、そしてVBAの隠れた名脇役である`FileSystemObject (FSO)`を組み合わせて、「タイムスタンプ付き自動バックアップ」を裏側で完璧に実行する仕組みを授けよう。
初心者向けのテーマではあるが、実装するコードは「プロダクション・グレード(現場品質)」だ。甘いコードを書けば、AutoCADの安定性を揺るがすバグの温床となる。その違いをロジカルに解説していこう。
—
1. なぜ「生のVBA標準関数」だけでは危険なのか?
ファイル操作を行う際、多くの初心者は `Name` ステートメントや `FileCopy` 関数、`Kill` 関数といったVBAネイティブの機能に走りがちだ。しかし、実務の現場においてこれらはいくつかの重大なリスクをはらんでいる。
- パスの結合エラー: `Path` 末尾に `\`(バックスラッシュ)が付いているか否かで条件分岐を書く羽になり、コードが汚泥化する。
- エラーハンドリングの脆弱性: バックアップ先フォルダが存在しない場合、容姿端麗に「実行時エラー 76: パスが見つかりません」を吐いてマクロが沈没する。
- ファイル競合の無視: 同一秒内に複数回保存された場合のハンドリングがない。
これらを一撃で解決し、かつOSレベルの堅牢なファイル操作を実現するのが `Scripting.FileSystemObject` (FSO) だ。これを使わない手はない。
—
2. アーキテクチャの全体像
今回の自動化ロジックの要件は以下の通りだ。
1. トリガーの検知: ユーザーが図面を保存しようとした瞬間(正確には `ThisDrawing` のイベント)を捉える。
2. 未保存チェック: まだ一度も保存されていない(`Path` が空の)新規図面は、バックアップ対象外として安全にスキップする。
3. バックアップ先の動的生成: 元図面と同じ階層、あるいは指定した専用フォルダ内に `Backup` 階層を作り、そこに `[元のファイル名]_[YYYYMMDD_HHMMSS].[拡張子]` という命名規則でコピーを生成する。
4. トランザクションの保護: 万が一バックアップに失敗しても、元のCADの保存処理本体を絶対に阻害しないこと(ここがプロの設計だ)。
—
3. プロダクションコード実装
このコードは、AutoCADのプロジェクト内にある `ThisDrawing` (ThisDrawingモジュール) に直接貼り付ける必要がある。標準モジュールではない点に注意してほしい。
Option Explicit
‘ =================================================================ot
‘ módulos名: ThisDrawing (クラスモジュールとしての動作)
‘ 概要: 図面保存イベントをフックし、FSOを用いてタイムスタンプ付きバックアップを生成する
‘ =================================================================ot
Private Sub AcadDocument_SaveComplete(ByVal FileName As String)
‘ ————————————————————-
‘ 設計思想:
‘ SaveCompleteイベントを使用する。
‘ 保存処理が正常に完了した直後にバックアップ走査を行うことで、
‘ CAD本体の保存パフォーマンスを阻害せず、かつ「最新の保存済み状態」を確実に退避させる。
‘ ————————————————————-
On Error GoTo ErrorHandler
‘ 1. 未保存図面(パスが確定していない)のガード
If Me.Path = “” Then Exit Sub
‘ 2. FSOのインスタンス化(後期バインディングにより参照設定のミスを排除)
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 3. パスとファイル名の分解
Dim originalPath As String
Dim originalName As String
Dim baseName As String
Dim ext As String
originalPath = Me.Path ‘ 例: “C:\Projects\2023\Design”
originalName = Me.Name ‘ 例: “A-101.dwg”
baseName = fso.GetBaseName(originalName) ‘ 例: “A-101”
ext = fso.GetExtensionName(originalName) ‘ 例: “dwg”
‘ 4. バックアップ先ディレクトリの定義と自動生成
‘ ※ここでは元図面と同じ階層に “_AutoBackup” フォルダを作成する設計とする
Dim backupDir As String
backupDir = fso.BuildPath(originalPath, “_AutoBackup”)
If Not fso.FolderExists(backupDir) Then
fso.CreateFolder backupDir
End If
‘ 5. タイムスタンプの生成 (例: 20231025_143022)
Dim timeStamp As String
timeStamp = Format(Now, “yyyymmdd_hhnnss”)
‘ 6. バックアップファイルのフルパスを構築
Dim backupFileName As String
backupFileName = baseName & “_” & timeStamp & “.” & ext
Dim backupFullPath As String
backupFullPath = fso.BuildPath(backupDir, backupFileName)
‘ 7. ファイルのコピー実行(上書き許可: True)
Dim targetFullPath As String
targetFullPath = fso.BuildPath(originalPath, originalName)
fso.CopyFile targetFullPath, backupFullPath, True
‘ クリーンアップ
Set fso = Nothing
Exit Sub
ErrorHandler:
‘ 【重要】バックアップシステムの異常によって、ユーザーのCAD作業全体を止めてはならない。
‘ ログ出力やメッセージボックスにとどめ、エラーを完全に吸着(Suppress)する。
MsgBox “自動バックアップの作成中に軽度なエラーが発生しました。” & vbCrLf & _
“エラー内容: ” & Err.Description, vbExclamation, “バックアップ警告”
If Not fso Is Nothing Then Set fso = Nothing
End Sub
—
4. コードの深層解説:なぜこの構造なのか?
① `SaveComplete` イベントの選択
保存前(`BeginSave`)にバックアップを取るアプローチもあるが、これは悪手だ。保存処理そのものがディスク容量不足や排他制御で失敗した際、「保存されていないのにバックアップだけが増殖する」という不整合を生む。
`SaveComplete` を使うことで、「確実にディスクに書き込まれた正当なデータ」の世代管理が担保される。
② 後期バインディング(`CreateObject(“Scripting.FileSystemObject”)`)の採用
参照設定で `Microsoft Scripting Runtime` にチェックを入れる手法は、他人に配布するツールにおいて地獄を生む。PC環境によって参照切れを起こすためだ。
`CreateObject` による動的生成であれば、どのような環境のAutoCADであってもコードがクラッシュすることなく即座に動作する。実務ツールの鉄則である。
③ エラーの「完全な吸着(Suppress)」
ErrorHandler内で `Resume Next` や単なる `Exit Sub` で逃げるだけでなく、CADの根幹を止める致命的な例外を発生させない配慮をしている。バックアップ機能の不具合で、エンジニアが苦労して描いた図面の保存ステータスを狂わせるような本末転倒な設計は、プロとして絶対に避けるべきだ。
—
5. チーフからの実践的アドバイス:肥大化対策
このツールを導入すると、無限にバックアップが増えていく。SSDの容量を圧迫するか、将来的にファイルサーバーの管理部門からお叱りを受けることになるだろう。
本格的なプロダクション環境に昇華させるのであれば、FSOの `Folder.Files` コレクションを走査し、「バックアップ作成から7日以上経過したファイルを自動削除するロジック」を先の `SaveComplete` 内、あるいは専用の定期ルーチンとして組み込むべきだ。
コードを書くとは、ただ動くものを作ることではない。「未来の運用コストをゼロにする設計」を施すことだ。
今回のコードをベースに、君たちの現場の安全性に圧倒的な付加価値をもたらしてほしい。次回の知見にも期待せよ。
