VBA - Instanzen einer Benutzdefinierten Klasse zählen
#1
Servus Excel-Forumsmitglieder,

ich möchte die Instanzen einer benutzerdefinierten Klasse zählen,
und kriege es nicht hin.

Ich habe in der angehängten Beispieldatei eine Tabelle, die vier Kisten auflistet.
Jede Kiste hat eine Bezeichnung und ein Gewicht.

.xlsm   20190728_LB1972_Kistenerfassen.xlsm (Größe: 30,77 KB / Downloads: 1)

Mit dem Kopf "Kisten erfassen" möchte ich diese in einer definierten Klasse  "cls_Kiste" erfassen,
und anschließend die Instanzen zählen und als Info ausgeben.

Definition von cls_Kiste (Klassenmodul):
Code:
Option Explicit


Private mstrBezeichnung As String
Private msngGewicht As Single
Private mKST1 As cls_Kiste



'---------------------------------------------------Bezeichnung-------------------------
Public Property Get Bezeichnung() As String
   Bezeichnung = mstrBezeichnung
End Property
Public Property Let Bezeichnung(ByVal vNewValue As String)
   mstrBezeichnung = vNewValue
End Property
'-------------------------------------------------Gewicht---------------------------
Public Property Get Gewicht() As Single
   Gewicht = msngGewicht
End Property
Public Property Let Gewicht(ByVal vNewValue As Single)
   msngGewicht = vNewValue
End Property
'-------------------------------------------------Collectionelemente zählen-------------------------------

Function Zaehlen() As Integer
   For Each mKST1 In Me
       mobkAnzahl.Add mKST1.Bezeichnung
   Next
       Zaehlen = mobkAnzahl.Count
End Function

Die Prozedur in dem "normalen" Modul "Arbeitsschritte" sieht wie folgt aus:
Code:
Option Explicit

Public myObjekt() As cls_Kiste
Public mobkAnzahl As New Collection


Sub Einsammeln()
   
   Dim i As Integer, k As Integer
   ReDim myObjekt(1 To Range("Tabelle").Rows.Count)
   
       For i = 1 To Range("Tabelle").Rows.Count
           Set myObjekt(i) = New cls_Kiste
           
           myObjekt(i).Bezeichnung = Range("Tabelle").Cells(i, 1).Value
           myObjekt(i).Gewicht = Range("Tabelle").Cells(i, 2).Value
       Next i
       
    MsgBox "Es wurden " & mobkAnzahl.Count & " Kisten erfasst." '"Hier sollte eine Info erfolgen, wie viele Kisten erfasst wurden."

End Sub
Mein (scheiternder) Plan sieht vor, ein Collection-Objekt "mobkAnzahl" zu definieren,
das in einer Funktion in cls_Kiste alle Instanzen einsammelt und anschließend mit mobkAnzahl.Count
das gewünschte Ergebnis bringt.
Allein, es funktioniert nicht und ich zweifle erheblich dran, ob mein Ansatz auch nur annähernd richtig ist.
Kann mir von euch jemand weiterhelfen?
Vielen Dank schon mal.
Gruß Ludwig
Top
#2
Hallöchen,

wenn Du das Klassenobjekt erzeugst, solltest Du es der Collection im Modul hinzufügen und nicht im Klassenmodul.
.      \\\|///      Hoffe, geholfen zu haben.
       ( ô ô )      Grüße, André aus G in T  
  ooO-(_)-Ooo    (Excel 97-2019+365)
Top
#3
Hallo Andre,

danke für deine schnelle Antwort.
Der von dir vorgeschlagene Weg funktioniert natürlich.

Ich vermute, dass es aber hier noch eine direkte Lösung geben müsste,
die das Zählen der Instanzen mit einem im Klassenmodul gekapselten Code ermöglicht.
Ich stelle mir etwas vor, das man "von außerhalb cls_Kiste nicht sieht", und eine Ausgabemöglichkeit
in etwa
Code:
MsgBox "Es wurden " & cls_Kiste.Zaehlen & " Kisten erfasst."

ermöglicht.
Gibt es diese Möglichkeit? Wie kriegt man das hin?
Gruß Ludwig
Top
#4
Hi Ludwig.

die Funktion wird nur ausgeführt, wenn sie auch aufgerufen wird. Du kannst schauen, ob Du einen Funktionsaufruf oder das ...add gleich direkt an geeigneter Stelle in Dein Klassenmodul einbauen kannst,
.      \\\|///      Hoffe, geholfen zu haben.
       ( ô ô )      Grüße, André aus G in T  
  ooO-(_)-Ooo    (Excel 97-2019+365)
Top
#5
Ich würde eine weitere Klasse cls_Kisten einführen. Das macht das ganze IMHO einfacher.
Code:
Option Explicit

Dim mKisten As New Collection

Sub Add(newKiste As cls_Kiste)
   mKisten.Add newKiste
End Sub

Function countKisten() As Long
   countKisten = mKisten.Count
End Function
Und im Modul

Code:
Option Explicit

Public myKisten As New cls_Kisten

Sub EinsammelnA()
   
   Dim i As Integer, k As Integer
   Dim sngKiste As cls_Kiste
   
       For i = 1 To Range("Tabelle").Rows.Count
           
           Set sngKiste = New cls_Kiste
           sngKiste.Bezeichnung = Range("Tabelle").Cells(i, 1).Value
           sngKiste.Gewicht = Range("Tabelle").Cells(i, 2).Value
           
           myKisten.Add sngKiste
       Next i
       
    MsgBox "Es wurden " & myKisten.countKisten & " Kisten erfasst." '"Hier sollte eine Info erfolgen, wie viele Kisten erfasst wurden."

End Sub


Angehängte Dateien
.xlsm   20190728_LB1972_Kistenerfassen.xlsm (Größe: 32,66 KB / Downloads: 3)
Top
#6
Hi Storax,

vielen Dank für deine Antwort mit Programmcode.

Es funktioniert, aber ich durchdringe das ganze wohl noch nicht so recht.

So hatte ich eigentlich angenommen, dass wenn ich deinen Code im "normalen Modul" mit
Code:
    MsgBox "Es wurden " & myKisten.countKisten & " Kisten erfasst." '"Hier sollte eine Info erfolgen, wie viele Kisten erfasst wurden."

   For i = 1 To myKisten.countKisten
        MsgBox sngKiste(i).Gewicht
   Next i

ergänze, ich dann für jede Kiste die Gewichtsangabe erhalte. Das sieht VBA aber anders und reagiert bockig.

Ähnlich sprödes Verhalten seitens VBA erlebe ich, wenn ich etwas mit
Code:
For each sngKiste in MyKisten
  MsgBox sngKiste.Gewicht
next

versuche.

Geht so etwas vielleicht gar nicht?

Danke für weitere Hilfe.
Gruß Ludwig
Top
#7
Klar geht das, ich hatte die Collection cls_Kisten nicht "ausprogrammiert".
Ich habe auch eine For Each Schleife hinzugefügt.


PS Vergiß diese elende SystemHungarianNotation weg, ist ja grausam

Update: Man kann Item auch zum Default Member der Klasse machen


Angehängte Dateien
.xlsm   20190728_LB1972_Kistenerfassen.xlsm (Größe: 33,4 KB / Downloads: 8)
[-] Folgende(r) 1 Nutzer sagt Danke an Storax für diesen Beitrag:
  • LB1972
Top
#8
Chapeau!
Danke!
Das trifft genau das, wo ich hinwollte!
Eine Frage noch, Storax:
Dem Sachverhalt, dass deine Lösung "zwei verschränkte" Klassen beinhaltet, entnehme ich,
dass es mit einer, die sich dann selber zählt usw. nicht gehen wird.
Habe ich das richtig interpretiert?
Gruß und merci für deine Zeit
Ludwig
Top
#9
Man kann in einer Klasse nicht zählen, wie oft sie schon instanziert wurde. Ich wüßte jedenfalls nicht wie
und wenn wahrscheinlich mit API Calls usw. usf.

Ds Vorgehen mit cls_Kiste und cls_Kisten ist ähnlich zu Worksheet und Worksheets.

Auf diese Weise kannst Du auch übrigens einfach weitere Funktionen für Deine Kisten implementieren,
wie etwa die Ermittlung des Gesamt-Gewichts. Dazu ergänzt Du einfach die Klasse cls_Kisten um die
folgende Funktion
Zitat:Public Function gesGewicht() As Double
    Dim i As Long, res As Double
    For i = 1 To Kisten.Count
        res = res + Kisten(i).Gewicht
    Next i
    gesGewicht = res
End Function

Und schon kannst Du nach dem "Sammeln" der Kisten das Gesamt-Gewicht mit myKisten.gesGewicht ausgeben.

Hier weiteres zum Thema Custom Collection CLass

PS Was ist eine "verschränkte" Klasse?
Top
#10
:18: 

Gruß
Ludwig
Top


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste