「応答なし」の恐怖を克服する。ADOのタイムアウト制御で、プロのAccessアプリへ昇華させる技術
こんにちは。現場で数々のシステム崩壊と、そこからの復旧を繰り返してきたエンジニアです。
Access VBAを学んでいると、必ずと言っていいほど直面する「壁」があります。それは、「ネットワークが不安定になった瞬間、Accessが真っ白になって『応答なし』になり、強制終了するしかなくなる」という現象です。
マクロの記録から一歩踏み出し、SQL Serverなどの外部データベースへADO(ActiveX Data Objects)を使って接続しようとしているあなた。もし、今のコードが「接続して、実行して、閉じる」という単純な流れだけなら、この「フリーズの罠」に片足を突っ込んでいます。
今日は、中級者への登竜門とも言える「ConnectionTimeout」と「CommandTimeout」の使い分けについて、その本質を伝授しましょう。ここをマスターすれば、あなたの作るツールは「動くだけの道具」から「信頼されるシステム」へと進化します。
1. なぜ、Accessは「固まる」のか?(DAOとADOの決定的な違い)
まず、アーキテクチャの視点から整理しましょう。Accessにはデータを扱うための窓口が主に2つあります。
| 特徴 | DAO (Data Access Objects) | ADO (ActiveX Data Objects) |
|---|---|---|
| 主な役割 | Access内部(ローカル)の操作に特化 | 外部DB(SQL Server等)との通信に特化 |
| スピード | Access内では最速 | ネットワーク越しなので通信コストがかかる |
| タイムアウト | 主にファイルアクセスの問題 | ネットワークの応答待ちが最大のリスク |
あなたが外部のデータベースに接続しようとしているなら、使うのはADOです。
ADOは「ネットワークという不確実な道」を通って、遠くのサーバーに会いに行きます。しかし、もしその道が工事中(ネットワーク断線)だったり、相手のサーバーがダウンしていたりしたらどうなるでしょうか?
デフォルトの設定のままだと、VBAは「相手が返事をしてくれるまで、永遠に待ち続ける」という挙動をすることがあります。これが、画面が固まる「応答なし」の正体です。
2. 二つの「タイムアウト」を正しく理解する
「フリーズを防ぐ」ためには、「いつまで待つか」という限界値を決めておく必要があります。ADOには、役割の異なる2つのタイムアウト設定が存在します。ここを混同するのが、初心者が陥る最大のミスです。
① ConnectionTimeout(接続のタイムアウト)
- 役割: 「サーバーの門を叩いて、中に入れてもらえるまで」の制限時間。
- いつ使うか: `Connection.Open` を実行する時。
- 例: サーバーが落ちている場合、ここで設定した秒数で「接続失敗」のエラーを返してくれます。
② CommandTimeout(コマンドのタイムアウト)
- 役割: 「門を抜けて中に入った後、指示(SQL)を出して、結果が返ってくるまで」の制限時間。
- いつ使うか: `Connection.Execute` や `Recordset.Open` を実行する時。
- 例: データ量が膨大なクエリを実行中、ネットワークが低速で結果がなかなか来ない場合、ここで制限をかけます。
図解イメージ:
> [ あなたのPC ] — (1. ConnectionTimeout) —> [ サーバーの門 ]
> [ あなたのPC ] — (2. CommandTimeout) ——–> [ サーバーの中身(データ) ]
3. 実践:フリーズを回避する「鉄壁の接続コード」
では、実際にどのように実装すべきか。現場でそのまま使える、堅牢なコードパターンを示します。
Option Explicit
''' <summary>
''' 外部データベースへ安全に接続し、データを取得するサンプル
''' </summary>
Public Sub SafeExternalConnection()
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strConn As String
Dim strSQL As String
' 接続文字列(環境に合わせて書き換えてください)
strConn = "Provider=SQLOLEDB;Data Source=YourServerName;Initial Catalog=YourDBName;Integrated Security=SSPI;"
' 実行したいSQL
strSQL = "SELECT * FROM LargeTable" ' 負荷の高いクエリを想定
' エラーハンドリングの開始
On Error GoTo ErrorHandler
' 1. オブジェクトの生成
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
' ---------------------------------------------------------
' 【重要】タイムアウトの設定
' ---------------------------------------------------------
' 接続タイムアウト:サーバーに繋がらない場合、15秒で諦める
conn.ConnectionTimeout = 15
' コマンドタイムアウト:クエリ実行に30秒以上かかったら諦める
' ※0に設定すると「無制限」になり、フリーズの原因になるので注意!
conn.CommandTimeout = 30
' 2. 接続の試行
Debug.Print "接続を試みています..."
conn.Open strConn
Debug.Print "接続成功!"
' 3. クエリの実行
Debug.Print "データを取得中..."
rs.Open strSQL, conn, adOpenStatic, adLockReadOnly
' 結果の表示(例)
If Not rs.EOF Then
MsgBox "データの取得に成功しました。", vbInformation
End If
' --- 後処理 ---
CleanUp:
On Error Resume Next
If Not rs Is Nothing Then
If rs.State = adStateOpen Then rs.Close
Set rs = Nothing
End If
If Not conn Is Nothing Then
If conn.State = adStateOpen Then conn.Close
Set conn = Nothing
End If
Exit Sub
' --- エラーハンドリング ---
ErrorHandler:
' ネットワーク切断やタイムアウトが発生した場合、ここへ飛んでくる
Select Case Err.Number
Case -2147467259 ' ADOの一般的な実行時エラー(タイムアウト含む)
MsgBox "通信エラーが発生しました。ネットワーク接続を確認してください。" & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical, "接続タイムアウト"
Case Else
MsgBox "予期せぬエラーが発生しました。" & vbCrLf & _
"番号: " & Err.Number & vbCrLf & _
"内容: " & Err.Description, vbCritical, "エラー"
End Select
Resume CleanUp
End Sub
4. 伝説のアーキテクトからのアドバイス
このコードを使いこなすために、以下の3点を心に刻んでおいてください。
1. 「0(無制限)」の誘惑に負けない
`CommandTimeout` を `0` に設定すると、理論上は「いつまでも待ち続ける」ことになります。巨大な集計処理を行う際に便利に見えますが、ネットワークが瞬断した瞬間に、あなたのアプリは「応答なし」の闇に落ちます。必ず適切な秒数を指定してください。
2. エラーハンドリングは「親切心」である
エラーが発生したとき、ユーザーに何が起きたか伝えないのは、暗闇の中で目隠しをして走らせるのと同じです。「サーバーが応答しません」「ネットを確認してください」と具体的に伝える。これが、プロのツールとしての「おもてなし」です。
3. オブジェクトのライフサイクルを意識する
コード内の `CleanUp` セクションを見てください。エラーが起きても起きなくても、必ず `Close` し、`Nothing` を代入してメモリを解放する。これを怠ると、Accessがメモリを食いつぶし、最終的にPC全体の動作を重くする原因になります。
まとめ:ここをクリアすれば、Access VBAの基本はバッチリですよ
「接続して、動けばいい」という段階を卒業し、「もしもの時(ネットワーク断絶)にどう振る舞うか」を設計する。これこそが、エンジニアリングの醍醐味です。
- ConnectionTimeout で、門前払いをスマートに。
- CommandTimeout で、長すぎる待ち時間をスマートに。
- ErrorHandler で、ユーザーを不安にさせない。
この3点を守るだけで、あなたの作成するAccessアプリケーションの信頼性は劇的に向上します。一歩ずつ、着実に「強いコード」を書いていきましょう。応援していますよ!
