2

注: コードエバーに関する質問を初めて投稿しました。私は VBA の正式なトレーニングを受けていません。私が学んだことはすべて、経験を通じて、または Web 上にあります。

私は雇用主のためにいくつかの仕事をしています。ユーザーがデザイン モードでフォームにアクセスできないようにするスケジューリング システムを作成しています。そのため、コードを使用してフォームを動的に作成しています (これが正しい用語であることを願っています)。コードでユーザー フォームを作成し、コードですべてのコントロールを追加します。コマンドボタンにクリックイベントがあり、ユーザーが入力したデータが保存され、フォームが閉じられます。

コードは (私にとっては) 複雑で、多くのシート、サブ ルーチン、およびクラスに分割されていますが、以下は、状況を説明する方法でいくつかのサブ ルーチンにまとめられたコードの一部です。このルーチンでは、WorkSheet_Selection_Change イベントでフォームが表示されます。フォームは、テキスト ボックスとコマンド ボタンで構成されます。コマンド ボタンをクリックすると、テキスト ボックスにテキストを表示するメッセージ ボックスが表示されます。

フォームが正常に表示され、クリック イベントが「発生」します。ただし、テキスト ボックスの変更に関するイベントは発生していないようです。テキスト ボックス内のテキストが変更された場合、それらの変更はメッセージ ボックスに表示されません。フォームを閉じる前 (コマンド ボタンをクリックする前) に手順を停止し、新しく作成されたフォームのコードに移動して、フォーム自体からコードを実行すると、すべてが正常に機能します。

コードが動的に記述されているときに、テキスト ボックスのイベントが発生しない原因は何ですか? 私は何かを逃しましたか?コードを以下に示します。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Call Add_Form
End Sub


Private Sub Add_Form()
        Dim VBProj As VBIDE.VBProject
        Dim VBComp As VBIDE.VBComponent

        Set VBProj = ActiveWorkbook.VBProject
        VBProj.VBComponents.Add (vbext_ct_MSForm)

        Dim myForm As Object
        Set myForm = ThisWorkbook.VBProject.VBComponents("UserForm1")

        Call AddControlToForm(ThisWorkbook.VBProject. _
                      VBComponents("UserForm1"), "CommandButton", 60, _
                      20, 135, 90, "btnSave", "Save")
        Call AddControlToForm(ThisWorkbook.VBProject. _
                      VBComponents("UserForm1"), "TextBox", 80, _
                      20, 90, 90, "txtTest")

        Dim Line As Integer
        Line = myForm.CodeModule.CountOfLines

        myForm.CodeModule.InsertLines Line + 1, "Private Sub UserForm_Initialize()"
        myForm.CodeModule.InsertLines Line + 2, "Me.txtTest.SetFocus"
        myForm.CodeModule.InsertLines Line + 3, "Me.txtTest.Text = ""Change Text"""
        myForm.CodeModule.InsertLines Line + 4, "End Sub"


        Dim NewButton As MSForms.CommandButton
        Set NewButton = myForm.Designer.Controls.Item(btnSave)

        myForm.CodeModule.InsertLines Line + 5, "Private Sub btnSave_Click()"
        myForm.CodeModule.InsertLines Line + 6, "  Unload me"
        myForm.CodeModule.InsertLines Line + 7, "End Sub"

        myForm.CodeModule.InsertLines Line + 8, "Private Sub btnSave" & _
                "_Exit(ByVal Cancel As MSForms.ReturnBoolean)"
        myForm.CodeModule.InsertLines Line + 9, "    MsgBox(UserForm1.txtTest.Text)"
        myForm.CodeModule.InsertLines Line + 10, "End Sub"
    Call ShowForm("UserForm1")
    Call RemoveForm("UserForm1")
End Sub

Public Sub AddControlToForm(objForm As Object, strCtlType As String, intWidth As _
                        Integer, intHeight As Integer, intTop As Integer, _
                        intLeft As Integer, strName As String, _
                        Optional strCaption As String = "!%!@")
    Dim objControl As Object
    Set oForm = objForm

    Set objControl = oForm.Designer.Controls.Add("Forms." & strCtlType & ".1")
    With objControl
        .Name = strName
        .Width = intWidth
        .Height = intHeight
        .Top = intTop
        .Left = intLeft
    End With

    If strCaption <> "!%!@" Then
        With objControl
            .Caption = strCaption
        End With
    End If


End Sub

Private Sub ShowForm(strFormName As String)

    Dim objForm As Object

    Set objForm = ThisWorkbook.VBProject.VBComponents(strFormName)

    VBA.UserForms.Add(objForm.Name).Show

End Sub


Private Sub RemoveForm(strFormName As String)
    Dim VBProj As VBIDE.VBProject
    Dim VBComp As VBIDE.VBComponent

    Set VBProj = ActiveWorkbook.VBProject
    Set VBComp = VBProj.VBComponents(strFormName)
    VBProj.VBComponents.Remove VBComp
End Sub
4

1 に答える 1