PDA

Vollständige Version anzeigen : Dynamische UserForm


andiE
05.09.2003, 14:35
Hallo zusammen,

ich hätte mal 'ne Frage zum dynamischen Erstellen einer UserForm.
Und zwar brauche ich eine variable Anzahl von Textfeldern und Buttons.
Beispiel-Code:

Dim tbCollection As Collection
Dim buttonCollection As Collection
Dim valueCollection as Collection

Private Sub UserForm_Activate()
Set tbCollection = New Collection
Set buttonCollection = New Collection
If Not (valueCollection Is Nothing) Then
Dim i As Integer
Dim myLabel As MSForms.Label
Dim myTextBox As MSForms.TextBox
Dim myButton As MSForms.CheckBox
myFrame.Controls.Clear
With valueCollection
For i = 1 To .count
Set myLabel = myFrame.Controls.add("Forms.Label.1")
Set myTextBox = myFrame.Controls.add("Forms.TextBox.1")
Set myButton = myFrame.Controls.add("Forms.CommandButton.1")
myLabel.Left = 20
myLabel.Width = 150
myLabel.Top = i * 30 + 10
myLabel.Caption = .item(i)
myTextBox.Left = 170
myTextBox.Width = 200
myTextBox.Top = i * 30 + 10
myButton.Left = 380
myButton.Width = 80
myButton.Caption = "Drück mich"
myButton.Top = i * 30 + 10
tbCollection.add myTextBox
buttonCollection.add myButton
Next i
End With
End If
End Sub

Die Idee ist: valueCollection wird vorher übergeben, dann für jedes Element aus der Collection ein Label, eine TextBox und ein Button angezeigt.
So weit so schön. Aber wie kann ich die Click-Events für die jeweiligen Buttons abfangen?
Oder muss ich das ganz anders angehen?

Viele Gruesse,
Andreas.

Hotte
05.09.2003, 19:39
Hi Andreas,

von der Idee her hört sich das nett an. Aber es scheint mir nicht praktikabel. Deine Userform hat doch eine bestimmte Größe. Also kannst Du auch nur eine begrenzte Anzahl an Terxtbox und Commandbuttons unterbringen.

Ich würd die maximalzahl auf die Userform setzen und alle ausblenden und nur nach Bedarf einblenden. Hat den Vorteil, dass Du den Code auch schön an den Stellen schreiben kannst, wo Du ihn brauchst.

Das Einzige was stört ist, dass wenn z.B. die 1. Textbox und Commandbutton und die 5. Textbox und Commandbutton eingeblendet wird, Du einiges an freier Fläche hast. Aber das hast Du so der so.


Das scheint mir schnell und ohne großen Aufwand erstellbar zu sein.

Gruß
Horst

andiE
08.09.2003, 08:27
Hallo Horst,

die Größe der UserForm ist nicht das eigentliche Problem, da die TextBoxen und CommandButtons in einem Frame platziert werden. Der bekommt eine ScrollBar und die ScrollHeight kann ich ja dynamisch setzen, je nachdem wieviel Felder ich habe.
Aber wahrscheinlich werde ich es so machen, wie Du vorgeschlagen hast.
Hat nur den Nachteil, dass man mehr Code schreiben muss ... ;-)

Vielen Dank jedenfalls,
Andreas

andiE
27.10.2003, 17:03
Hallo zusammen,

Und es geht doch ... ;-)

Wir haben jetzt doch eine Möglichkeit gefunden, wie das Ganze funktioniert. Und zwar definiert man ein Klassenmodul (ich habe es mal ButtonWrapper genannt) wie folgt:

Option Explicit

Private WithEvents theButton As MSForms.CommandButton

Public Property Set button(ByRef bt As MSForms.CommandButton)
Set theButton = bt
End Property

Private Sub theButton_Click()
Modul1.processEvent theButton
End Sub

Hier noch das Hauptmodul:

Option Explicit

' Wird gehalten, damit ButtonWrapper-Objekte nicht gelöscht werden.
Dim wrapperColl As New Collection

Sub showForm()
Dim answerStr As String
Dim noOfFields As Integer, i As Integer
Dim tb As MSForms.TextBox
Dim button As MSForms.CommandButton
Dim wrapper As ButtonWrapper

answerStr = InputBox("Wieviele Felder?")
If IsNumeric(answerStr) Then
noOfFields = answerStr
For i = 1 To noOfFields
Set tb = UserForm1.Frame1.Controls.Add("Forms.TextBox.1", "TextBox" & i)
Set button = UserForm1.Frame1.Controls.Add("Forms.CommandButton.1", "Button" & i)
tb.Left = 10
tb.Top = 10 + i * 30
button.Left = 210
button.Top = 10 + i * 30
button.Caption = "Button " & i
Set wrapper = New ButtonWrapper
Set wrapper.button = button
wrapperColl.Add wrapper
Next i
UserForm1.Show
End If
End Sub

Sub processEvent(ByRef bt As MSForms.CommandButton)
MsgBox "Event kam von Button " & bt.Name
End Sub

Das heißt, für jeden Button wird ein ButtonWrapper-Objekt erzeugt, das dann den Event verarbeiten kann. Das ButtonWrapper-Objekt wird dann in ein Collection-Objekt gesteckt, damit es nicht gelöscht wird (als Java-Programmierer würde ich sagen, weil sonst der GarbageCollector kommt).

Ich hänge mal das DOC an, falls jemand Interesse hat. Ist natürlich nicht sehr ausgefeilt, soll auch nur das Grundprinzip darstellen ...

Viele Grüsse,
Andreas

Hotte
27.10.2003, 19:28
Hallo Andreas,

Prima, dass Du Deine Lösung hier nochmal reinstellst. Gefällt mir auch gut. Obwohl ich mir im Moment einfach keine Aufgabenstellung vorstellen kann, wo ich das brauchen könnte. Kommt jedenfalls in meine "Sammlung". Auch das Festlegen der Ereignisse der einzelnen Buttons ist wieder aufwändig je nach Aufgabenstellung und muss dann doch wieder bereits als Code hinterlegt sein. Kommt aber auf die Aufgabenstellung an!

Nur zur Info: Habe eine einfache Lösung als Code-Beispiel für die Bildlaufleiste hinzugefügt.



....
....
Set wrapper.button = button
wrapperColl.Add wrapper
Next i

Load UserForm1
If answerStr > 7 Then
With UserForm1
.Frame1.ScrollBars = fmScrollBarsVertical
.Frame1.KeepScrollBarsVisible = fmScrollBarsVertical
.Frame1.ScrollHeight = 2 * .Frame1.Height

End With
End If

UserForm1.Show
End If
End Sub




Nur als Beispiel. Kann man natürlich noch nach Bedarf verfeinern je nach der geplanten maximalen Anzahl der Felder / Buttons.


Gruß
Horst