ユーザーフォーム独自イベント。Spinボタンで数量±2する。
Spinボタンで数量±2するためには…
以下の動画をご覧ください。
VBA ユーザーフォーム 独自イベント
— かずやん (@y8bV4ty1wbkTjPd) 2020年11月14日
Spinボタンで数量±2する。 pic.twitter.com/HGuVvMyNZm
数量1がSpinボタンで±2されています。この処理を実装するためには、UserFrom上にSpinボタンを作成して、SpinUp、SpinDownイベントに±2するように記述すればいいと思われるでしょう。
しかし、このユーザーフォームには以下の画像の通り、Spinボタンはありません。
つまり、ユーザーフォーム上には実体がないため、SpinボタンのSpinup、SpinDownイベントに記述することができません。
仮に、実体があれば以下のコードで実装が可能。
Private Sub spn_数量_Spinup() UserForm1.Controls("txt_数量").Object.Value = UserForm1.Controls("txt_数量").Object.Value + 2 End Sub '-------------------------------------------------------------------------------------- Private Sub spn_数量_SpinDown() UserForm1.Controls("txt_数量").Object.Value = UserForm1.Controls("txt_数量").Object.Value - 2 End Sub
しかし、今回のように動的に作成したコントロールに対してイベント処理をさせるにはどうすればいいのか。それはクラスモジュールの「WithEvents」を使います。
その設定方法について解説します。
1 閲覧対象者
クラスモジュールの「WithEvents」を使ってユーザフォームコントロールに、独自のイベント処理を追加する方法を学びたい方。
3 設計
動的に作成したSpinボタンに対して、クラスモジュールの「WithEvents」を使って、Spinup、Spindownで、TextBoxの数量1を±2する独自イベントを作成する。
<2 ユーザーフォーム コード>
'UserFromのコレクションの宣言(独自イベントの登録用コレクション) Private CheckCollection As Collection '-------------------------------------------------------------------------------------- Private Sub UserForm_Initialize() Dim obj As Cls_amount Dim ctrl As Control Set CheckCollection = New Collection 'コレクション生成 'spinボタンを作る Dim newSpin As MSForms.SpinButton Set mySpin = UserForm1.Controls.Add("Forms.spinbutton.1", "spn_数量") '名前をつけてSpinボタンを追加 With mySpin .Width = 30 '横幅 .Height = 42 '縦幅 .Left = 150 '左からの距離 .Top = 78 '上からの距離 End With '独自イベントをMe.Collectionに登録する処理 For Each ctrl In Me.Controls If TypeName(ctrl) = "SpinButton" Then If ctrl.Name = "spn_数量" Then 'スピンアップを登録 Set obj = New Cls_amount 'インスタンスの生成 obj.SetCtrl_SpinButton_数量Up ctrl 'コントロールをセット CheckCollection.Add obj 'コレクションへ追加 Set obj = Nothing 'インスタンス破棄 End If End If Next End Sub
<3 標準モジュール>
Sub 数量UP() UserForm1.Show End Sub
<4 クラスモジュール(Cls_amount)>
'独自イベントの宣言 Private WithEvents Target_SpinButton_数量Up As MSForms.SpinButton '-------------------------------------------------------------------------------------- 'Spinボタンに独自イベントをSetする処理 Public Sub SetCtrl_SpinButton_数量Up(new_ctrl_SpinButton_Up As MSForms.SpinButton) Set Target_SpinButton_数量Up = new_ctrl_SpinButton_Up End Sub '-------------------------------------------------------------------------------------- 'SpinUpしたときの処理 Private Sub Target_SpinButton_数量Up_SpinUp() UserForm1.Controls("txt_数量").Object.Value = UserForm1.Controls("txt_数量").Object.Value + 2 End Sub '-------------------------------------------------------------------------------------- 'SpinDownしたときの処理 Private Sub Target_SpinButton_数量Up_SpinDown() UserForm1.Controls("txt_数量").Object.Value = UserForm1.Controls("txt_数量").Object.Value - 2 End Sub
以上で実装は完了です。では、解説していきます。
4 処理の解説
ユーザーフォームに独自のイベントを持たせる場合、対象のUserFromに対して独自イベント登録用のCollectionが必要になります。その部分は、<2 ユーザーフォーム コード>の「Private CheckCollection As Collection」です(モジュールレベルに宣言)。
'UserFromのコレクションの宣言(独自イベントの登録用コレクション) Private CheckCollection As Collection
宣言した「CheckCollection 」に対象のSpinボタンを独自のイベントとして追加します。
次に、独自イベントを記述しているクラスモジュールを作成します。細部を見ていきましょう。
'独自イベントの宣言 Private WithEvents Target_SpinButton_数量Up As MSForms.SpinButton
まず、「Target_SpinButton_数量Up」という独自のイベントを宣言します。
次に、「Target_SpinButton_数量Up」に引数となるSpinボタンを登録する処理を記述します。
'Spinボタンに独自イベントをSetする処理 Public Sub SetCtrl_SpinButton_数量Up(new_ctrl_SpinButton_Up As MSForms.SpinButton) Set Target_SpinButton_数量Up = new_ctrl_SpinButton_Up End Sub
この処理で、「Target_SpinButton_数量Up」に対して、引数となったSpinボタンを独自イベントにSetします(UserFrom1のCheckCollectionへの登録は、フォームモジュール部で説明します)。
次に、独自のイベント処理を記述します。今回のお題のSpinup、Spindown時に±2するイベントです。
'SpinUpしたときの処理 Private Sub Target_SpinButton_数量Up_SpinUp() UserForm1.Controls("txt_数量").Object.Value = UserForm1.Controls("txt_数量").Object.Value + 2 End Sub '-------------------------------------------------------------------------------------- 'SpinDownしたときの処理 Private Sub Target_SpinButton_数量Up_SpinDown() UserForm1.Controls("txt_数量").Object.Value = UserForm1.Controls("txt_数量").Object.Value - 2 End Sub
これで、クラスモジュールは完成しました!次にフォームモジュール(UserForm_Initialize)を見ていきましょう。
まず、クラスモジュール(Cls_amount)として「obj」を宣言。また、Controlとして「ctrl」を宣言します。
Dim obj As Cls_amount Dim ctrl As Control
次に、CheckCollection(独自イベントの登録用コレクション)を実体化します。これで、Me(UserFrom1)に「CheckCollection」というCollectionが実体化され、独自イベントを登録する器ができました。
Set CheckCollection = New Collection 'コレクション生成
次に、Spinボタンを作成するコードを記述します。
'spinボタンを作る Dim newSpin As MSForms.SpinButton Set mySpin = UserForm1.Controls.Add("Forms.spinbutton.1", "spn_数量") '名前をつけてSpinボタンを追加 With mySpin .Width = 30 '横幅 .Height = 42 '縦幅 .Left = 150 '左からの距離 .Top = 78 '上からの距離 End With
最後に、一番肝心な「独自イベントをMe.Collectionに登録する処理」です。
'独自イベントをMe.Collectionに登録する処理 For Each ctrl In Me.Controls If TypeName(ctrl) = "SpinButton" Then If ctrl.Name = "spn_数量" Then 'スピンアップを登録 Set obj = New Cls_amount 'インスタンスの生成 obj.SetCtrl_SpinButton_数量Up ctrl 'コントロールをセット CheckCollection.Add obj 'コレクションへ追加 Set obj = Nothing 'インスタンス破棄 End If End If Next End Sub
Me(UserFrom1)のすべてのコントロール(Me.Controls)内をループ処理します。
コントロールが「SpinButton」かつ、コントロールの名前が「spn_数量」のとき、独自イベント登録処理を実施します。
まず、objを「Cls_amount」として実体化します。
次に、クラスモジュールの「SetCtrl_SpinButton_数量Up」で、Spinボタン(spn_数量)を、WithEventsで宣言した「Target_SpinButton_数量Up」にSetします。
次に、Me(UserFrom1)のCheckCollection(独自イベントの登録用コレクション)に加えます。その後、objを破棄します。
これが、ユーザーフォーム内の処理です。
最後に、標準モジュールにUserFrom1を呼び出す処理を記述します。
Sub 数量UP() UserForm1.Show End Sub
これで、最初の動画の通り独自イベントが追加されたSpinボタンが作成され、Spinup、Spindownで±2が可能となりました。
VBA ユーザーフォーム 独自イベント
— かずやん (@y8bV4ty1wbkTjPd) 2020年11月14日
Spinボタンで数量±2する。 pic.twitter.com/HGuVvMyNZm
ちなみに、ローカルウィンドウを確認すると以下の画像蛍光線部に独自イベントが登録されていることが確認できます。
以上で解説終了です。
5 感想
いかがでしょうか。複雑なようですが、要はクラスモジュールで宣言したWithEventsに該当のSpinボタンをセットして、そのSetされたSpinボタンをMe(UserFrom1)のCollectionに追加してあげればいいということです。
私自身、まだあやふやな部分はありますが自分の思考のまとめとして記述しました。とりあえず、こう書けば動きますw。
処理を共通化すると、コードが軽くなります。例えば、Spinボタンが300個あったら、300個1つ1つに、Spinup、Spindownイベントを記述するのは非合理的ですよね。メモリが小さいPCでは、メモリ不足となります。そう言った点でも大事です。
クラスモジュールについて、ネット検索してもあまり参考になるものがなかったので具体的にやりたいことのコードを書いたつもりです。独自イベントの設定方法の理解の助けになれば幸いです。
6 使ってみたい方はnoteで無料DL
実際に使ってみたい方は、noteより無料ダウンロード可能です。
note.com