Access VBAの暗黒面を討つ:DoCmd.SetWarningsを捨て、CurrentDb.Executeで「真の制御」を手に入れろ
Access開発の現場で、初心者から中級者へステップアップする際に必ずぶつかる壁がある。「アクションクエリ実行時のあの忌々しい警告メッセージ」だ。
「テーブルを更新しますか?」「1件のレコードを削除しますか?」
開発者なら誰もが一度は `DoCmd.SetWarnings False` を使ってこれを消し去ろうとするだろう。だが、断言する。その書き方は、プロの現場では「悪」だ。 なぜなら、それは「例外を握りつぶすリスク」と「アプリケーション全体の安定性」を天秤にかけ、自ら崩壊への道を歩んでいることに他ならないからだ。
今日は、なぜ `DoCmd.SetWarnings` が危険なのか、そして我々エンジニアがなぜ `CurrentDb.Execute` を選ぶのか。その極限の知見を授ける。
—
1. なぜ「DoCmd.SetWarnings」は禁じ手なのか
`DoCmd.SetWarnings False` は、AccessのUIに対するグローバルな設定を変更する。これが恐ろしい理由は以下の3点に集約される。
1. エラーハンドリングの崩壊: もし `False` に設定した直後に予期せぬエラーでコードが停止した場合、Accessの警告機能は「オフのまま」になる。ユーザーは「削除の確認」も「エラー通知」も受け取れないまま、データが破損する惨状をただ眺めることになる。
2. パフォーマンスの鈍重さ: `DoCmd` はUI(画面)を前提とした命令だ。バックグラウンドでのデータ処理にUIの制約を持ち込むのは、スポーツカーのエンジンを軽トラックに載せるようなものだ。
3. 可読性と保守性の欠如: `False` にしたなら、必ず `True` に戻す必要がある。この「セット」を忘れるバグは、修正工数の無駄でしかない。
—
2. CurrentDb.Executeによる「静かなる実行」
`CurrentDb.Execute` は、DAO(Data Access Objects)の直系メソッドだ。UIを一切介さないため、最初から警告メッセージなどは表示されない。さらに、実行結果をプログラム側で制御できるという強力な利点がある。
実践:堅牢なSQL実行用プロシージャ
実務でそのまま使える、エラーハンドリングを完備したテンプレートを提示する。これを標準モジュールに置いておけば、もう警告ダイアログに悩まされることはない。
‘ —————————————————————————
‘ 関数名 : ExecuteSqlSafe
‘ 概要 : エラーハンドリングを内包したアクションクエリ実行用汎用関数
‘ 引数 : sqlString (実行するSQL文)
‘ —————————————————————————
Public Sub ExecuteSqlSafe(ByVal sqlString As String)
Dim db As DAO.Database
‘ CurrentDbをオブジェクト変数に格納(パフォーマンス向上の鉄則)
Set db = CurrentDb
On Error GoTo ErrorHandler
‘ dbFailOnError オプションが「魂」。
‘ これを指定することで、エラー発生時にロールバックし、
‘ かつVBA側でエラーを捕捉可能にする。
db.Execute sqlString, dbFailOnError
Exit Sub
ErrorHandler:
‘ 開発者として、エラーログを記録するなり、ユーザーへ適切に通知する
MsgBox “データの更新中にエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“内容: ” & Err.Description, vbCritical, “システムエラー”
‘ ここで必要に応じてロールバックやトランザクションの処理を行う
End Sub
—
3. この設計が「プロ」である理由
① `dbFailOnError` の重要性
`db.Execute` の第二引数に `dbFailOnError` を指定しないのは、ブレーキのない車で高速道路を走るのと同じだ。この定数は、クエリが1件でも失敗した際に即座にVBA側の `ErrorHandler` を発火させる。これにより、データの不整合(部分的な更新)を未然に防げる。
② `CurrentDb` のキャッシュ
`CurrentDb` は呼び出すたびに新しいインスタンスを生成する可能性がある。大規模なシステムでは、`Set db = CurrentDb` と変数に格納してから使い回すのが、メモリ負荷を軽減する「アーキテクトの作法」だ。
③ トランザクションとの親和性
`CurrentDb.Execute` を使う最大のメリットは、`db.BeginTrans` や `db.CommitTrans` と組み合わせて、「原子性(Atomicity)」を保証できる点にある。複数のテーブルを更新する複雑な処理も、これなら安全に実装できる。
—
最後に:コードは「意思」を語る
あなたが書くコードは、あなた自身のエンジニアとしての品格を表す。
`DoCmd.SetWarnings` という「場当たり的な処置」で満足するのではなく、`CurrentDb.Execute` と `dbFailOnError` を使いこなすことで、「何が起きてもシステムを壊さない」という強固な意志をコードに刻み込んでほしい。
業務自動化は、単に作業を減らすことではない。運用者が安心して夜を眠れるような、堅牢な基盤を作ることだ。
さあ、今すぐ既存のプロジェクトのコードを見直してほしい。警告ダイアログという「悪」を排除し、真にメンテナンス性の高いシステムへと進化させよう。それができるのは、この技術を理解したあなただけだ。
