注意:第一次发布关于代码的问题。我没有接受过正式的 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