【テクニカル・上級編】フォームの「Dirty」プロパティを監視して未保存データの破棄を制御する – Access VBA解析バイブル

スポンサーリンク

フォームの「Dirty」を掌握せよ:Accessデータ整合性の防波堤を構築する

Access開発の現場で、ジュニアなエンジニアが最も見落としがちなのが「フォームの暗黙的な保存」という地雷だ。`Dirty`プロパティは、単なる編集フラグではない。これは、データベースの整合性を守るための「最後の防波堤」である。

今回は、この`Dirty`プロパティを制御し、予期せぬデータ永続化を封じ込めるための、シニア層にこそ知ってほしい「極限の制御アーキテクチャ」を伝授する。

1. なぜ「Dirty」を監視しなければならないのか

Accessのフォームは、フォーカスが移動するだけで、あるいは閉じるボタンが押されるだけで、驚くほど簡単にデータをコミットする。トランザクションの概念が希薄なレガシーなAccess環境において、この「自動保存」は致命的な不整合を生む。

ユーザーの誤操作や、バックグラウンドでのAPI通信中に発生する競合。これらを未然に防ぐには、「アプリケーションの制御下でしか保存を許さない」という設計思想が必要だ。

2. 実装:Dirtyフラグを利用した排他制御パターン

単に「保存するか確認する」だけでは甘い。メモリ上のバッファをクリアし、レコードセットの状態を明示的にロールバックさせる必要がある。

‘ フォームのBeforeUpdateイベントで制御をフックする
Private Sub Form_BeforeUpdate(Cancel As Integer)
‘ ユーザーの意志を確認
If Me.Dirty Then
If MsgBox(“変更を保存しますか?”, vbQuestion + vbYesNo) = vbNo Then
‘ ここが肝:Undoメソッドはバッファをクリアし、DirtyをFalseに戻す
Me.Undo
‘ キャンセルを伝達し、更新を無効化する
Cancel = True
End If
End If
End Sub

【上級者向け:システム間連携時の注意点】

API経由で外部システムと同期を取る場合、`Dirty`が`True`のままフォームを閉じると、不完全なデータがDBに書き込まれる。これを防ぐには、`Form_Unload`イベントにて、`If Me.Dirty Then Me.Undo`を強制実行させるのが鉄則だ。

3. メモリ管理と「オブジェクトの寿命」

多くのエンジニアが`CurrentDb`を乱用しているが、これはメモリリークの温床だ。特に自動化されたプロセスでは、DAOオブジェクトの解放を怠ると、Accessのプロセスがメモリに居座り、次の同期処理を阻害する。

以下は、Dirty監視と併用すべき「メモリに優しい」DAO利用のテンプレートだ。

‘ 不必要なオブジェクトの生成を避け、スコープを最小化する
Public Sub SafeUpdateOperation()
Dim db As DAO.Database
Dim rs As DAO.Recordset

‘ CurrentDbは呼び出すたびに参照を生成するため、変数にキャッシュする
Set db = CurrentDb

On Error GoTo Cleanup
Set rs = db.OpenRecordset(“T_TargetTable”, dbOpenDynaset)

‘ — 処理ロジック —

Cleanup:
‘ 明示的な解放こそが、安定したシステムの要
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
If Not db Is Nothing Then Set db = Nothing
End Sub

4. 極限の知見:Windows APIによる「閉じる」の遮断

ユーザーがフォームの右上の「×」ボタンを押すと、`BeforeUpdate`をすり抜けて保存されるケースがある。これを物理的に遮断するには、Windows APIを活用してフォームのシステムメニューを制御するしかない。

‘ システムメニューを無効化するAPI宣言
Private Declare PtrSafe Function GetSystemMenu Lib “user32” (ByVal hwnd As LongPtr, ByVal bRevert As Long) As LongPtr
Private Declare PtrSafe Function DeleteMenu Lib “user32” (ByVal hMenu As LongPtr, ByVal nPosition As Long, ByVal wFlags As Long) As Long

‘ フォームロード時に実行し、×ボタンを無効化する
Private Sub Form_Load()
Dim hMenu As LongPtr
hMenu = GetSystemMenu(Me.hwnd, 0)
‘ 閉じるボタン(SC_CLOSE)を削除
DeleteMenu hMenu, &HF060, &H0
End Sub

最後に:職人のアーキテクチャを目指せ

Access VBAは、一見するとGUI主体の簡易ツールに見える。しかし、その内部構造を理解し、`Dirty`プロパティによるトランザクション管理、DAOのメモリ解放、そしてWindows APIによる低レイヤーの制御を組み合わせれば、堅牢なエンタープライズシステムを構築することが可能だ。

「便利だから使う」のではない。「制御し尽くすためにVBAを使う」
この意識が、君のシステムを「レガシーな負債」から「信頼の基盤」へと昇華させる。

コードは嘘をつかない。君が書いた一行が、数年後の誰かの運命を救うことを忘れないでほしい。

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