【実務・中級編】DoCmd.OpenFormのWindowModeを駆使したダイアログ形式でのデータ入力設計と制御 – Access VBA解析バイブル

スポンサーリンク

Access VBAの「同期処理」を制する:DoCmd.OpenFormによる堅牢なダイアログ制御術

Access開発において、初心者が最初に躓くのが「画面遷移と処理の同期」だ。ボタンを押したらフォームが開き、入力が終わるのを待たずに次のコードが走り出し、結果として「空のデータ」や「不完全なレコード」を掴まされてエラーを吐く――。

そんなコードは、プロの現場では「負債」でしかない。

今日は、`DoCmd.OpenForm`の`WindowMode`引数を極め、呼び出し元の実行を完全に制御する「同期型データ入力アーキテクチャ」の設計思想を伝授する。

1. なぜ「非同期」的な設計がバグの温床となるのか

`DoCmd.OpenForm`をデフォルトで呼び出すと、Accessは「フォームを開く」という命令を投げた瞬間、次の行のコードを実行し始める。これが「非同期」の罠だ。

  • 何が起きるか: 入力フォームの準備ができる前に、呼び出し元の処理がテーブルへの書き込みや集計を始めてしまう。
  • 結果: ユーザーが入力する前にプログラムが終了する、あるいは排他制御エラーが発生する。

これを防ぐために`DoEvents`を連打するようなコードは、設計の敗北だ。我々が求めているのは、「ダイアログが閉じるまで、呼び出し元の実行コンテキストを一時停止させる」という、堅牢な同期制御である。

2. 究極の同期制御:acDialogの真価

`DoCmd.OpenForm`の第6引数`WindowMode`に`acDialog`を指定すると、Accessは魔法をかける。「そのフォームが閉じられるか、非表示になるまで、呼び出し元のコードの実行を中断(サスペンド)」するのだ。

これこそが、業務アプリにおける「確実な入力フロー」の要である。

実践:プロダクションコード例

以下は、メイン画面から「新規顧客登録フォーム」を呼び出し、入力が完了するまで待機し、結果をハンドリングする堅牢な実装パターンだ。

‘ 【呼び出し元のメイン処理】
Public Sub OpenCustomerEntry()
Dim frmName As String
frmName = “frm_CustomerEntry”

‘ 1. ダイアログモードで開く(ここでコード実行が一時停止する)
‘ acWindowNormalだと非同期になるため、必ずacDialogを指定する
DoCmd.OpenForm FormName:=frmName, _
View:=acNormal, _
WindowMode:=acDialog

‘ 2. フォームが閉じられた後、ここからコードが再開される
‘ フォームが「存在するか」を確認して、結果を取得する
If CurrentProject.AllForms(frmName).IsLoaded = False Then
‘ フォームが閉じられた後の後処理
Debug.Print “データ入力が完了しました。最新のリストを再描画します。”
Me.Requery
End If
End Sub

3. 呼び出される側の「正しい作法」

ダイアログとして開かれるフォーム側にも、守るべき鉄則がある。

1. 閉じるボタンの制御: 「閉じる」ボタンのクリック時に`DoCmd.Close acForm, Me.Name`を実行させる。
2. キャンセル時の判定: ユーザーが「キャンセル」を押したのか、「保存」したのかを判別するために、`OpenArgs`プロパティを活用せよ。

フォーム側の終了制御コード

‘ 【入力フォーム側の処理】
Private Sub btnSave_Click()
‘ ここでバリデーションと保存処理を実行
If Me.Dirty Then Me.Dirty = False

‘ 正常終了としてフォームを閉じる
DoCmd.Close acForm, Me.Name, acSaveNo
End Sub

Private Sub btnCancel_Click()
‘ キャンセル時はデータを破棄して閉じる
If Me.Dirty Then Me.Undo
DoCmd.Close acForm, Me.Name, acSaveNo
End Sub

4. 現場のアーキテクトが教える「3つの教訓」

① 排他制御を意識せよ

`acDialog`はUI上の停止を保証するが、データベースのロックは別物だ。もしそのフォームが特定のレコードを編集する場合、フォームを開く前に`If Me.Dirty Then Me.Dirty = False`で呼び出し元の変更を確定させておくこと。

② `OpenArgs`を使いこなせ

フォームを呼び出す際、`OpenArgs`引数にIDやモード(”New”や”Edit”)を渡せ。これにより、同じフォームを汎用的なダイアログとして使い回すことが可能になり、保守性が劇的に向上する。

③ エラーハンドリングを怠るな

同期処理は「呼び出し元」が待機するため、もし入力フォーム内で予期せぬエラーが発生して無限ループやハングアップが起きると、メイン処理まで巻き添えになる。`On Error GoTo`による例外処理は、ダイアログフォームの必須要件だ。

まとめ

Access VBAにおいて、`acDialog`は単なるオプション引数ではない。「ユーザーの操作」と「プログラムのロジック」を同期させるための唯一の架け橋だ。

コードは「動く」だけでなく「意図通りに制御される」ことが重要だ。あなたが書くコードが、次の開発者の足かせではなく、信頼性の高い基盤となることを期待している。さあ、今すぐコードをリファクタリングし、その不安定な非同期処理を撲滅せよ。

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