动态创建UserForm,命令按钮和文本框:不注册文本框更改

时间:2013-08-22 14:55:41

标签: dynamic excel-vba user-controls vba excel

注意:首次发布有关代码的问题。我没有接受过VBA的正式培训,我所学到的一切都是通过经验或在网上进行的。

我正在为雇主做一些工作。我正在创建一个调度系统,我不希望用户在设计模式下访问表单。所以我通过代码动态创建表单(我希望这是正确的术语)。我通过代码创建用户表单,并通过代码添加所有控件。我在命令按钮上有一个点击事件,用户输入的数据存储在该事件上,表格已关闭。

代码很复杂(对我而言)并分为许多工作表,子例程和类,但下面是以一种应该解释情况的方式放在一起的几个子例程中的代码片段。在此例程中,将在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

1 个答案:

答案 0 :(得分:0)

根据您提问的信息,您希望在有人退出文本框后触发事件,其名称为txtTest。在此期间,您创建了为exit event创建btn_Save button的代码。因此,您需要更改此行:

    myForm.CodeModule.InsertLines Line + 8, "Private Sub btnSave" & _
            "_Exit(ByVal Cancel As MSForms.ReturnBoolean)"

进入这个:

    myForm.CodeModule.InsertLines Line + 8, "Private Sub txtTest" & _
            "_Exit(ByVal Cancel As MSForms.ReturnBoolean)"

编辑经过以下评论后,我明白了。所以,改变这一行:

myForm.CodeModule.InsertLines Line + 9, "    MsgBox(UserForm1.txtTest.Text)"

进入这一个:

myForm.CodeModule.InsertLines Line + 9, "    MsgBox Me.txtTest.Text"

似乎UserForm1可能会令人困惑,因此您可以通过此方法设置对用户表单的引用。这解决了我的测试代码中的问题。

顺便说一下,你的问题写得很好。如果您自己编写此代码并获得网络支持,我只能向您表示祝贺。 :)继续编程!