色々と思うことが有って、VBAのFormに取り組んでいるのですが
知識が足りず悩んでます。
UserFromにコマンドボタンを動的に追加し、イベントも動的に発生させたいです。
こちらで教わったのですが
Formの内容を、DrawTableに反映する - C#ATIA
こちらを参考にしてみました。
VBA。フォームにコントロールを動的に追加する - Qiita
が、こちらのコード、色々とまずかったのでこんな風に
してみました。
まず、フォームモジュールですが作りましたが何もしません。
とにかく作るだけで、名前は "UserForm1" です。
続いて、クラスモジュール。 名前は "Class1" です。
'vba Class1.cls Option Explicit Private WithEvents mBtn As MSForms.CommandButton Sub InitBtn(ByVal Btn As MSForms.CommandButton) Set mBtn = Btn End Sub Private Sub mBtn_Click() Dim Msg$ Msg = "オートコンプリートで、" & vbNewLine & _ "ControlTipText出ませんが" & vbNewLine & _ "このボタンでは[ " & mBtn.ControlTipText & " ]です" MsgBox Msg End Sub
続いて標準モジュール。 名前は "Module1" です。
'vba Module1.bas Option Explicit Sub FormTest() Dim CapAry As Variant: CapAry = Split("hoge,piyo,fuga", ",") Dim TipAry As Variant: TipAry = Split("foo,bar,baz", ",") Dim BtnInfoAry() As Variant: ReDim BtnInfoAry(UBound(CapAry)) Dim i& For i = 0 To UBound(CapAry) BtnInfoAry(i) = Array(CapAry(i), TipAry(i)) Next Call Init_Form(BtnInfoAry) End Sub Private Function Init_Form(ByVal InfoAry As Variant) As UserForm1 Dim BtnCnt&: BtnCnt = UBound(InfoAry) Dim Uf As UserForm1: Set Uf = UserForm1 With Uf .Width = 70 .Height = (BtnCnt + 1) * 20 + 30 End With Dim i&, Btn As MSForms.CommandButton Dim BtnAry() As Class1: ReDim BtnAry(BtnCnt) For i = 0 To BtnCnt Set Btn = Uf.Controls.Add("Forms.CommandButton.1", i, True) With Btn .Top = 5 + (i) * 20 .Left = 5 .Height = 20 .Width = 70 .Caption = InfoAry(i)(0) .ControlTipText = InfoAry(i)(1) End With Set BtnAry(i) = New Class1 Call BtnAry(i).InitBtn(Btn) Next UserForm1.Show End Function
Init_Form関数は戻り値返していないのですが、後のテストの為です。
この関数のキモは、こちら
Dim Uf As UserForm1: Set Uf = UserForm1
インスタンスを生成しているのではなく、最初に作った空っぽのForm自体を
受け取っています。
で、この状態であれば無事動き、イベントも発生します。
自宅なのでExcelでやってますが、CATIAでも同じでした。
問題はここから。先程の部分をインスタンスに変更します。
Dim Uf As UserForm1: Set Uf = New UserForm1
これだと、イベントが発生しません・・・。
又、インスタンスではなく最初の状態に戻し、
'vba Module1.bas Option Explicit Sub FormTest() ・・・ Dim Uf As UserForm1 Set Uf = Init_Form(BtnInfoAry) Uf.Show End Sub Private Function Init_Form(ByVal InfoAry As Variant) As UserForm1 Dim BtnCnt&: BtnCnt = UBound(InfoAry) Dim Uf As UserForm1: Set Uf = UserForm1 ・・・ Next 'UserForm1.Show Set Init_Form = Uf End Function
FormTest側で戻り値を受け取り、FormTest側でShowさせても
同様にイベントが発生しません。
(本当はこうしたかったので、関数名をInit_Formしたのに…)
こんなもんなのでしょうか?
追記です。 教えていただきました。
フォームモジュールは空っぽではなく、この様にしました。
'vba UserForm1.frm Option Explicit Private mAry As Variant Sub SetBtn(ByVal Ary As Variant) mAry = Ary End Sub
標準モジュールはこの様に
'vba Module1.bas Option Explicit Sub FormTest() ・・・ Dim Uf As UserForm1 Set Uf = Init_Form(BtnInfoAry) Uf.Show End Sub Private Function Init_Form(ByVal InfoAry As Variant) As UserForm1 Dim BtnCnt&: BtnCnt = UBound(InfoAry) Dim Uf As UserForm1: Uf = New UserForm1 ・・・ Next 'UserForm1.Show Call Uf.SetBtn(BtnAry) Set Init_Form = Uf End Function
これで上手く行きました。 ありがとうございます。