【実務・中級編】フォームのActiveControlプロパティを活用した、汎用的な入力チェック関数の構築 – Access VBA解析バイブル

スポンサーリンク

Access VBAを掌握せよ:ActiveControlで実現する「神」のバリデーション設計

現場のAccess開発で、フォームの入力チェックを個々のコントロールごとに`If`文で書くのは、今すぐやめるべき「負債の増殖行為」だ。

「氏名が空ではないか」「数値か」「桁数は正しいか」。これらをイベントごとに記述すれば、仕様変更のたびに地獄を見る。今回は、Accessの`Screen.ActiveControl`を核に据え、「どのコントロールから呼ばれても自己完結する」極めて堅牢な汎用バリデーション関数の設計論を伝授する。

なぜ「個別記述」が死を招くのか

初学者は、各テキストボックスの`BeforeUpdate`イベントに直接チェックロジックを書き込む。これがなぜ悪手なのか。

1. 保守性の欠如: 仕様変更(例:入力必須項目の追加)のたびに、全フォームの全イベントを修正する必要がある。
2. ロジックの散逸: バリデーションルールがコードの海に埋もれ、全体像が見えなくなる。
3. UIとロジックの密結合: フォームの構成が変わるたびにコードが壊れる。

プロのアーキテクチャでは、「UIは入力を受け取るだけ。判断は中央集権的なエンジンに委ねる」のが鉄則だ。

汎用バリデーションの設計戦略

`Screen.ActiveControl`を活用すれば、イベントの発生源(どのコントロールが今アクティブか)を動的に特定できる。これにより、個別のコントロール名をハードコーディングする必要がなくなる。

実装の勘所

  • Tagプロパティの活用: コントロールの`Tag`プロパティにバリデーションルール(例: `Req;Type=Num;Len=10`)を記述し、メタデータとして扱う。
  • イベントの共通化: `BeforeUpdate`で同一の共通関数を呼び出す。
  • キャンセル制御: `Cancel = True`を返すことで、不正なデータの入力を物理的に阻止する。

【実戦コード】堅牢な汎用バリデーションエンジン

標準モジュール(例: `modValidation`)に以下のコードを配置せよ。

Option Compare Database
Option Explicit

‘ —
‘ @description 汎用バリデーションエンジン
‘ @param ctl バリデーション対象のコントロール
‘ @param cancel 入力キャンセルを制御するフラグ
‘ —
Public Sub ValidateControl(ctl As Control, ByRef cancel As Integer)
Dim rules As Variant
Dim rule As Variant
Dim ctlValue As Variant

ctlValue = ctl.Value
rules = Split(Nz(ctl.Tag, “”), “;”)

For Each rule In rules
Select Case True
‘ 必須チェック
Case rule = “Req”
If IsNull(ctlValue) Or ctlValue = “” Then
MsgBox ctl.Name & “は必須入力です。”, vbExclamation
cancel = True: Exit Sub
End If

‘ 数値チェック
Case rule = “Type=Num”
If Not IsNumeric(ctlValue) Then
MsgBox “数値で入力してください。”, vbExclamation
cancel = True: Exit Sub
End If

‘ 桁数チェック (例: Len=10)
Case Left(rule, 4) = “Len=”
If Len(Nz(ctlValue, “”)) > Val(Mid(rule, 5)) Then
MsgBox “文字数が多すぎます。”, vbExclamation
cancel = True: Exit Sub
End If
End Select
Next rule
End Sub

フォーム側での呼び出し方

フォームの各コントロールの`BeforeUpdate`には、たった一行を書くだけだ。

Private Sub txtUserName_BeforeUpdate(Cancel As Integer)
‘ Screen.ActiveControl は「今まさに更新されようとしているコントロール」を指す
Call ValidateControl(Screen.ActiveControl, Cancel)
End Sub

現場で生き残るための「制約事項」と「知見」

この設計を導入するにあたり、以下の注意点を心に刻んでおいてほしい。

1. Tagプロパティは「契約」である: 開発者間でのタグの書き方(`Req`なのか`Required`なのか)を統一せよ。これをドキュメント化しないのは手抜きである。
2. マルチユーザー環境の考慮: `CurrentDb`を用いたDB連携を行う場合、このバリデーションは「フロントエンドでの検問」に過ぎない。テーブルレベルの入力規則(Validation Rule)や、ストアドプロシージャでの制約を二重の防壁として構築すること。
3. パフォーマンスへの影響: 今回のコードは軽量だが、複雑なマスタ参照を行う場合は、`DLookup`を乱発してはいけない。必要であれば、フォームロード時に必要なマスタ情報をメモリ上の`Dictionary`等にロードしておくのが、真のプロフェッショナルの振る舞いだ。

結論

コードを減らし、ロジックを統合する。それがAccess VBAにおける「保守性」の正体だ。
`ActiveControl`という強力な武器を正しく使いこなせば、あなたの作るツールは単なる「動くもの」から、堅牢で拡張性のある「システム」へと進化する。

さあ、今すぐコードを整理し、無駄な`If`の連鎖を断ち切る準備を始めろ。

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