こんにちは!Access VBAの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、自分の手でロジックを組み立てる楽しさに目覚め始めたあなたへ。
今日は、Access VBAにおける「オブジェクトモデルの本質」と、フォーム開発で絶対に知っておくべき`ActiveControl`プロパティを武器にして、どのフォームからでも使い回せる「汎用的な入力チェック関数」の作り方を解説します。
ここをクリアすれば、Access VBAの基本はバッチリですよ。ぜひ最後までついてきてくださいね!
—
1. なぜ「入力チェック」のコードが重複してしまうのか?
Accessでフォームを作っているとき、こんな絶望感を味わったことはありませんか?
- 「社員マスタフォーム」の名前欄が空っぽじゃないかチェックするコードを書いた。
- 次は「顧客マスタフォーム」の会社名欄のチェック…あれ、さっきとほぼ同じコードをまた書いているぞ?
- フォームが10個あったら、似たようなバリデーションコードを何十回もコピペする羽目に……。
初学者が最初に陥る罠が、「どのコントロールをチェックしているか」をコードに直接書き込んでしまうことです。
`Me.txtEmployeeName.Value` のように特定の名前を指定してしまうと、他のフォームや他のテキストボックスで使えなくなってしまいます。
ここで登場するのが、今回マスターする `Screen.ActiveControl`(またはフォームの `ActiveControl`) です。
—
2. 「ActiveControl」とは何か?(オブジェクトの現在地を知る)
`ActiveControl` とは、文字通り「今、ユーザーがフォーカス(選択)しているコントロール」を指し示すポインタのようなものです。
イメージしてみてください。
あなたが警察官で、目の前でスピード違反をした車を止めるとします。「赤色のトヨタのプリウス、ナンバー1234のドライバー!」と特定しなくても、「今、目の前で動いている車」を捕まえれば、違反キップ(バリデーション)を切れますよね。
VBAでも同じです。
「今、ユーザーが入力しているそのコントロールは何のデータ型か? 値は入っているか?」を、`ActiveControl` を通じて動的に(その場で)取得すれば、1つの関数をすべてのフォームで使い回すことができるのです。
—
3. 実装! どのフォームからも呼び出せる「汎用バリデーション関数」
それでは、標準モジュールに「値が入っているか」「文字数がオーバーしていないか」を判定する汎用関数を書いてみましょう。
手順1:標準モジュールに共通関数を置く
VBAの編集画面(VBE)で「挿入」>「標準モジュール」を選択し、以下のコードを貼り付けてください。
Option Compare Database
Option Explicit
‘ =================================================================
‘ 汎用入力チェック関数(必須入力 & 最大文字数チェック)
‘ 呼び出し元のコントロールを ActiveControl で動的に判定する
‘ =================================================================
Public Function ValidateActiveControl(Optional MaxLength As Long = 0) As Boolean
Dim ctl As Control
‘ エラーハンドリング:フォーカスを持つコントロールがない場合を考慮
On Error GoTo ErrorHandler
‘ 現在アクティブなコントロールを取得
Set ctl = Screen.ActiveControl
‘ — 1. 必須チェック(値がNullまたは長さ0の文字列の場合) —
If IsNull(ctl.Value) Or ctl.Value = “” Then
MsgBox ctl.Tag & ” は必須入力です。”, vbExclamation, “入力エラー”
ctl.SetFocus ‘ 問題のコントロールにフォーカスを戻す
ValidateActiveControl = False
Exit Function
End If
‘ — 2. 文字数チェック(MaxLengthが指定されている場合) —
If MaxLength > 0 Then
If Len(ctl.Value) > MaxLength & Then
MsgBox ctl.Tag & ” は ” & MaxLength & ” 文字以内で入力してください。” & vbCrLf & _
“(現在: ” & Len(ctl.Value) & ” 文字)”, vbExclamation, “文字数オーバー”
ctl.SetFocus
ValidateActiveControl = False
Exit Function
End If
End If
‘ すべてのチェックをクリア
ValidateActiveControl = True
Exit Function
ErrorHandler:
‘ コントロールが値を持たない型(ボタンなど)だった場合の対策
MsgBox “チェックできないオブジェクトが選択されています。”, vbCritical, “システムエラー”
ValidateActiveControl = False
End Function
このコードのスマートなポイント
1. `Screen.ActiveControl` の活用
どのフォームの、どのテキストボックスから呼ばれても、「今フォーカスがある場所」を自動で特定します。
2. `ctl.Tag`(コントロールのタグ)の利用
メッセージボックスに「`txt_name` は必須です」と出すのは無機質で冷たいですよね。コントロールの「プロパティシート > その他 > タグ」プロパティに「顧客名」と書いておけば、`ctl.Tag` がそれを拾って「顧客名は必須入力です。」と人間味のあるエラーを返してくれます。
—
4. フォーム側のコード(驚くほどシンプルに)
さて、この魔法の関数を実際のフォームの「保存ボタン」や「次へボタン」のクリックイベントでどう使うか見てみましょう。
Private Sub btnSave_Click()
‘ フォーカスをテキストボックスからボタンに移す前に、
‘ チェックしたいコントロールにフォーカスがある状態、あるいは
‘ ロジック内で判定させます。
‘ 例:社員名テキストボックスのバリデーション(最大20文字)
Me.txtEmployeeName.SetFocus
If ValidateActiveControl(20) = False Then Exit Sub
‘ 例:メールアドレスのバリデーション(最大100文字)
Me.txtEmail.SetFocus
If ValidateActiveControl(100) = False Then Exit Sub
‘ すべてのチェックを通過した場合の処理
MsgBox “すべての入力チェックをクリアしました!データを保存します。”, vbInformation
‘ DoCmd.RunCommand acCmdSaveRecord などの処理へ…
End Sub
どうですか? フォーム側には「何文字までOKか」というルールを渡すだけで、エラーメッセージの出し分けやフォーカスの制御はすべて標準モジュールの関数が裏でやってくれます。これが「保守性の高いコード」の姿です。
—
5. 初学者が絶対にハマる「罠」と回避策
ここで、現場でよくあるエラーと、その回避策を先輩からこっそり伝授しておきます。
罠①:「実行時エラー ‘2475’: このアクションを実行するには、フォームまたはレポートがアクティブである必要があります」
- 原因: フォームが開いていない状態や、コントロールにフォーカスがない状態で `Screen.ActiveControl` を呼び出してしまったときに出ます。
- 対策: 必ず関数を呼び出す前に、対象のコントロールに `.SetFocus` でフォーカスを当ててから関数を実行する癖をつけましょう。
罠②:データ型によるエラー
- 原因: チェック対象がテキストボックスではなく、チェックボックス(Boolean)やコンボボックス(Longなど)だった場合、単純な `Len()` 関数や `””` 判定で予期せぬ動作をすることがあります。
- 対策: 本格的なシステムを作る際は、`ctl.ControlType` を判定条件に組み込み、「テキストボックスの時だけ文字数を見る」といった分岐を入れると、さらに金庫の鍵のように堅牢なコードになります。
—
まとめ
今回は、Access VBAのオブジェクトモデルの醍醐味である `ActiveControl` を使った、汎用入力チェック関数の作り方を解説しました。
- 特定のコントロール名に依存しないコードを書くこと
- `Screen.ActiveControl` で「今ここ」のオブジェクトを操作すること
- `ctl.Tag` を活用してユーザーフレンドリーなメッセージを作ること
この3つをマスターすれば、あなたの書くAccess VBAは、マクロの域を完全に脱却し、プロのエンジニアが作る「モジュール設計されたシステム」へと生まれ変わります。
ぜひ、あなたの開発するAccessデータベースに組み込んで、その快適さを体感してみてくださいね。それでは、また次の知見でお会いしましょう!
