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

スポンサーリンク

こんにちは! Access VBAの世界へようこそ。チーフアーキテクトの私です。

マクロの記録ボタンを押すだけの世界から一歩踏み出し、「自分の手でシステムをコントロールしたい」と願うあなたへ。今回は、実務の現場で必ずと言っていいほど直面する「フォームを使ったデータ入力の制御」について、極上の知見をお伝えします。

ここをクリアすれば、Access VBAの基本はバッチリですよ。優しく、そして本質的なところまでしっかりと解説していきますね。

1. なぜ「普通のフォームを開く」だけでは実務で使えないのか?

Accessでフォームを開くとき、よく使われるのが `DoCmd.OpenForm` という命令ですね。
例えば、以下のように書いたとします。

‘ フォームを開くだけのコード
DoCmd.OpenForm “F_CustomerInput”

これだけでフォームは開くのですが、実務の現場ではこれだけだと致命的な問題が起きます。
それは、「フォームを開いた瞬間、VBAのプログラム(呼び出し元)が後ろでどんどん先に進んでしまう」という点です。

ユーザーが「名前を入力している最中」にもかかわらず、プログラムは次の処理(データの集計や保存など)を勝手に進めてしまうため、未完成のデータを処理してエラーになってしまいます。

ここで登場するのが、今回の主役である `WindowMode`(ウィンドウモード) です。

2. 魔法の引数 `acDialog` で処理を「ピタッと止める」

`DoCmd.OpenForm` には、いくつかのオプション(引数)が用意されています。その中の `WindowMode` に `acDialog` という設定を指定すると、世界が一変します。

‘ モーダル(ダイアログ)形式でフォームを開く
DoCmd.OpenForm FormName:=”F_CustomerInput”, WindowMode:=acDialog

`acDialog` がもたらす2つの奇跡

1. 処理の一時停止(同期処理)
`acDialog` を指定して開いたフォームは、「ダイアログボックス」として振る舞います。このフォームが開いている間、呼び出し元のVBAコードは、ここでピタッと実行を一時停止します。ユーザーがフォームを閉じる(または非表示にする)まで、次の行には進みません。
2. 親フォームの操作ブロック(モーダル)
他のウィンドウをクリックして操作を邪魔されないよう、入力中のフォームが完了するまで他の操作をロックしてくれます。

これにより、「フォームを開く ➔ ユーザーが入力する ➔ 入力された値を受け取って次の処理に進む」という、王道の入力ダイアログパターンが完璧に実現できるのです。

3. 【実践】ダイアログフォーム設計の全貌

それでは、実際に現場で使える設計パターンのコードを見てみましょう。
今回は、「顧客追加ダイアログ」を呼び出し、入力された値を受け取る一連の流れを構築します。

ステップ①:呼び出し元のコード(VBA)

まずは、ボタンをクリックされたときなどに走る親側のコードです。

Public Sub ShowCustomerDialog()
Dim inputCustomerName As String

‘ 1. ダイアログとしてフォームを開く(ここでコードの実行が一時停止します!)
DoCmd.OpenForm FormName:=”F_CustomerInput”, _
View:=acNormal, _
WindowMode:=acDialog

‘ ==========================================================
‘ ※ ここから下のコードは、ユーザーがダイアログを閉じるまで実行されません!
‘ ==========================================================

‘ 2. フォームがまだ(メモリ上に)存在しているか確認する
If CurrentProject.AllForms(“F_CustomerInput”).IsLoaded = True Then

‘ 3. フォーム上のテキストボックスから値を取得する
inputCustomerName = Forms!F_CustomerInput!txtCustomerName.Value

‘ 4. フォームを完全に閉じてメモリから解放する
DoCmd.Close acForm, “F_CustomerInput”

‘ 5. 取得した値を使った処理を行う
MsgBox “以下の顧客を追加しました: ” & inputCustomerName, vbInformation

Else
‘ ユーザーがデータを保存せずに×ボタン等でキャンセルした場合
MsgBox “入力をキャンセルしました。”, vbExclamation
End If

End Sub

ステップ②:ダイアログ側のフォームのボタン設計

ダイアログ側(`F_CustomerInput`)には、通常「登録ボタン」と「キャンセルボタン」を配置します。

ここで重要なプロのテクニックがあります。ダイアログフォームを閉じるとき、単に `DoCmd.Close` で閉じてしまうと、親側から値が取得できなくなります。そのため、「フォームを閉じずに、非表示(Visible = False)にする」という技を使います。

登録ボタンのコード(子フォーム側)

Private Sub btnSave_Click()
‘ 入力チェック(簡易版)
If Trim(Me.txtCustomerName.Value & “”) = “” Then
MsgBox “顧客名を入力してください。”, vbCritical, “エラー”
Me.txtCustomerName.SetFocus
Exit Sub
End If

‘ フォームを「閉じる」のではなく「非表示」にする!
‘ (こうすることで、親側のコードがこの後の行から値を取り出せるようになります)
Me.Visible = False
End Sub

キャンセルボタンのコード(子フォーム側)

Private Sub btnCancel_Click()
‘ キャンセルの場合は、フォームを完全に閉じてしまう
DoCmd.Close acForm, Me.Name
End Sub

4. 陥りやすい罠とエンジニアの心得

この設計を実装するとき、初学者が必ずと言っていいほどハマる「罠」があります。最後にそれをシェアしておきますね。

⚠️ トラブル:「フォームが閉じられない」エラー

`Me.Visible = False` でフォームを非表示にした後、親側で値を取得して `DoCmd.Close acForm, “F_CustomerInput”` を実行しますが、もし子フォーム側のデザイン画面で「×ボタン」を押されたりすると、思わぬ挙動をすることがあります。

【解決策の極意】
ダイアログフォームのプロパティで、

  • [閉じるボタン]: `いいえ` に設定する(右上の×を無効化する)
  • フォーム内に必ず「キャンセル(または閉じる)」専用のボタンを置き、その中で確実に `DoCmd.Close` を呼ぶように設計する。

これらを徹底するだけで、ユーザーが意図しない操作でシステムがエラー落ちするリスクを劇的に減らすことができます。

まとめ

今回は `DoCmd.OpenForm` の `WindowMode:=acDialog` を駆使した、プロフェッショナルなデータ入力設計について解説しました。

1. `acDialog` で処理を一時停止させる
2. 値を受け取るまではフォームを「非表示(Visible = False)」にして生き残らせる
3. 値を受け取った後に、コード側で確実にフォームを閉じる

この3つのステップをマスターすれば、あなたの作るAccessデータベースは、市販のパッケージソフト並みに堅牢で使いやすいものに生まれ変わります。

ぜひ、次の開発案件で試してみてくださいね。あなたのAccess開発ライフを応援しています!

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