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

スポンサーリンク

フォームの「イベント地獄」を卒業せよ:ActiveControlを活用した汎用バリデーション設計の極意

Access開発において、最も生産性を低下させる要因は「コントロール単位でのコード記述」だ。
テキストボックスを10個追加するたびに、同じような「未入力チェック」や「文字数制限」のコードを`BeforeUpdate`にコピペしているようでは、プロフェッショナルとは呼べない。

メンテナンスのたびに10箇所のコードを修正し、漏れが発生してバグを生む。そんな泥沼から脱却し、「フォームのイベントを中央集権的に制御する」アーキテクチャを伝授する。

なぜ「個別記述」が地獄への入り口なのか

初心者は、各コントロールのイベントに直接ロジックを書きたがる。しかし、これは以下の理由で「負債」となる。

1. 疎結合の欠如: UI(フォーム)とロジック(バリデーション)が密結合になり、仕様変更時に修正箇所を特定できない。
2. 冗長なコード: 同じロジックが各所に分散し、DRY原則(Don’t Repeat Yourself)に反する。
3. 拡張性の欠如: 新しい入力項目が増えるたび、イベントプロシージャを量産しなければならない。

我々エンジニアが目指すべきは、「コントロールの定義に基づいた動的なバリデーション」である。

ActiveControlを活用した「汎用バリデーション」の実装

Accessには、現在フォーカスがあるコントロールを指し示す強力なポインタ `Screen.ActiveControl` が存在する。これを利用し、各コントロールの `BeforeUpdate` イベントを、単なる「バリデーションエンジンへのトリガー」に格下げするのだ。

1. バリデーションエンジン(標準モジュール)

まずは、チェックロジックを一手に引き受ける司令塔を作成する。

‘ 標準モジュール: modValidator
Option Compare Database
Option Explicit

‘ 汎用バリデーション関数
‘ 引数:
‘ ctl: チェック対象のコントロール
‘ msg: エラー時に表示するメッセージ
Public Function ValidateRequired(ByRef ctl As Control, Optional ByVal msg As String = “必須項目です。”) As Boolean
‘ 値がNullまたは空文字ならエラー
If IsNull(ctl.Value) Or Trim(ctl.Value) = “” Then
MsgBox msg, vbExclamation, “入力エラー”
ctl.SetFocus
ValidateRequired = False ‘ 失敗
Exit Function
End If
ValidateRequired = True ‘ 成功
End Function

2. フォーム側での呼び出し(極限まで簡略化)

各コントロールの `BeforeUpdate` には、たった一行のコードしか書かせない。

‘ フォームの各コントロールのイベント
Private Sub txtUserName_BeforeUpdate(Cancel As Integer)
‘ 成功しなければイベントをキャンセル(更新を阻止)
If Not ValidateRequired(Screen.ActiveControl, “氏名を入力してください。”) Then
Cancel = True
End If
End Sub

プロダクション環境における「堅牢性」へのこだわり

上記のコードをさらに一段上のレベルへ昇華させるための、伝説的な知見を共有する。

注意点:CurrentDbとオブジェクトのライフサイクル

バリデーション内で `CurrentDb` を多用してテーブルと突き合わせを行う場合、注意が必要だ。`CurrentDb` は呼び出すたびに新しいインスタンスを生成する可能性がある。
パフォーマンスを重視するなら、`DAO.Database` 変数をモジュールレベルで保持し、必要に応じて `Set db = CurrentDb` を行うか、あるいは `OpenRecordset` の際も適切なキャッシュ戦略をとるべきだ。

「タグ」によるメタデータ駆動開発

さらに進んだ手法として、コントロールの「タグ(Tag)」プロパティにバリデーションルールを埋め込む方法がある。

‘ 例: タグに “Required;Numeric” と書いておけば、
‘ 関数側で “Required” を見つけて必須チェック、”Numeric” を見つけて数値チェックを行う
If InStr(ctl.Tag, “Required”) > 0 Then
‘ 必須チェック処理
End If

このように、コントロールのプロパティを「設定ファイル」として扱うことで、VBAのコードを一切書かずにチェックルールを追加・変更できるメタデータ駆動アーキテクチャが完成する。

結論:コードを書くほど、システムは脆弱になる

優れたエンジニアは、「いかにして書くコードを減らすか」に心血を注ぐ。
今回紹介した `ActiveControl` を起点としたバリデーションは、その第一歩だ。

  • 保守性: チェックロジックは `modValidator` に集約されている。
  • 拡張性: タグプロパティを活用すれば、UI側をいじるだけでルールを適用できる。
  • 堅牢性: `Cancel = True` による制御で、不正なデータがデータベースに流入するのを確実に防ぐ。

Access開発は、単なる「画面作成」ではない。オブジェクトモデルを掌握し、いかにシステムを構造化するかという「設計の戦い」だ。今日から、そのイベントプロシージャのコピペ作業を卒業し、真のアーキテクトとしての設計を開始してほしい。

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