要約:Accessフォームに動的に追加されたコントロールで共通のイベントコードを実行する方法を解説。Excel VBAのイベント処理を参考に、Accessのチェックボックスに対して単体テストコードを作成し、クラスモジュールを用いてイベントを管理。動的フォーム作成と結合テストを通じて、チェックボックスのイベント操作を実演。
キーワード: #MSAccess #VBA #イベント処理 #チェックボックス #クラスモジュール #WithEvents #フォームイベント #コントロール
目次
00:00 0.やりたいこと:
01:18 1.似ている処理を紹介する
2.単体のテストコードを作成する
02:55 2.1 クラスモジュールを作成 名前はClass1と安易に付ける
06:09 2.2 テスト用の フォーム1 にコードを書く
08:00 2.3 イミディエイトの表示でコードの実行とタイミングを確認する
13:42 再度WithEventsのコードを軽く説明する
3.結合テスト Accessフォームでコントロールを動的追加後に単体テストコードを組み込む
15:46 3.1 メインフォームから動的フォームを作る
20:05 3.2 クラスモジュールを作成 名前はClassChkBoxと安易に付ける
22:16 3.3 フォームのForm_Current レコード移動時で、チェックボックス(のイベント)に細工する
3.4 タイミングが取れているか?チェックする
27:37 3.5 CheckBox Clickのイベントに固定のコードを書く おいおい
30:19 総合・結合テスト
0.やりたいこと:
https://youtu.be/7HKggrix5n4
Accessのフォームに作成した(動的追加した)
コントロールで共通のイベントコードを走らせたい、
そんな処理にチャレンジしてみます。
知恵袋の質問:
detail.chiebukuro.yahoo.co.jp
1.似ている処理を紹介する
Excel VBA グラフ選択時のイベント処理を探る クラスモジュールにWithEvents As Chartを書きイベント取得
解説動画:
https://www.youtube.com/watch?v=5Z6P4RldTsw&list=PL8vZhsyiiFht0NNHTC-4DdjsYls8KCcep
ソースコード:
ken3memo.hatenablog.com
2.上記を参考にして、単体のテストコードを作成する
ExcelのグラフとAccessのチェックボックスが違うところ、
OnClick : "[Event Procedure]"が無いと、イベントが走らなかったり
(
ウォッチ式で不思議な文字列 String型を確認
: OnClick : "[Event Procedure]" : String : Form_フォーム1.Form_Current
)
とりあえず、固定の動かないフォームで単体テストする
2.1 クラスモジュールを作成 名前はClass1と安易に付ける
02:55 https://www.youtube.com/watch?v=7HKggrix5n4&t=175
Public WithEvents chk As CheckBox Private Sub chk_Click() Debug.Print chk.Name & " チェックボックスのクリックイベント" End Sub Private Sub chk_Enter() Debug.Print chk.Name & "チェックボックスの_Enterイベント" End Sub
2.2 テスト用の フォーム1 にコードを書く
06:19 https://www.youtube.com/watch?v=7HKggrix5n4&t=369
Private objChkBox(100) As New Class1 '100個のchkbox、違うな書き方が・・ Private Sub Form_Current() Debug.Print "Form_Current レコード移動時" 'コントロールのセット Dim Con As Control Dim i As Long i = 0 For Each Con In Me.Controls Debug.Print Con.Name If Con.Name <> "全協定" Then If TypeName(Con) = "CheckBox" And Right(Con.Name, 2) = "協定" Then i = i + 1 Con.OnClick = "[Event Procedure]" 'イベントを発生させるおまじない※これないとダメ? Set objChkBox(i).chk = Con Debug.Print "set" End If End If Next End Sub Private Sub Form_Load() Debug.Print "Form_Load" End Sub Private Sub Form_Open(Cancel As Integer) Debug.Print "Form_Open" End Sub
2.3 イミディエイトの表示でコードの実行とタイミングを確認する
08:00 https://www.youtube.com/watch?v=7HKggrix5n4&t=480
チェックボックスをクリックして、動作を確認する
こんな感じて、コントロールのイベントをクラスモジュールに書くことができます。
3.結合テスト Accessフォームでコントロールを動的追加後に単体テストコードを組み込む
知恵袋の質問:(※勝手に改行位置変更)
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10299103690
>生成はF_メインのbtn_更新作業クリック時に行っています。
>各協定名チェックボックスは、更新作業時に協定名で対象を絞るためのものですが、
>協定は増減があり、また、使用状況も変更が多いため、動的に生成しています。>全協定を一括選択するためにchk_全選択というチェックボックスも設置(これは固定)し、
>全協定のチェックボックスのON/OFFを切り替えるのですが、
>全協定をON(=各協定チェックボックスがON)にした後、
>各協定のチェックボックスを触ったときに、
>全協定チェックボックスをOFFにしたいのですが、うまく行きません。>フォントサイズや色等は生成時に設定できたのですが、
>「クリック時:chk_全協定.Value=False」はどこにどう書けば設定できるか教えてください。
>=========================================
>■全協定
>■A協定 □B協定 □C協定
>□D協定 ■E協定
>=========================================
>解りづらいですが、↑のような状態になるのを避けるのが目的です。
>よろしくお願いいたします。
3.1 メインフォームから動的フォームを作る
15:46 https://www.youtube.com/watch?v=7HKggrix5n4&t=946
まぁ、いろいろやり方あるけど、
メインフォームから、
動的のサブ登録フォームを作成してみます
![](https://cdn-ak.f.st-hatena.com/images/fotolife/k/ken3memo/20240608/20240608211225.jpg)
名前 値 説明
acCheckBox 106 CheckBox コントロール
acLabel 100 Label コントロール
Private Sub btn_MAKETEST_Click() '登録フォームをデザインモードで開き、チェックボックスを作る 'デザインモードで開く DoCmd.OpenForm "登録フォーム", acDesign 'CreateControl の ヘルプからコードをコピーして作成。 '名前 値 説明 'acCheckBox 106 CheckBox コントロール 'acLabel 100 Label コントロール Dim ctlCheckBox As CheckBox 'チェックボックスのコントロール Dim ctlLabel As Label 'ラベルのコントロール Dim intDataX As Integer, intDataY As Integer ' 新しいコントロールの位置を設定します。 intDataX = 1000 intDataY = 2000 Dim n As Integer '先に chk_ lab_のコントロールを消す 'コントロールの数を知るには Forms("フォーム名").Controls.Count Dim strNAME As String For n = Forms("登録フォーム").Controls.Count - 1 To 0 Step -1 '消すには、 DeleteControl "フォーム名", "コントロール名" strNAME = Forms("登録フォーム").Controls(n).Name '対象のコントロール名 '後ろ2文字が協定のコントロールを消す、ただし全協定は残す。 If Right(strNAME, 2) = "協定" And Right(strNAME, 3) <> "全協定" Then 'コントロールを消す DeleteControl "登録フォーム", strNAME End If Next 'チェックボックスとラベルを付ける For n = 1 To Me.項目数 'メニューの項目数分テストで作成する 'チェックボックスを、詳細セクションに作成します。 Set ctlCheckBox = CreateControl("登録フォーム", acCheckBox, , "", "", _ intDataX, intDataY) '上↑作成したテキストボックスに名前 chk_A協定 を付けたり ctlCheckBox.Name = "chk_" & Chr(Asc("A") + n - 1) & "協定" ctlCheckBox.DefaultValue = True 'デフォルトでON※非連結なのでテスト用 'ラベルを作成します。↑の名前で関連付ける Set ctlLabel = CreateControl("登録フォーム", acLabel, , ctlCheckBox.Name, "", _ intDataX + 250, intDataY, 900, 400) ctlLabel.Name = "lab_" & Chr(Asc("A") + n - 1) & "協定" ctlLabel.Caption = Chr(Asc("A") + n - 1) & "協定" 'Y位置を増やす intDataY = intDataY + 500 '5件でX位置の調整 If (n Mod 5) = 0 Then intDataX = intDataX + 2000 '横移動 intDataY = 2000 'Y位置を初期に縦位置を戻す End If Next MsgBox "動的にチェックボックスを作成終了" 'フォームを閉じる DoCmd.Close acForm, "登録フォーム", acSaveYes '保存して閉じる End Sub Private Sub 登録Fを開く_Click() DoCmd.OpenForm "登録フォーム", acNormal End Sub
その他、関連動画を紹介:
かなり、古い動画ですが少しヘルプを見ながら解説をしています。
テスト ウ. Access フォームにコントロールを動的に追加 QA110318
https://youtu.be/qLKQ9UISxnQ?t=212
↑、こちらも、時間のある時に2倍速で笑ってみてください。
ken3memo.hatenablog.com
3.2 クラスモジュールを作成 名前はClassChkBoxと安易に付ける
20:05 https://www.youtube.com/watch?v=7HKggrix5n4&t=1205
Public WithEvents chk As CheckBox 'これで、イベントを取得する Private Sub chk_Click() Debug.Print chk.Name & " チェックボックスのクリックイベント" End Sub Private Sub chk_Enter() Debug.Print chk.Name & "チェックボックスの_Enterイベント" End Sub
3.3 フォームのForm_Current レコード移動時で、チェックボックス(のイベント)に細工する
22:16 https://www.youtube.com/watch?v=7HKggrix5n4&t=1336
Open,LOAD,後に処理を入れたかったので
(※loadに入れてもいいかも?)
Form_Current レコード移動時のタイミングで、コードを実行します。
'クラスモジュールに付けた名前↓ClassChkBoxを使用する Private objChkBox(100) As New ClassChkBox '100個のchkbox、違うな書き方が・・ Private Sub Form_Current() '非連結のテストなのにね・・ Debug.Print "Form_Current レコード移動時" 'コントロールのセット Dim Con As Control Dim i As Long i = 0 For Each Con In Me.Controls Debug.Print Con.Name If Con.Name <> "chk_全協定" Then If TypeName(Con) = "CheckBox" And Right(Con.Name, 2) = "協定" Then i = i + 1 Con.OnClick = "[Event Procedure]" 'イベントを発生させるおまじない※これないとダメ? Set objChkBox(i).chk = Con Debug.Print "set" End If End If Next End Sub Private Sub Form_Load() 'おまけ、タイミング確認用、いつもどれが先か忘れるのは初老? Debug.Print "Form_Load" End Sub Private Sub Form_Open(Cancel As Integer) 'おまけ、タイミング確認用、いつもどれが先か忘れるのは初老? Debug.Print "Form_Open" End Sub
3.4 タイミングが取れているか?チェックする
3.5 CheckBox Clickのイベントに固定のコードを書く おいおい
27:37 https://www.youtube.com/watch?v=7HKggrix5n4&t=1657
クラスモジュールに、固定のForm操作コードを書く
>「クリック時:chk_全協定.Value=False」はどこにどう書けば設定できるか教えてください。
Forms![登録フォーム]![chk_全協定].Value=False
をクラスモジュールへ
Option Compare Database Option Explicit Public WithEvents chk As CheckBox 'これで、イベントを取得する Private Sub chk_Click() Debug.Print chk.Name & " チェックボックスのクリックイベント" Forms![登録フォーム]![chk_全協定].Value = False End Sub
コードの動作を確認する
30:19 https://www.youtube.com/watch?v=7HKggrix5n4&t=1819
4.おわりの挨拶
こんな感じて、
チェックボックス(※他のコントロールも)
のイベントをクラスモジュールにかけるので、
使ってみてください。
再生リストの紹介: WithEvents VBA マクロ イベント処理
https://www.youtube.com/playlist?list=PL8vZhsyiiFht0NNHTC-4DdjsYls8KCcep
↑似た処理があるので、お時間のある時に動画を見て笑って(ツッコんで下さい)