質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

1回答

6820閲覧

【VBA】動的に生成したコントロールにイベントを追加したいです。

hikonyansuke

総合スコア9

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2022/03/08 23:15

お世話になります。
VBAを始めて3週間ほどの者です。

ユーザーフォームに動的にコマンドボタンを設置し、
さらにクリックイベントを付与したいと思っております。

ユーザーフォームのInitializeイベントの中で呼び出している「checkClmn」という
関数内で下記のコードを記述しております。

Private Sub UserForm_Initialize() Application.ScreenUpdating = False 'ユーザーフォームのCaptionにシート名(テーブル名)を入れる ufrmValueInput.Caption = ActiveSheet.Name 'セルB3(固定)からカラム名の取得を開始する Call checkClmn Application.ScreenUpdating = True End Sub

当初はオリジナルのクラスを作成せずに、
動的作成コントロールにイベントを作成する
↑こちらのサイトを参考にさせていただき、WithEventsキーワードを使って、

Dim WithEvents btn_rst As MSForms.CommandButton Set btn_rst = Controls.Add("Forms.CommandButton.1", "btn_rst" & now_cell_ad)

と記述したのですが、
コードを記述する黒い画面のすぐ上にありますオブジェクトボックスの中に、
「btn_rst 」(コマンドボタンのオブジェクト)が現れず、
上記の方法を辞めて、クラスを作成しました。

クラスモジュール(クラス名「clsOpbtnRst」)に

Option

1Private WithEvents btnRst As MSForms.CommandButton 2Private usr_frm As MSForms.UserForm 3 4'対応するコントロールを設定する 5Public Sub setEvent(new_ctrl As MSForms.CommandButton) 6 Set btnRst = new_ctrl 7End Sub 8 9Private Sub btnRst_Click() 10 MsgBox "OK" 11End Sub

そして、ユーザーフォームのUserForm_Initialize()の関数checkClmn内(先程と同じ場所)に、

Dim WithEvents btn_rst As MSForms.CommandButton Set btn_rst = Controls.Add("Forms.CommandButton.1", "btn_rst" & now_cell_ad) Dim cls_oprst_obj As clsOpbtnRst Set cls_oprst_obj = New clsOpbtnRst cls_oprst_obj.setEvent btn_rst

と記述しました。
すると、コマンドボタンは作成されるのですが、
押しても何も反応せず、メッセージボックスは表示されません。エラーも発生しませんでした。

デバックのF8で一つずつ進めると、きちんとクラスを認識して処理をしてくれているようですが(↓)
イメージ説明

コマンドボタンをクリックしても、何も反応せずエラーも出ず、
クラス内のイベントプロシージャに黄色い矢印が表示されません。(↓)
イメージ説明

長文すみません!
エラーが発生しないため、途方に暮れております。
どなたか、イベントプロシージャを実行できる方法をご教示いただけますと大変ありがたいです。
どうかよろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

フォームのinitializeに書いている

Dim cls_oprst_obj As clsOpbtnRst

をグローバル(プロシージャの外)に置いてください

投稿2022/03/08 23:59

aaabrt

総合スコア22

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hikonyansuke

2022/03/09 00:35

回答を誠にありがとうございます。 あっさり動いてしまいました。少々お恥ずかしいですが本当に助かりました。 これは、オリジナルクラスのインスタンスである「cls_oprst_obj 」をモジュールレベルで、宣言すると、 再度、プロシージャ外で呼び出せるということだと思うのですが、 イベント発生時にまたこのインスタンスを必要とするということでしょうか? よろしければ、動いた理由を簡単に教えていただけいますとありがたいです。
aaabrt

2022/03/09 00:48

プロシージャ外で宣言すると、フォームが起動している間インスタンスが維持されるので、正常にイベントが処理されます。 元のコードだとプロシージャ内でのみインスタンスが維持される書き方(ローカル変数)になっているのでプロシージャを抜けた後はイベントの処理をしてくれるインスタンスが無くなってしまいます。 (スマホから入力しているので細かく書けなくて申し訳ないです) 結論から言えば質問者さんの認識の通りですね
hikonyansuke

2022/03/09 00:56

なるほど、頭の中がすっきりしました! 大変助かりました。 本当にありがとうございました!
hikonyansuke

2022/03/09 01:10

ちなみにおかげさまで、 質問の最初で申し上げた「クラスを使わない方法」も、 ご回答と同じように、プロシージャ外で宣言しましたら上手くいきました! どちらも変数の宣言場所が問題だったのですね。 本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問