AutoCAD VBAの極意:ネットワークの壁を越える「堅牢な保存」の実装術
「ローカル環境では完璧に動いたのに、共有サーバーに保存しようとした瞬間にマクロが止まってしまう……」
もしあなたが今、そんな壁にぶつかっているとしたら、おめでとうございます。あなたはプログラミングの「理想」から、実務という「現実」へと足を踏み入れた証拠です。
こんにちは。今日は、AutoCAD VBAの世界で中級者へとステップアップするために避けては通れない、「ファイルアクセスにおける不確実性」への対処法についてお話ししましょう。
マクロの記録から脱却し、現場で「本当に使える」ツールを作るための、魂のコードを伝授します。
1. なぜ「単純な保存」は失敗するのか?
AutoCADのVBAで、図面を保存するコードは非常にシンプルです。
ThisDrawing.SaveAs "Z:\Project\Drawing1.dwg"
しかし、実務環境(特にNASや共有サーバーを使用している現場)では、この一行が「エラー」を吐いて止まることが多々あります。なぜでしょうか?
犯人は「ファイルロック」と「ネットワークの揺らぎ」
原因はあなたのコードの書き間違いではありません。以下の外部要因による「一時的な拒絶」です。
1. ネットワークの遅延(Latency): サーバーへの書き込みリクエストが、一瞬だけネットワークの混雑でタイムアウトした。
2. アンチウイルスソフトの干渉: 保存された瞬間に、セキュリティソフトが「新しいファイルができたぞ!」と検知してスキャンを開始し、ファイルにロックをかけた。
3. 他のユーザーやプロセス: 誰かがそのファイルをプレビューしていたり、バックアップソフトが掴んでいたりした。
これらは「プログラムのバグ」ではなく、「OSやインフラの振る舞い」です。プロのエンジニアは、こうした「避けられないエラー」を前提に、「エラーが起きても、粘り強くやり直す仕組み」を組み込みます。
2. 戦略:リトライアル(再試行)ループの設計
エラーが起きたら即座に終了するのではなく、「数秒待ってから、もう一度試す」。これを数回繰り返すのが、堅牢なプログラムの鉄則です。
設計図はこうなります。
1. 保存を試みる
2. 成功したら、即座にループを抜ける
3. 失敗したら、エラー内容を確認する
4. 「一時的なエラー」なら、数秒待機(Sleep)してリトライ
5. 規定回数(例:5回)試してもダメなら、諦めてユーザーに通知する
ここで重要なのが、「待ち時間」です。一瞬でリトライしても、サーバーの状態が変わっていなければまた失敗します。2〜3秒の「間」を置くことが、成功への鍵となります。
3. 実装:プロフェッショナルな「堅牢保存」コード
それでは、実際に現場でそのまま使えるレベルのコードを見ていきましょう。
ここでは、Windowsの機能を呼び出す「API宣言」を使い、精密な待機処理を実現します。
Option Explicit
' Windowsの「Sleep」機能を使うための宣言(ミリ秒単位で待機させるため)
' 64bit版AutoCADを使用している場合は PtrSafe を追加します
If VBA7 Then
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
Else
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
End If
''' <summary>
''' ネットワーク遅延を考慮した、堅牢な「名前を付けて保存」関数
''' </summary>
''' <param name="fullPath">保存先のフルパス</param>
''' <returns>成功したらTrue、失敗したらFalse</returns>
Function RobustSaveAs(fullPath As String) As Boolean
Dim retryCount As Integer
Dim maxRetries As Integer
Dim waitTimeSeconds As Integer
Dim isSuccess As Boolean
' --- 設定値 ---
maxRetries = 5 ' 最大5回まで挑戦する
waitTimeSeconds = 3 ' 失敗時に3秒待機する
isSuccess = False
' --------------
For retryCount = 1 To maxRetries
' エラーハンドリングの開始
On Error Resume Next
' 保存実行
ThisDrawing.SaveAs fullPath
' エラーが発生したかチェック
If Err.Number = 0 Then
' 成功!
isSuccess = True
On Error GoTo 0 ' エラーハンドリングを通常に戻す
Exit For
Else
' 失敗した場合の処理
Debug.Print "Attempt " & retryCount & " failed. Error: " & Err.Description
' エラー内容をクリアして、次の試行へ
Err.Clear
On Error GoTo 0
' まだリトライ回数が残っているなら待機
If retryCount < maxRetries Then
' ここが重要!ユーザーに「今、頑張ってリトライ中だよ」と伝えるためのDoEvents
DoEvents
' 指定した秒数だけ待機 (Sleepはミリ秒指定なので 1000倍する)
Sleep (waitTimeSeconds * 1000)
End If
End If
Next retryCount
' 結果を返す
RobustSaveAs = isSuccess
End Function
''' <summary>
''' メイン処理:この関数を呼び出して使用します
''' </summary>
Sub MainSaveProcess()
Dim targetPath As String
targetPath = "Z:\Shared_Folder\Project_A\Design_v01.dwg" ' 保存したいパス
MsgBox "保存を開始します。ネットワーク状況により数十秒かかる場合があります。", vbInformation
If RobustSaveAs(targetPath) Then
MsgBox "保存に成功しました!", vbInformation
Else
MsgBox "【警告】保存に失敗しました。" & vbCrLf & _
"ネットワークを確認するか、ローカルに保存してください。", vbCritical
End If
End Sub
4. 伝説のアーキテクトが教える「ここが落とし穴!」
このコードを理解する上で、絶対に外してはいけない「3つの極意」を伝授します。ここをクリアすれば、あなたはもう初級者ではありません。
① `DoEvents` の魔法
コードの中に `DoEvents` という記述を入れましたね。これは非常に重要です。
VBAがループ処理(待ち時間)をしている間、AutoCAD自体が「応答なし」の状態になり、Windowsから「このプログラムはフリーズしています」と判断されてしまうことがあります。`DoEvents` を挟むことで、「OSに制御を一時的に戻す」ことができ、AutoCADの画面が固まるのを防ぎます。
② `On Error Resume Next` の使い所
「エラーを無視する」というこの命令は、使い方を間違えると悪魔の道具になります。
今回のコードのように、「特定の処理(SaveAs)の直前で使い、直後にエラーチェックを行う」という限定的な使い方こそが、プロの作法です。エラーを無視し続けるのではなく、「エラーが起きたことを検知するために、一時的に無視する」という感覚を持ってください。
③ `Sleep` による「戦略的撤退」
エラーが起きた瞬間に、猛スピードで再試行しても意味がありません。ネットワークの瞬断や、セキュリティソフトのスキャンが終わるには「時間」が必要です。あえて「何もしない時間を作る」こと。これが、自動化エンジニアに求められる「余裕」です。
最後に
いかがでしたか?
「エラーが起きるのは当たり前。だから、エラーが起きても大丈夫なように準備しておく」
この考え方こそが、プロフェッショナルな業務自動化の第一歩です。
今回紹介した `RobustSaveAs` 関数は、一度作ってしまえば、あなたのあらゆるプロジェクトで使い回せる「最強の武器」になります。ぜひ、自分のコードに組み込んで、その堅牢さを体感してみてください。
一歩ずつ、確実に。
AutoCAD VBAの深淵へ、共に進んでいきましょう。
