こんにちは! Access VBAの開発現場で、日々頭を悩ませていませんか?
「フォームに入力されたデータを綺麗に保存したい」
「ボタン一つでレコードを削除させたい」
「ユーザーが勝手にかけたフィルタをきれいに初期状態に戻したい」
こうした操作を、VBAのコードを一からガリガリ書いて実現しようとすると、意外とコードが長くなったり、予期せぬエラーに躓いたりするものですよね。「たったこれだけの処理なのに、なんでこんなに面倒なんだろう……」と、心が折れそうになった経験がある方も多いはずです。
でも、安心してください。
実はAccessには、私たちが自前で複雑なコードを書かなくても、Access本体が持っている「超優秀な標準機能」をVBAから呼び出すという、とっておきの裏技があるんです。
それが今回解説する `DoCmd.RunCommand` メソッドです。
ここをクリアすれば、あなたのAccess VBAのスキルは一段と洗練され、コード量もグッと減らせます。さあ、一緒に扉を開けていきましょう!
—
1. なぜ「自作コード」より「標準機能の呼び出し」なのか?
私たちがAccessでフォームを作るとき、Accessは最初から「レコードの保存」「削除」「検索」「フィルタリング」といった、データベースに必要な一通りの機能を標準備えています。
例えば、フォーム上のデータを保存する処理を考えてみましょう。
VBAだけで書こうとすると、データの妥当性チェック(バリデーション)から始まり、ダーティフラグの監視、エラーハンドリング……と、なかなかの大工事になります。
しかし、`DoCmd.RunCommand` を使えば、AccessのUI(画面)が裏側でやっている「あの保存ボタンを押したときの挙動」を、そのままVBAから実行できるのです。
- メリット1: コードが圧倒的にシンプルになり、バグが入り込む隙が減る。
- メリット2: Accessのネイティブな動きと完全に同期するため、予期せぬ不整合が起きにくい。
- メリット3: マクロの記録からステップアップしたいユーザーにとって、最も直感的で分かりやすい。
まさに、車輪の再発明をする必要はない、というわけですね。
—
2. `DoCmd.RunCommand` の基本構文と魔法の定数
使い方は驚くほどシンプルです。基本の形はこれだけ。
DoCmd.RunCommand acCmdCommandConstant
`acCmd…` で始まる部分は「定数(ビルトイン定数)」と呼ばれ、Accessが用意してくれた命令のリストのようなものです。これを指定するだけで、Accessがあらゆる標準作業を代行してくれます。
百聞は一見にしかず。現場でよく使う「三大お助けコマンド」を具体例とともに見ていきましょう。
—
3. 実践! 現場で即効性のある3つの自動化パターン
パターン①:確実にレコードを保存する(`acCmdSaveRecord`)
入力フォームで、別のコントロールにフォーカスを移したり、レコード移動をしたりする前に「現在の入力内容を確実に保存したい」という場面は多々あります。
Private Sub btnSave_Click()
On Error GoTo ErrorHandler
‘ 現在フォーカスがあるレコードの変更内容を強制的に保存する
DoCmd.RunCommand acCmdSaveRecord
MsgBox “データを正常に保存しました。”, vbInformation, “保存完了”
Exit Sub
ErrorHandler:
‘ 必須入力漏れなどで保存できなかった場合のエラー捕捉
MsgBox “保存に失敗しました。入力内容を確認してください。” & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “エラー”
End Sub
【ここがポイント】
`acCmdSaveRecord` は、いわば「画面上のフロッピーディスクのアイコン(保存ボタン)をプログラムからポチッと押した状態」を作ります。エラーハンドリングと組み合わせることで、入力漏れがある場合の制御もバッチリです。
—
パターン②:安全にレコードを削除する(`acCmdDeleteRecord`)
「この行、やっぱり消したいな」というときに、SQLの `DELETE` 文を組み立てるのはちょっと面倒だし、主キーの指定ミスなどが怖いですよね。これも標準機能に任せてしまいましょう。
Private Sub btnDelete_Click()
‘ ユーザーに削除確認のメッセージを挟むのが実務の鉄則
If MsgBox(“現在のレコードを削除しますか?この操作は元に戻せません。”, _
vbYesNo + vbQuestion, “削除の確認”) = vbYes Then
On Error GoTo ErrorHandler
‘ 現在選択されているレコードを削除する標準コマンド
DoCmd.RunCommand acCmdDeleteRecord
End If
Exit Sub
ErrorHandler:
MsgBox “削除できませんでした。関連データが存在する可能性があります。”, vbCritical, “エラー”
End Sub
【ここがポイント】
Access標準の削除ダイアログをトリガーするため、ユーザーにとっても馴染みのある挙動になります。ただし、誤削除を防ぐために、VBA側で必ず `MsgBox` によるワンクッション(確認)を入れるのがプロの作法です。
—
パターン③:フィルタをすっきり全解除する(`acCmdRemoveAllFilters`)
ユーザーがフォーム上であちこち絞り込み(フィルタ)を行った結果、「あれ?データが何も表示されなくなったんだけど……」とパニックになる姿、見たことありませんか? そんなときに「全フィルタ解除ボタン」を用意しておくと神がかって喜ばれます。
Private Sub btnResetFilter_Click()
On Error GoTo ErrorHandler
‘ フォームにかけられているすべてのフィルタを解除し、全件表示に戻す
DoCmd.RunCommand acCmdRemoveAllFilters
MsgBox “フィルタを解除し、全レコードを表示しました。”, vbInformation, “リセット完了”
Exit Sub
ErrorHandler:
‘ そもそもフィルタがかかっていない状態で実行された場合のエラー等を回避
MsgBox “フィルタの解除処理でエラーが発生しました。”, vbExclamation, “通知”
End Sub
【ここがポイント】
フォームの `FilterOn = False` と記述しても同じような効果は得られますが、`acCmdRemoveAllFilters` はAccessのUI(リボンやフィルターメニュー)と完全に連動するため、画面上の検索ボックスやフィルター表示も綺麗にクリアされます。
—
4. 初学者が必ずハマる!知っておくべき「実行時エラー」の罠
さて、ここまで読んで「よし、明日から全部これに置き換えよう!」と思ったあなた。少しだけ待ってください。
`DoCmd.RunCommand` を使う上で、絶対に知っておかなければならない「致命的な罠」が一つあります。
それは、「そのコマンドが実行できる状態(コンテキスト)に画面がないと、容赦なくエラーで止まる」ということです。
トラブル事例:
例えば、まだフォーム上に新規レコードを入力している最中で、まだ何もデータが確定していない(ダーティ状態ではない)のに `acCmdSaveRecord` を呼び出したり、そもそもレコードが1件もない空っぽのフォームで `acCmdDeleteRecord` を実行しようとすると、Accessは容赦なく実行時エラー(エラー番号:2046など)を吐き出して止まります。
対策:
1. エラーハンドリング (`On Error GoTo`) を必ず実装する
先ほどのサンプルコードでも入れているように、予期せぬ状態でコマンドが呼ばれてもプログラムが強制終了しないよう、防波堤を作っておきます。
2. ボタンの有効/無効をコントロールする
必要に応じて `Me.AllowDeletions` などのプロパティや、フォーカスの有無をチェックしてから実行するスマートな設計を心がけましょう。
—
5. おわりに:標準機能の波に乗ろう
今回は、`DoCmd.RunCommand` を使ったフォーム操作の自動化について解説しました。
Accessという強力なアプリケーションには、先人たちが何十年もかけて磨き上げてきた「便利機能」がこれでもかと詰まっています。VBAのコードで車輪の再発明をする前に、「これって、Accessの標準機能で代用できないだっけ?」と一歩引いて考えてみる。この視点を持てるかどうかが、初級者から一歩抜け出す大きな分かれ道です。
ここをクリアすれば、Access VBAの基本はもうバッチリです!
ぜひ明日の開発現場で、無駄なコードを削ぎ落とし、このスマートな標準機能の呼び出しを取り入れてみてくださいね。あなたのAccess開発が、より軽快で楽しいものになることを応援しています!
