2017-01-24 2 views
6

Sagen wir, ich möchte ein Fahrrad-Designer-Programm in Excel VBA machen. Ich habe ein Klassenobjekt (cBike), das einige Standardeinstellungen hat. Jetzt möchte ich ein Formular erstellen (wie das im Bild), mit dem diese Einstellungen geändert werden können, bevor das Fahrrad in der Datenbank gespeichert wird. Die Methode (Sub) zum Speichern befindet sich in cBike.Preserve Class Module in Form

Example of a userform for designing a bicycle.

Ich konnte das Objekt als öffentliche Variable in Form Code wie folgt erhalten:

Public objBike As cBike 
Public Sub StoreBikeToDatabase() 
'database storing code goes here 
End Sub 

Während das funktionieren würde, ich habe viele Leute gesehen, die sich gegen die Verwendung von öffentliche (globale) Variablen. Ich bin nicht ganz sicher, warum, außer dass, wenn Sie zu viele globale Variablen haben, Ihr Code ein Durcheinander sein wird.

Alternativ könnte ich das Objekt vergessen und die Werte aus den verschiedenen Formularsteuerelementen anstelle der Eigenschaften des Klassenmoduls cBike verwenden. Dies scheint jedoch eine etwas ungeschickte Lösung zu sein.

Meine Frage ist: Welche der oben genannten Lösungen sind die besten, wenn überhaupt? Und wenn keiner von ihnen, was sollte ich stattdessen tun?

Update: Ich würde dringend vorschlagen, dass Sie sowohl die angenommene Antwort, als auch die durch dee weiter unten lesen. Beide Antworten haben einige großartige Ideen und dee's Beitrag enthält zusätzlich einige umfassende Codebeispiele, die für andere mit ähnlichen Fragen verwendet werden können.

+0

Sie könnten die drei Werte auf dem Formular in dem Eigentum machen, zusammen mit einer Cancelled-Eigenschaft, die von dem anrufenden Code gelesen/geschrieben werden, die Pflege des von der Aktualisierung dauert ' cBike' Objekt nach Bedarf. – Rory

+0

Es hängt davon ab, wo und warum Sie diese Daten speichern müssen (im Speicher und nicht in der Datenbank). Wenn Sie jedes Mal nur eine neue Instanz der Klasse erstellen, die Eigenschaften bearbeiten und in einer Datenbank speichern, sollten Sie wahrscheinlich eine 'private' Instanz von' cBike' innerhalb des Formulars erstellen oder ein bereits erstelltes 'cBike' an das Formular übergeben bevor ich es zeige. – GSerg

+0

Die Idee war, dass ich eine bereits erstellte Instanz von 'cBike' an das Formular übergeben musste, das dieses Objekt dann speichert, bis es gespeichert werden muss. Eigenschaften von 'cBike' können vom Formular geändert werden, nachdem es an das Formular übergeben wurde, aber bevor es in der Datenbank gespeichert wird. – Noceo

Antwort

4

Ein Formular ist im Wesentlichen eine Klasse für sich, daher würde ich empfehlen, ein Privatobjekt im Formular zu erstellen, um Ihr Bike-Objekt zu halten. Sie können dann das vorhandene Bike-Objekt über eine Property-Set-Routine in das Formular/die Klasse übergeben.

Es gibt kein Problem mit der Deklaration des Bike-Mitglieds/-Eigenschaft auf Formularebene, wenn auf mehrere Routinen innerhalb des Formulars zugegriffen werden muss. Globale/öffentliche Variablen (deklariert in einem Modul) sollten nur verwendet werden, wenn das Objekt vom gesamten Projekt verwendet werden muss.

'Private Member of this Form/Class 
Private mBike As cBike 

'Pass the existing object into this Form/Class 
Public Property Let Bike(ByVal obj As cBike) 

    Set mBike = obj 

End Property 

Sie können eine dynamische Verbindung zwischen den Formular-Steuerelemente und Ihre Klasse durch die Eigenschaften von cBike erklärt wie folgt effektiv erstellen:

Private WithEvents mTextBox1 As MSForms.TextBox 

Public Property Set TextBox1(ByVal obj As MSForms.TextBox) 

    Set mTextBox1 = obj 

End Property 

Dies bedeutet, dass Sie den Wert der Weitergabe nicht halten müssen das Textfeld der Klasse sollte sich ändern. Sie benötigen einen Verweis auf Microsoft Forms 2.0-Objektbibliothek

+0

Danke, das scheint ein klügerer Weg als meine Ideen. Mit etwas Cleverness würde das vermutlich auch eine Art Verbindung zwischen den Steuerelementen und den entsprechenden Eigenschaften des 'cBike' -Objekts ermöglichen ... – Noceo

+0

Ja, das stimmt. Ich habe eine Bearbeitung hinzugefügt, um zu zeigen, wie das gemacht wird. –

+0

Anstatt also eine Eigenschaft als Variable hinzuzufügen, füge ich die Kontrolle als Eigenschaft hinzu? Zum Beispiel, anstatt eine Eigenschaft namens 'NumberOfGears()' zu haben, die mit einer Ganzzahl verknüpft ist, verknüpfe ich sie mit einem Textfeld? Wie bekomme/setze ich dann den Wert dieser Eigenschaft (d. H. Den Wert der Textbox). – Noceo

3

Ein anderer Ansatz könnte sein, die Bike editierbar zu lassen. Die Klasse Bike enthält eine BikeEditor, die ein Benutzerformular für die Bearbeitung von Fahrradobjekt ist. Hier ist ein Beispiel für den Fahrradtyp, aber die anderen Fahrradeigenschaften könnten ähnlich gemacht werden. Für die BikeType wird eine Klasse verwendet, die die TypeOfBikeEnum umschließt.

Bike

Private m_editor As BikeEditor 
Private m_bikeType As BikeType 

Private Sub Class_Initialize() 
    Set m_editor = New BikeEditor 
    Set m_bikeType = New BikeType 
End Sub 

Public Property Get TypeOfBike() As BikeType 
    Set TypeOfBike = m_bikeType 
End Property 

Public Property Set TypeOfBike(ByVal vNewValue As BikeType) 
    Set m_bikeType = vNewValue 
End Property 

Public Sub Edit() 
    m_editor.Initialize Me 
    m_editor.Show 
End Sub 

BikeType

Public Enum TypeOfBikeEnum 
    [_First] 
    Unknown = 1 
    MountainBike = 2 
    StreetBike = 3 
    OfficeBike = 4 
    MoonBike = 5 
    [_Last] 
End Enum 

Private m_type As TypeOfBikeEnum 

Private Sub Class_Initialize() 
    m_type = Unknown 
End Sub 

Public Property Get TypeValue() As TypeOfBikeEnum 
    TypeValue = m_type 
End Property 

Public Property Let TypeValue(ByVal vNewValue As TypeOfBikeEnum) 
    m_type = vNewValue 
End Property 

Public Function GetBikeTypeNames() As VBA.Collection 
    Dim enumVal As Long, name As String 
    Set GetBikeTypeNames = New VBA.Collection 
    For enumVal = TypeOfBikeEnum.[_First] To TypeOfBikeEnum.[_Last] 
     name = GetBikeTypeName(enumVal) 
     If name <> "" Then _ 
      GetBikeTypeNames.Add name, CStr(enumVal) 
    Next enumVal 
End Function 

Public Function GetBikeTypeName(typeOfBikeValue As TypeOfBikeEnum) As String 
    Select Case typeOfBikeValue 
     Case TypeOfBikeEnum.Unknown 
      GetBikeTypeName = "Unknown" 
     Case TypeOfBikeEnum.MountainBike 
      GetBikeTypeName = "MountainBike" 
     Case TypeOfBikeEnum.StreetBike 
      GetBikeTypeName = "StreetBike" 
     Case TypeOfBikeEnum.OfficeBike 
      GetBikeTypeName = "OfficeBike" 
     Case TypeOfBikeEnum.MoonBike 
      GetBikeTypeName = "MoonBike" 
     Case Else 
      GetBikeTypeName = "" 
    End Select 
End Function 

BikeEditor

Private m_bikeToEdit As Bike 

Public Sub Initialize(bikeToEdit As Bike) 
    Set m_bikeToEdit = bikeToEdit 
    Dim bikeTypeName 
    For Each bikeTypeName In m_bikeToEdit.TypeOfBike.GetBikeTypeNames 
     Me.bikeTypesComboBox.AddItem bikeTypeName 
    Next 
    Me.bikeTypesComboBox.ListIndex = m_bikeToEdit.TypeOfBike.TypeValue - 1 
End Sub 

Private Sub CancelCommandButton_Click() 
    Unload Me 
End Sub 

Private Sub SaveCommandButton_Click() 
    If Me.bikeTypesComboBox.ListIndex > -1 Then 
     m_bikeToEdit.TypeOfBike.TypeValue = Me.bikeTypesComboBox.ListIndex + 1 
    End If 
    Unload Me 
End Sub 

Modul

Sub test() 
    Dim bk As Bike 
    Set bk = New Bike 

    Dim bt As BikeType 
    Set bt = New BikeType 
    bt.TypeValue = OfficeBike 

    Set bk.TypeOfBike = bt 
    bk.Edit 
End Sub 
+0

Danke für die umfassende Anleitung. Ich mag die Idee, das Bearbeitungsformular dem Objekt selbst hinzuzufügen, anstatt das Objekt an das Formular zu übergeben. – Noceo

+0

Gern geschehen. – dee

Verwandte Themen