スポンサーリンク

【Microsoft Access】フォームイベントの発生順まとめ|処理を書く場所で迷わないために

Accessの湯
スポンサーリンク

Microsoft Accessでフォームを作っていると、「この処理、どのイベントに書くのが正解なんだろう?」と迷った経験はありませんか?

“開くとき”や“閉じるとき”に複数のイベントが発生しますが、その実行順を正確に把握できているでしょうか。

Form_Open、Form_Load、Form_Current、Form_Activate……

イベントの種類は多いのに、それぞれいつ・どんな順番で実行されているのかは意外と意識しないまま使っている方も多いと思います。

その結果、次のような問題が起こりがちです。

  • 想定より早く処理が走ってエラーになる
  • なぜか処理が二重に実行される
  • 開いた直後と、フォーカス移動時で挙動が変わる

といった「理由の分からない挙動」に悩まされがちです。

特に「Form_OpenとForm_Loadの違いが分からない」「Form_Currentに書いたら二重実行された」といった悩みは、イベントの発生順を正しく理解していないことが原因であるケースがほとんどです。

この記事では、Accessフォームを開いてから閉じるまでに発生するイベントを、実際に検証した結果をもとに時系列で整理します。

さらに、使用可能なオブジェクトがある場合/ない場合で何が変わるのかについても比較し、「どのイベントに処理を書くべきか」を判断しやすくなることを目的としています。

フォームのイベント処理で一度でも首をかしげたことがある方は、ぜひ参考にしてみてください。

この記事で分かること

  • Accessフォームのイベントが発生する正確な順番
  • Form_Open / Load / Current / Activate の役割の違い
  • オブジェクト有無で何が変わるのか
  • 処理を書くときに避けた方がいいイベント

※ 本記事は、Accessフォームのイベントを一通り使ったことはあるが、「どこに何を書くべきか」で迷った経験がある方向けの内容です。

※ 本検証はシングルフォームを前提としています。サブフォームや連続フォームでは結果が異なる可能性があります。

調査の方法

ここでは「イベントが実際にどの順番で動いているのか」を推測ではなくログとして確認するための方法を紹介します。

調査の方法としては、フォーム(F_MAIN)とテーブル(T_処理)を準備し、各イベントの発生時に処理名と処理の対象をテーブルに追加クエリ(Q_追加)で追加する方法で行いました。

テーブルのフィールドは以下のように設定

  • id 【長整数型オートナンバー】
  • 処理名 【テキスト型】
  • 対象 【テキスト型】

追加クエリ(Q_追加)は以下のSQLで実施

INSERT INTO T_処理 ( 処理名, 対象 ) SELECT iddataf() AS 処理名, TaisyouF() AS 対象;

上記SQLではマーカーの自作関数を2つ利用しています。

上記関数も含めた作成モジュール全文は以下の通り

Option Compare Database

Public iddata As String
Public taisyou As String

Private Declare Sub Sleep Lib "kernel32" (ByVal sleep_milli_second As Long)

Function IDdataF()
    IDdataF = iddata
End Function


Function TaisyouF()
    TaisyouF = taisyou
End Function

Sub SyoriID(strIDdata As String, strTaisyou As String)
    
    iddata = strIDdata
    taisyou = strTaisyou
    
    DoCmd.SetWarnings False
    
    DoCmd.OpenQuery "Q_追加"
    
    DoCmd.SetWarnings True
    
    Sleep 100
    
End Sub

SyoriID関数をフォームの各イベントに記述することで、実行されるイベントの順番をT_処理保管する形となります。

また、Sleep 100で処理を100ミリ秒待たせて順番の入れ替わりがないように設定しています。

(おそらく同期処理と思われるので不要だとは思いますが念のため)

フォームのイベントの記述は以下の通り。

Private Sub Form_Open(Cancel As Integer)
    Call SyoriID("開く時", "フォーム")
End Sub

開いて閉じるまでに発生するイベント

では、前述の処理を用いて検証した結果を見ていきましょう。

フォームの開き方はナビゲーションウィンドウから「F_MAIN」をダブルクリックで開く。

タブで表示されているフォームのxボタンで閉じる方法で閉じる。

という方法を取っています。

Accessフォームではフォーム上のボタンを利用して閉じることが可能ですが、オブジェクトの影響を極力避けるため、上記方法を取りました。

使用可能なオブジェクトが存在しない場合

まずはフォームの中に使用可能な(選択可能な)オブジェクトが存在しない場合の発生イベントは以下の順番で発生します。

ID処理名対象
1開く時フォーム
2読込時フォーム
3サイズ変更時フォーム
4アクティブ時フォーム
5フォーカス取得後フォーム
6レコード移動時フォーム
7描画時フォームヘッダー
8描画時詳細
9描画時フォームフッター
10描画時フォームヘッダー
11描画時詳細
12描画時フォームフッター
13描画時フォームヘッダー
14描画時フォームヘッダー
15描画時詳細
16描画時詳細
17描画時フォームフッター
18描画時フォームフッター
19読込解除時フォーム
20フォーカス喪失時フォーム
21非アクティブ時フォーム
22閉じる時フォーム
フォームを開いて閉じるまでに発生するイベント順

この結果から分かる重要なポイントは以下です。

  • Form_Open / Load は1回だけ実行される
  • Form_Current はレコードソースの有無に関係なく発生する
  • 描画時(Paint)イベントは想像以上に複数回呼ばれる

6の「レコード移動時」イベントはレコードソースとしてテーブルを指定していても、指定していなくても同様に発生していました。

今回この検証をして驚いたのが、7~18で発生している「描画時」イベントです。

フォームを開き終わるまでにフォームヘッダー・詳細・フォームフッターでそれぞれ4回描画していることが分かります。

閉じる時に描画を行っている可能性もあったので、念のためクエリに処理した時間を追記して再検証しました。

この検証後、処理を分離するために開き終わって10秒程度触らずに、10秒経ったらxボタンで閉じる操作を実施しました。

結果、「描画時」イベントがフォームを開いている時に4回発生しているということで間違いありませんでした。

もし「描画時」イベントに処理をすることを考える場合、重複した処理が発生しないよう注意が必要です。

使用可能なオブジェクトが存在する場合

次に、フォームの詳細に使用可能なテキストボックスを追加し、開いて閉じる操作を実行してみました。

実行結果は以下の表の通りです。

ID処理名対象
1開く時フォーム
2読込時フォーム
3サイズ変更時フォーム
4アクティブ時フォーム
5レコード移動時フォーム
6フォーカス取得時テキストボックス
7フォーカス取得後テキストボックス
8描画時フォームヘッダー
9描画時詳細
10描画時フォームフッター
11描画時フォームヘッダー
12描画時詳細
13描画時フォームフッター
14描画時フォームヘッダー
15描画時フォームヘッダー
16描画時詳細
17描画時詳細
18描画時フォームフッター
19描画時フォームフッター
20フォーカス喪失時テキストボックス
21フォーカス喪失後テキストボックス
22読込解除時フォーム
23非アクティブ時フォーム
24閉じる時フォーム
フォームを開いて閉じるまでに発生するイベント順(オブジェクトあり)

変わったところはフォームにフォーカスが映らないというところです。

フォーカス取得が可能なオブジェクト(使用可能なテキストボックスやコマンドボタンなど)が存在する場合、フォームにはフォーカスが移動せず、オブジェクトに直接フォーカスが移動することが分かります。

まとめ

Accessのフォームを開いて閉じるまでに発生するイベントの順番を調査し紹介しました。

用途別おすすめイベント例

  • 初期化処理 → Form_Load
  • 表示制御(初回のみ) → Form_Current(フラグ管理前提)
  • サイズ・レイアウト調整 → Form_Resize
  • 描画依存の処理 → 原則非推奨(Paintは多重発火するため)

今回の検証で描画時イベントの複数回発生について気になったので、後日検証してみようと思います。

Accessで処理を作成する際、適切なタイミングで処理しないと思ってもいない現象が起こることがあります。

適切なタイミングを見つけるようにしましょう。

困ったら検証してみても良いかもしれません。

効率化が求められる昨今、ノーコードのソフト開発も簡単にできるようになってきていますが、色々作れるに越したことはありません。

色々弄って試してみてください。

コメント

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