2013-08-22 99 views
2

注意:第一次發佈有關代碼的問題。我沒有接受VBA的正式培訓,我所學到的一切都是通過經驗或在網絡上。Dyamically創建UserForm,命令按鈕和文本框:不註冊文本框更改

我正在爲僱主做一些工作。我正在創建一個調度系統,我不希望用戶在設計模式下訪問表單。所以我通過代碼動態地創建表單(我希望這是正確的術語)。我通過代碼創建一個用戶表單,並通過代碼添加所有控件。我在命令按鈕上有一個點擊事件,用戶輸入的數據存儲在這個事件按鈕上,表單關閉。代碼很複雜(對我來說)並分解成許多工作表,子例程和類,但下面的代碼片段組合成幾個子例程,以解釋情況。在這個例程中,一個表單顯示在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 = "!%[email protected]") 
    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 <> "!%[email protected]" 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 

回答

0

據你的問題的信息,你想火有人退出文本框,其名稱爲txtTest後事件。與此同時,您爲btn_Save button創建了exit event的代碼。因此,你需要改變這一行:

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可能是一個令人迷惑的,因此你可以在該提案的方式設置參考窗體。這解決了我的測試代碼中的問題。

順便說一句,你的問題寫得很好。如果您在網絡上提供一些支持的情況下自行編寫此代碼,我只能恭喜你。 :)保持編程!

+0

謝謝您的評論:)雖然這在我的文章中肯定不是很清楚,'_Exit'事件與'btnSave'綁定,因爲表格我將使用「父母」幾個文本框。在這種形式下,每個文本框對輸出做出貢獻,因此我想觸發'btnSave_Exit'(或'_Click')事件中的代碼。但是,即使將'_Exit'事件切換到'txtTest',並且在運行時在文本框中進行了用戶更改,消息框仍會在'_Exit'事件中讀取原始(預先更改)的文本框文本。我需要消息框在文本框中註冊更改。思考? – geekeel

+0

@geekeel,請參閱我提供的解決方案的答案。 –

+0

這很好。謝謝 – geekeel

相關問題