【実務・中級編】フォームの「OnCurrent」イベントで制御する、レコードごとの動的なUI制御 – Access VBA解析バイブル

スポンサーリンク

Access VBAを掌握する極限の知見:OnCurrentイベントによる動的UI制御の極意

こんにちは。開発プロジェクトの現場で、数々のAccess基幹システムを立て直してきたチーフアーキテクトの私だ。

Access VBAによるデスクトップアプリケーション開発において、最も頻繁に直面する課題の一つが「レコードごとの動的なUI制御」である。
「ステータスが『完了』のレコードは編集不可にしたい」「特定の種別の時だけ、このコンボボックスを活性化させたい」。こうした要件に対し、君はどのように実装しているだろうか?

「とりあえずボタンのクリック時や、各コントロールのフォーカス取得時に判定コードを入れている」――もしそう答えたなら、今すぐその設計は破棄してほしい。その場しのぎのイベント処理の乱立は、画面のちらつき(フリッカ)、予期せぬコントロールのロック漏れ、そして何より「データ不整合の温床」となる。

今回は、Accessのフォームが持つライフサイクルの核心「OnCurrent(カレント時)イベント」を完全に掌握し、堅牢で保守性の高いプロダクションコードを実装するための極意を伝授しよう。

1. なぜ「OnCurrent」なのか? オブジェクトモデルの本質を知る

まず大前提として、Accessのフォームは「単票ビュー」であれ「連続フォーム」であれ、レコードが移動するたびにコントロールの状態を再評価する必要があるという性質を持っている。

素人がやりがちな失敗は、フォームの「読み込み時(Open / Load)」や「更新前(BeforeUpdate)」だけに制御コードを記述することだ。これでは、ユーザーがレコード間を移動した瞬間、「前のレコードの状態が次のレコードに引き継がれてしまう(あるいはリセットされない)」という致命的なバグを引き起こす。

カレントレコード移動のライフサイクル

ユーザーがレコードを切り替えるとき、Access内部では以下の順序でイベントが発火する。

1. 現在のレコードの保存(必要に応じて `BeforeUpdate` / `AfterUpdate`)
2. `OnCurrent` イベントの発火

この `OnCurrent` こそが、「今まさにフォーカスが当たったレコードのデータを読み込み、UIの表情(ロック、色、表示・非表示)を動的に決定するための唯一無二のトリガー」なのだ。

2. 実務で直面する「3つの罠」と設計方針

プロダクション環境で動く堅牢なコードを書くためには、以下の3点を死守しなければならない。

罠①:連続フォームでの「全行一斉変化」の恐怖

単票フォームであれば直感的に実装できるが、連続フォームで `OnCurrent` を使う場合、1行のコントロールの設定を変更すると、画面上のすべてのレコードの同名コントロールが同じ状態に変化するというAccessの仕様(制限)にぶつかる。
したがって、連続フォームにおいては「視覚的な強調(背景色の変更など)」は諦め、「入力の可否(Lockedプロパティ)」の制御に絞るのがプロの選択だ。

罠②:Null値のハンドリング漏れ

新規レコード(レコード追加行)に移動した瞬間、背後のフィールド値は `Null` になる。ここで `Me.Status = “完了”` のような判定を素朴に行うと、型ミスマッチや実行時エラーの餌食になる。`Nz()` 関数や `IsNull()` による厳格なガードが必須である。

罠③:パフォーマンスの劣化

`OnCurrent` はレコードを移動するたびにミリ秒単位で高頻度に実行される。このイベント内で重いドメイン関数や不必要なDAO/ADOのレコードセット走査を行うと、画面の動作が途端にモッサリする。判定は必ず「現在のレコードのコントロール値(`Me.ControlName`)」のみで完結させること。

3. コピペで使えるプロダクションコード例

それでは、実際の現場でそのまま使える、洗練された実装パターンを提示しよう。

今回のシナリオ:

  • フォーム名:`frm_OrderManagement`
  • 制御対象:
  • `txt_ItemName` (商品名)
  • `cmb_Category` (カテゴリ)
  • `btn_Delete` (削除ボタン)
  • ビジネスルール:
  • ステータスフィールド(`status_code`)が 「99: 完了」 の場合、編集不可(ロック)にする。
  • 新規レコード(まだデータが確定していない行)の場合は、特別な案内色として背景色を淡い黄色にする。

Option Compare Database
Option Explicit

‘ =========================================================================
‘ イベント名 : Form_Current
‘ 概要 : レコードが移動するたびに発火し、UIの動的制御を行う
‘ =========================================================================
Private Sub Form_Current()
On Error GoTo ErrorHandler

‘ 1. 新規レコード判定と、ステータスによるロック制御を同時に実行
Call ApplyRecordStyle(Me.NewRecord, Nz(Me!status_code, 0))

Exit Sub

ErrorHandler:
‘ ログ出力や致命的なエラーハンドリングをここに記述
MsgBox “UIの動的制御中にエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”
End Sub

‘ =========================================================================
‘ 関数名 : ApplyRecordStyle
‘ 概要 : レコードの状態に応じたUIの活性/非活性、および背景色の制御
‘ 引数 : isNew (Boolean) – 新規レコードか否か
‘ : statusCode (Long) – 現在のステータスコード
‘ =========================================================================
Private Sub ApplyRecordStyle(ByVal isNew As Boolean, ByVal statusCode As Long)

Const COLOR_LOCKED As Long = 15790320 # ‘ 灰色 (RGB: 240,240,240)
Const COLOR_NORMAL As Long = 16777215 # ‘ 白 (RGB: 255,255,255)
Const COLOR_NEW_ROW As Long = 14934783 # ‘ 淡い黄色 (RGB: 255,255,224)

Dim isEditable As Boolean

‘ ビジネスロジックの定義:ステータスが 99(完了) なら編集不可
If statusCode = 99 Then
isEditable = False
Else
isEditable = True
End If

‘ — コントロールのロック制御 —
‘ 編集不可、または新規レコードであっても入力させたい項目以外を制御
Me!txt_ItemName.Locked = Not isEditable
Me!cmb_Category.Locked = Not isEditable

‘ 完了レコードは削除も禁止する
Me!btn_Delete.Enabled = isEditable

‘ — 視覚的フィードバック(背景色)の制御 —
‘ ※単票フォームを想定。連続フォームの場合は背景色変更は全行に波及するため注意
If isNew Then
‘ 新規行のスタイル
Me!txt_ItemName.BackColor = COLOR_NEW_ROW
Me!cmb_Category.BackColor = COLOR_NEW_ROW
ElseIf Not isEditable Then
‘ ロックされた(編集不可)行のスタイル
Me!txt_ItemName.BackColor = COLOR_LOCKED
Me!cmb_Category.BackColor = COLOR_LOCKED
Else
‘ 通常の編集可能行のスタイル
Me!txt_ItemName.BackColor = COLOR_NORMAL
Me!cmb_Category.BackColor = COLOR_NORMAL
End If

End Sub

4. この設計が「プロの仕事」である理由

上記のコードを見て、単なる「動くコード」以上の意図を感じ取っていただけただろうか。

1. 関数の単一責任の原則(Single Responsibility Principle)
`Form_Current` 自体には複雑な判定を書かず、エラーハンドリングのラッパーに徹している。実際の制御ロジックは `ApplyRecordStyle` というプライベートメソッドに完全にカプセル化しているため、将来的な要件変更(例:ステータスが「50: 承認済」の時も一部ロックするなど)が発生した際も、修正箇所が極めて明確になる。
2. マジックナンバーの排除と定数化
背景色のカラーコード(RGB値)を直接コードにベタ書きせず、`Const` として意味のある名前で定義している。これにより、保守性が劇的に向上する。
3. 安全な Null 対策
`Nz(Me!status_code, 0)` と記述することで、データベース側のフィールドが未入力(Null)であっても、型エラーを起こすことなく安全にデフォルト値(0)として評価できる。

5. まとめ

Access VBAにおけるUI制御は、一見すると泥臭いコーディングになりがちだ。しかし、オブジェクトのライフサイクル(特に `OnCurrent` イベント)の本質を理解し、堅牢な設計パターンを適用すれば、Webアプリケーションに負けない洗練された動的UIを構築することが可能だ。

「とりあえず動く」というアマチュアのコードから脱却し、メンテナンス性に優れた、プロフェッショナルなデータベースシステムを君の手で構築してほしい。

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