【入門編】DoCmd.RunCommandによる「レコードの保存」強制とバリデーションのタイミング制御 – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの世界へようこそ。チーフアーキテクトの私です。

今回は、現場の desenvolvedor(開発者)たちが一度は頭を悩ませる「フォームのデータ保存とバリデーション(入力値検証)のタイミング」について、深く、そして優しく解説していきます。

「フォームに入力して他の場所に移動しようとしたら、よく分からないエラーメッセージが出る…」
「入力チェックを入れたはずなのに、意図しないタイミングでデータが保存されてしまう…」

そんなモヤモヤを抱えたことはありませんか?
ここをクリアすれば、あなたの作るAccessアプリは見違えるほど堅牢で、プロフェッショナルな動きをするようになりますよ。さあ、一緒に本質を掴んでいきましょう!

1. なぜ「保存のタイミング」でエンジニアは悩むのか?

Accessのフォームは、非常に優秀な「自動保存機能」を持っています。ユーザーがテキストボックスに文字を入力し、別のレコードやコントロールに移動した瞬間、Accessは裏側でこう判断します。

> 「おっ、データが変更されたな。じゃあ勝手にテーブルに保存しておいてあげるよ!」

この「おせっかいなほどの親切心」が、時として牙を向きます。
例えば、「未入力の必須項目がある状態で保存させたくない」というバリデーション(入力チェック)を組みたい場合、Accessが勝手に保存を走らせるタイミングと、あなたがチェックしたいタイミングがズレてしまうのです。

ここで発生するのが、いわゆる「保存の競合」や、ユーザーを混乱させる鬱陶しい標準エラーダイアログの嵐です。

2. 救世主 `DoCmd.RunCommand` による保存の「強制」

このコントロールしにくい保存のタイミングを、完全にあなたの手中に収めるための鍵が `DoCmd.RunCommand acCmdSaveRecord` です。

まずは、百聞は一見にしかず。実際のコードを見てみましょう。
例えば、フォーム上の「保存ボタン」がクリックされたときのイベントプロシージャを想定してください。

Private Sub btnSave_Click()
On Error GoTo ErrorHandler

‘ 1. 現在のフォーカスがあるコントロールの変更を確定させ、レコードの保存を強制する
If Me.Dirty Then
DoCmd.RunCommand acCmdSaveRecord
End If

MsgBox “データを正常に保存しました!”, vbInformation, “完了”
Exit Sub

ErrorHandler:
‘ 予期せぬエラーや、バリデーション規則に違反した際のトラップ
MsgBox “保存中にエラーが発生しました。入力内容を確認してください。” & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “保存エラー”
End Sub

このコードが持つ「圧倒的な意味」

1. `Me.Dirty` で変更を検知
レコードが変更されていない(汚れていない)無駄なタイミングでの保存処理をスキップし、パフォーマンスと無駄なエラーを防ぎます。
2. `DoCmd.RunCommand acCmdSaveRecord` で強制書き込み
Accessの「なんとなく保存するタイミング」を待ちません。「今、この瞬間にお前のデータをテーブルに叩き込め!」と、VBA側から明示的に保存命令(コミット)を発行します。

3. バリデーションのタイミングを完全に支配する

「保存の強制」がなぜ重要かというと、入力チェック(バリデーション)を走らせるベストなタイミングを作り出せるからです。

Accessには `Form_BeforeUpdate`(更新前処理)という、テーブルに書き込まれる直前に走るイベントがあります。ここで入力チェックを行うのが王道ですが、`DoCmd.RunCommand acCmdSaveRecord` をボタンに仕込むことで、チェックの主導権を完全に握ることができます。

以下の実戦的なパターンを見てみましょう。

Private Sub Form_BeforeUpdate(Cancel As Integer)
‘ 【バリデーションの要塞】

‘ 1. 顧客名が未入力の場合のチェック
If IsNull(Me.txtCustomerName) Or Trim(Me.txtCustomerName) = “” Then
MsgBox “顧客名は必須入力です。”, vbExclamation, “入力漏れ”
Me.txtCustomerName.SetFocus ‘ 該当箇所にフォーカスを戻す
Cancel = True ‘ ★超重要:保存をキャンセルし、フォームにとどまる
Exit Sub
End If

‘ 2. 数量が0以下の場合のチェック
If Me.txtQuantity <= 0 Then MsgBox "数量は1以上を指定してください。", vbExclamation, "入力値不正" Me.txtQuantity.SetFocus Cancel = True ' ★保存を阻止 Exit Sub End If ' すべての関門を突破したら、データは無事にテーブルへ保存されます End Sub

ここがエンジニアの急所:`Cancel = True` の魔力

`Form_BeforeUpdate` イベント内で `Cancel = True` を指定すると、Accessはその保存処理をガッチリとストップさせ、ユーザーを元のレコード、かつエラーの起きたコントロールにとどめておくことができます。

先ほど紹介した `DoCmd.RunCommand acCmdSaveRecord` をボタンクリック時に実行すると、内部でこの `BeforeUpdate` が必ず呼び出されます。つまり、

> 「ボタンを押す」 = `RunCommand` = `BeforeUpdate` でチェック = OKなら安全に保存!

という、美しく隙のないデータ確定フローが完成するのです。

4. 初学者が陥りがちな「罠」と回避策

ここで、現場でよくある失敗パターンを一つ共有しておきます。

  • やってはいけないこと:

エラーメッセージを出した後に、`Me.Undo` を安易に使いすぎてユーザーの入力データをすべて消してしまうこと。「親切のつもりで全消去したら、入力したデータが消えた!」とユーザーからクレームの嵐になります。

  • 正しいアプローチ:

エラー時は `Cancel = True` のみに留め、ユーザーが入力した「間違ったデータ」は保持したまま、該当のテキストボックスに `.SetFocus` でカーソルを戻して修正を促すのが、UI/UXデザインの鉄則です。

まとめ:ここをクリアすれば、Access VBAは怖くない!

今回マスターした知見を整理しましょう。

1. Accessの「自動保存」に頼ると、エラーのコントロールが難しくなる。
2. `DoCmd.RunCommand acCmdSaveRecord` を使えば、意図したタイミングで確実にデータを「保存(コミット)」できる。
3. `BeforeUpdate` イベントと `Cancel = True` を組み合わせることで、鉄壁のバリデーション防衛ラインが築ける。

「マクロの記録」や、ただ動くだけのコードから一歩抜け出し、オブジェクトのライフサイクルとイベントの順序をコントロールできるようになると、Access VBAを書くことが一気に楽しく、そして芸術的に感じられるようになります。

ここをクリアしたあなたなら、もう初級者ではありません。自信を持って、堅牢で美しいデータベースアプリを作り上げていってくださいね!それでは、次の現場でお会いしましょう。

タイトルとURLをコピーしました