質問者
リストボックスの Change イベントと BeforeUpdate / AfterUpdate イベントは併用できないのでしょうか

質問
-
前回、[Excel 2016 VBA] Excel 2013 の VBA で複数選択可能リストボックスの Change イベント で
ご回答くださった方ありがとうございます。
(上記タイトル誤記していますが直すの面倒なのでそのままです (^ ^; )上記の質問とは直接関係ないものの関連した内容でまた躓いています。
上記質問の回答にてはじめて BeforeUpdate / AfterUpdate というイベントがあるのを知って
いろいろ試していたらうまくイベントが呼ばれないことがあり、さらに調べてみると Change イベントで
何か処理をする記述をしていると BeforeUpdate / AfterUpdate イベントが発生しないようです。
(BeforeUpdate / AfterUpdate イベントが発生せず、Change イベントのみ発生する)Change イベントと BeforeUpdate / AfterUpdate イベントは併用できないのでしょうか?
それともなにか書き方などが間違っているでしょうか。Private Sub ListBox1_AfterUpdate() MsgBox "ListBox1_AfterUpdate" End Sub Private Sub ListBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean) MsgBox "ListBox1_BeforeUpdate" ' これがないとフォーカスが外れるまで BeforeUpdate イベントが ' 呼ばれなくなる ListBox1.ListIndex = -1 End Sub Private Sub ListBox1_Change() ' (1) MsgBox などのコードがあると NG 'MsgBox "ListBox1_Change" ' (2) Stop, Debug.Assert を含むブレークポイントがあると NG 'Stop 'Debug.Assert False ' (3) Debug.Print と Exit Sub は OK ' (ブレークポイントを設定すると NG) Debug.Print "ListBox1_Change" Exit Sub ' (4) Exit Sub の下にはコードが書いてあっても OK ' (Exit Sub 以下ならブレークポイントも OK) MsgBox "ListBox1_Change" End Sub Private Sub UserForm_Initialize() With ListBox1 ' 単一選択リストボックス .MultiSelect = fmMultiSelectSingle .RowSource = "a1" End With End Sub
- 編集済み infade 2019年5月21日 4:34 リンクに target="_blank" を忘れてた
すべての返信
-
試してみましたが、イベントが併用できないわけではなく、MsgBoxが影響しているようです。MsgBoxを使用しなければ全てのイベントが発動されました。この件に関して詳しくないので調べてみましたが、有益な情報を見つけることができませんでした。フォーカスが関係しているような気もしますが・・・
あまり回答になってなくてごめんなさい
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
- 編集済み trapemiyaModerator 2019年5月21日 8:18
-
infadeさん、こんばんは。
面白いこと試していますねぇ。ちょっと興味がわいたので、小生もいろいろ試して見ました。確かにMsgBoxでは途中で止まるので、Debug.Printで情報を見ることにしました。それから、思い付きで、UserForm2~4を作って、MsgBox代わりに表示するようにしました。Modelessでの表示も試したのですが、申し訳ないですが、説明が面倒ですので、省略。一般的なModalでの動作を報告します。
次のようなスクリプトを作成して実行してみました。
Sub main()
Load UserForm1
UserForm1.Show
MsgBox "fini"
End SubPrivate Sub UserForm_Initialize()
With ListBox1
' 単一選択リストボックス
.MultiSelect = fmMultiSelectSingle
.RowSource = "a1:a5"
End With
End SubPrivate Sub ListBox1_Change()
Debug.Print "ListBox1_Change_start"
UserForm2.Label1.Caption = "ListBox1_Change"
UserForm2.Show vbModal
Debug.Print "ListBox1_Change_end"
End SubPrivate Sub ListBox1_BeforeUpdate(ByVal cancel As MSForms.ReturnBoolean)
Debug.Print "ListBox1_BeforeUpdate_start"
UserForm3.Label1.Caption = "ListBox1_BeforeUpdate"
UserForm3.Show vbModal
Debug.Print "ListBox1_BeforeUpdate_end"
End SubPrivate Sub ListBox1_AfterUpdate()
Debug.Print "ListBox1_AfterUpdate_start"
UserForm4.Label1.Caption = "ListBox1_AfterUpdate"
UserForm4.Show vbModal
Debug.Print "ListBox1_AfterUpdate_end"
End SubUserForm2~4の表示とイミディエイトウィンドウの表示の関係は、次の通り。
まず、UserForm2の上にUserForm3が重ねて表示されます。UserForm2は閉じることができません。
この段階で、ListBox1_Change_startと ListBox1_BeforeUpdate_startがイミディエイトウィンドウ(以下IWと省略します。)に記されます。
UserForm3を閉じるとUserForm4が表示されます。
この段階で、ListBox1_BeforeUpdate_endと ListBox1_AfterUpdate_startがIWに記されます。
UserForm4を閉じるとUserForm1を閉じることができるようになります。
この段階で、ListBox1_AfterUpdate_endが記されます。
UserForm2を閉じるとListBox1_Change_endが記されます。
続けてListBox1の別のリスト項目を選択すると、上記の動作が繰り返されることになります。
この場合、ListBox1の表示は、ListBox1_startからListBox1_Change_endまでの間は、最初の選択項目と新たな選択項目の2つが反転表示されています。
UserForm2を閉じると同時に、最初の選択項目の反転表示が解除されます。以上、単純にChange>BeforeUpdate>AfterUpdateではなくて、Change(>BeforeUpdate>AfterUpdate)のような、Changeが最初なのですが、Changeの処理中にBeforeUpdateとAfterUpdateが行われるような理解をするしかないような、感じなのです。MsgBox代わりのUserFormを2から4まで別々にしたのも、重ねて表示されてしまうものですから、UserFormを別々にしないとエラーになってしまうからです。
Windows10 + Excel2016 で試した結果です。
以上、ご参考まで。
- 回答の候補に設定 Takumi_Q 2019年5月21日 14:05
- 編集済み KokemomoYamamomo 2019年5月22日 2:17 試行錯誤中の残滓削除ほか
- 回答の候補の設定解除 Takumi_Q 2019年6月16日 17:42