Erstellen eines Benutzerformulars

Benutzerformulare sind benutzerdefinierte Dialoge, die dazu dienen, zu Beginn eines Makros Eingabedaten vom Benutzer zu erfassen. Der in Code VBA enthaltene UserForm Builder erstellt automatisch UserForms. Die generierten Benutzerformulare sind mit einem Code zur Eingabevalidierung versehen, um sicherzustellen, dass alle erforderlichen Eingaben vom richtigen Typ sind. Dadurch wird das Makro zuverlässiger. Da die Steuerelemente und der Validierungscode generiert werden, sparen Sie eine Menge Zeit, die Sie für die manuelle Erstellung des Benutzerformulars benötigen würden. Das UserForm kann verändert werden, um das Design optisch ansprechender zu gestalten, indem die Steuerelemente verschoben und in der Größe verändert werden. Darüber hinaus können Sie den UserForm-Vba-Code erweitern, um zusätzliche Anforderungen zu erfüllen.

Verwendung des UserForm Builders

Der UserForm Builder wird über das Menü Code VBA gestartet:

UserForm Name: Kontrolliert Name Datenart Kontrolle Typ Erforderlich Namen auswählen... erstellen. Benutzerformular-Ersteller

Im UserForm Builder werden Sie Folgendes angeben

  • UserForm Name: Geben Sie dem Formular einen Namen, der kurz für die einzugebenden Daten ist. Im Beispiel war der Name "Bestellung".
  • Das Raster für Steuerelemente ist der Bereich, in dem Sie angeben, welche Steuerelemente Sie in das gerade erstellte UserForm einfügen möchten. Jedes Steuerelement wird in einer separaten Zeile mit Eigenschaften angegeben:
    • Name: wird als Bezeichnung für das Eingabefeld verwendet.
    • Datentyp: Wenn der Benutzer einen Wert des falschen Typs in das Steuerelement eingibt, wird der Benutzer durch Drücken der Schaltfläche OK darauf hingewiesen, dass ein Wert für dieses Feld falsch ist, und der Cursor wird zurück in das Feld gesetzt, damit der Benutzer ihn korrigieren kann.
    • Kontrolltyp: Hier können Sie angeben, welcher Kontrolltyp bevorzugt wird. Ein boolescher Wert (ja/nein) kann auf benutzerfreundliche Weise durch ein Häkchen dargestellt werden
    • Erforderlich: Wenn der Benutzer keinen Wert in das Steuerelement eingibt, wird durch Drücken der Schaltfläche OK eine Meldung an den Benutzer ausgegeben, dass ein Wert für dieses Feld fehlt, und der Cursor wird in dieses Feld gesetzt.
  • Namen auswählen...: öffnet ein Eingabefeld für die Bereichsauswahl können Sie einen oder mehrere Namen aus Ihrer Excel-Tabelle auswählen. Dies ist nützlich, wenn Ihr Dialog erstellt wird, um ein bestehendes Excel-Formular oder eine Tabelle zu füllen.
  • Erstellen: erstellt das UserForm - Bild unten - und fügt den Code zum Starten des Userforms ein.
Benutzerformular-Ersteller

UserForm VBA-Code

Zusätzlich zum UserForm-Objekt fügt der Builder auch drei Codestücke hinzu:

Code zum Öffnen / Anzeigen des Benutzerformulars

Angenommen, der Cursor befände sich innerhalb der Prozedur Sub Demo, so würde die Prozedur nach dem Drücken von OK im UserForm Builder wie folgt aussehen.


Sub Demo()
    Dim udtOrder As Order
    With udtOrder
        .Client = ""
        .EntryDate = Date
        .Product = ""
        .Attention = True
    End With
    ufmOrder.FillList "cboProduct", Array("v1", "v2", "v3")
    ufmOrder.SetValues udtOrder
    ufmOrder.Show
    If Not ufmOrder.IsCancelled Then
        ufmOrder.GetValues udtOrder
        ''continue process after OK here
        With udtOrder

        End With
    End If
    Unload ufmOrder
End Sub

Um eine saubere Schnittstelle zu erhalten, wird ein benutzerdefinierter Typ verwendet, der die Datenelemente mit ihren Typdefinitionen auf dem Benutzerformular umfasst. Sie können den Code zwischen dem ersten With und End With ändern, um die Anfangs- oder Standardwerte zu ändern. Die Übergabe der Werte an das Formular erfolgt in der Methode SetValues

Die FillList-Prozedur wird verwendet, um ein Array von Werten an das Produktlistenfeld zu übergeben. Die Werte im Array ("v1",...) sind nur ein Beispiel, das Sie anpassen müssen.

Die Methode Show ist die Standardmethode zum Öffnen der UserForm.

Der Benutzer kann das Dialogfeld mit OK oder Abbrechen bestätigen. Dies wird durch Testen der Eigenschaft .IsCancelled ermittelt.

Wenn der Benutzer auf OK drückt, fährt das Makro mit den Daten fort, die der Benutzer im Benutzerformular angegeben hat. Dazu fügen Sie Ihren eigenen Prozesscode zwischen dem zweiten With und End With ein.

Benutzerdefinierter Typ für eine saubere Schnittstelle

Der generierte benutzerdefinierte Typ bietet eine saubere Schnittstelle zwischen Ihrem Makro und dem UserForm. Wenn sich die Prozedur, von der aus Sie das UserForm aufrufen, in einem Standardmodul befindet, wird der benutzerdefinierte Typ dort eingefügt. Wenn nicht, wird er in einem Modul namens 'modTypes' abgelegt. Im Beispiel sieht die Typdeklaration wie folgt aus:


Public Type Order
    Client As String
    EntryDate As Date
    Product As String
    Attention As Boolean
End Type
Hinweis - Benutzerdefinierter Type Builder
Ähnlich wie der hier beschriebene Builder enthält Code VBA auch einen User Defined Type Builder:

UserForm-Validierung und anderer Code

Innerhalb der generierten UserForm befindet sich noch eine ganze Menge Code, der für die Erstellung der UserForm verwendet wird:

Handhabung von OK und Abbrechen

Der nachstehende Code zeigt die Handhabung von Ok und Cancel. Die Schaltfläche Schließen wird ebenfalls wie Abbrechen behandelt, ohne dass zusätzlicher Code erforderlich ist. Die öffentliche Variable IsCancelled wird verwendet, um dem aufrufenden Makro mitzuteilen, ob der Benutzer Ok oder Cancel gedrückt hat.


Public IsCancelled As Boolean

Private Sub UserForm_Initialize()
    IsCancelled = True
End Sub

Private Sub btnCancel_Click()
    Me.Hide
End Sub

Private Sub btnOk_Click()
    If IsInputOk Then
        IsCancelled = False
        Me.Hide
    End If
End Sub

Übergabe von Daten an das Benutzerformular

Die Daten werden über SetValues und GetValues an das Benutzerformular übergeben bzw. von diesem abgerufen. Beide verwenden die Variable Benutzerdefinierter Typ.


Public Sub SetValues(udtOrder As Order)
    With udtOrder
        SetValue Me.txtClient, .Client
        SetValue Me.txtEntryDate, .EntryDate
        SetValue Me.cboProduct, .Product
        SetValue Me.cbxAttention, .Attention
    End With
End Sub

Public Sub GetValues(ByRef udtOrder As Order)
    With udtOrder
        .Client = GetValue(Me.txtClient, TypeName(.Client))
        .EntryDate = GetValue(Me.txtEntryDate, TypeName(.EntryDate))
        .Product = GetValue(Me.cboProduct, TypeName(.Product))
        .Attention = GetValue(Me.cbxAttention, TypeName(.Attention))
    End With
End Sub

SetValues und GetValues werden mit den folgenden Verfahren durchgeführt:


Private Sub SetValue(ctl As MSForms.Control, value As Variant)
    On Error GoTo HandleError
    ctl.value = value
HandleExit:
    Exit Sub
HandleError:
    Resume HandleExit
End Sub

Private Function GetValue(ctl As MSForms.Control, strTypeName As String) As Variant
    On Error GoTo HandleError
    Dim value As Variant
    value = ctl.value
    If IsNull(value) And strTypeName <> "Variant" Then
        Select Case strTypeName
        Case "String"
            value = ""
        Case Else
            value = 0
        End Select
    End If
HandleExit:
    GetValue = value
    Exit Function
HandleError:
    Resume HandleExit
End Function

Validierung von Benutzerformulareingaben

Wenn der Benutzer auf OK drückt, werden die Daten in der UserForm durch die Funktion IsInputOk validiert. Diese prüft für jedes Eingabefeld IsInputControl, ob es einen Wert HasValue hat, falls dieser erforderlich ist IsRequired. Als nächstes wird geprüft, ob der Wert vom richtigen Typ ist IsCorrectType - wie in UserForm Builder angegeben. Wenn einer der beiden Tests nicht bestanden wird, erhält der Benutzer eine Meldung und der Fokus wird auf das Steuerelement gesetzt, dessen Wert fehlgeschlagen ist ctl.SetFocus.


Private Function IsInputOk() As Boolean
    Dim ctl As MSForms.Control
    Dim strMessage As String
    IsInputOk = False
    For Each ctl In Me.Controls
        If IsInputControl(ctl) Then
            If IsRequired(ctl) Then
                If Not HasValue(ctl) Then
                    strMessage = ControlName(ctl) & " must have value"
                End If
            End If
            If Not IsCorrectType(ctl) Then
                strMessage = ControlName(ctl) & " is not correct"
            End If
        End If
        If Len(strMessage) > 0 Then
            ctl.SetFocus
            GoTo HandleMessage
        End If
    Next
    IsInputOk = True
HandleExit:
    Exit Function
HandleMessage:
    MsgBox strMessage
    GoTo HandleExit
End Function

Beachten Sie, dass IsCorrectType die Funktion ControlDataType verwendet, die einfach den Typ für das angegebene Steuerelement mit Hilfe von Select Case Anweisungen zurückgibt die vom UserForm Builder eingefügt werden. Ein ähnlicher, aber einfacherer Ansatz wird für IsRequired verfolgt.


Private Function IsCorrectType(ctl As MSForms.Control) As Boolean
    Dim strControlDataType As String, strMessage As String
    Dim dummy As Variant
    strControlDataType = ControlDataType(ctl)
    On Error GoTo HandleError
    Select Case strControlDataType
    Case "Boolean"
        dummy = CBool(GetValue(ctl, strControlDataType))
    Case "Byte"
        dummy = CByte(GetValue(ctl, strControlDataType))
    Case "Currency"
        dummy = CCur(GetValue(ctl, strControlDataType))
    Case "Date"
        dummy = CDate(GetValue(ctl, strControlDataType))
    Case "Double"
        dummy = CDbl(GetValue(ctl, strControlDataType))
    Case "Decimal"
        dummy = CDec(GetValue(ctl, strControlDataType))
    Case "Integer"
        dummy = CInt(GetValue(ctl, strControlDataType))
    Case "Long"
        dummy = CLng(GetValue(ctl, strControlDataType))
    Case "Single"
        dummy = CSng(GetValue(ctl, strControlDataType))
    Case "String"
        dummy = CStr(GetValue(ctl, strControlDataType))
    Case "Variant"
        dummy = CVar(GetValue(ctl, strControlDataType))
    End Select
    IsCorrectType = True
HandleExit:
    Exit Function
HandleError:
    IsCorrectType = False
Resume HandleExit
End Function

Private Function ControlDataType(ctl As MSForms.Control) As String
    Select Case ctl.Name
    Case "txtClient": ControlDataType = "String"
    Case "txtEntryDate": ControlDataType = "Date"
    Case "cboProduct": ControlDataType = "String"
    Case "cbxAttention": ControlDataType = "Boolean"
    End Select
End Function

Private Function IsRequired(ctl As MSForms.Control) As Boolean
    Select Case ctl.Name
    Case "txtClient", "txtEntryDate", "cboProduct", "cbxAttention"
        IsRequired = True
    Case Else
        IsRequired = False
    End Select
End Function