{"id":55000423,"date":"2024-04-01T00:00:00","date_gmt":"2024-04-23T12:48:18","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=423"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Klassen_programmieren_unter_VBA","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Klassen_programmieren_unter_VBA\/","title":{"rendered":"Klassen programmieren unter VBA"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/54265a9c81824a719760b93770339d6c\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Neben den Standardmodulen gibt es in VBA-Projekten auch noch einen weiteren Typ von Modulen, n&auml;mlich die Klassenmodule. Diese kommen wiederum in zwei Ausf&uuml;hrungen: Es gibt alleinstehende Klassenmodule und eingebaute Klassenmodule, die den Code zu bestimmten Objekten enthalten &#8211; wie beispielsweise die Klassenmodule zu Formularen und Berichten in Access, zu Word-Dokumenten f&uuml;r das Dokument oder in Excel f&uuml;r Worksheet und Workbook. Auch in Outlook gibt es Klassenmodule. Wir wollen uns an dieser Stelle jedoch auf die alleinstehenden Klassenmodule konzentrieren, also auf solche, die wir selbst anlegen m&uuml;ssen. Hier schauen wir uns an, warum man diese &uuml;berhaupt nutzen sollte, welche Anwendungszwecke es gibt und welche Best Practices sich f&uuml;r uns etabliert haben.<\/b><\/p>\n<h2>Unterschied zwischen Standardmodulen, eingebauten Klassenmodulen und benutzerdefinierten Klassenmodulen<\/h2>\n<p>Zun&auml;chst einmal wollen wir den Unterschied zwischen den verschiedenen Typen von Modulen erl&auml;utern. <\/p>\n<h2>Standardmodule<\/h2>\n<p>Wir beginnen mit den Standardmodulen:<\/p>\n<ul>\n<li>Standardmodule sind einfache Container f&uuml;r VBA-Code, die in einer VBA-Projektdatei enthalten sind und die selbst hinzuf&uuml;gen m&uuml;ssen.<\/li>\n<li>Sie enthalten normalerweise Funktionen, Prozeduren und Variablen, die in verschiedenen Teilen des Projekts verwendet werden k&ouml;nnen.<\/li>\n<li>Ein Standardmodul kann Funktionen und Prozeduren enthalten, die unabh&auml;ngig voneinander sind und direkt vom Rest des Codes aufgerufen werden k&ouml;nnen.<\/li>\n<li>Standardmodule werden oft verwendet, um allgemeine Funktionen und Hilfsroutinen zu speichern, die von verschiedenen Teilen des Projekts ben&ouml;tigt werden.<\/li>\n<\/ul>\n<h2>Klassenmodule allgemein<\/h2>\n<p>Wir schauen uns erst einmal die allgemeinen Eigenschaften an, die allen Klassenmodulen gemein sind:<\/p>\n<ul>\n<li>Klassenmodule erm&ouml;glichen die Definition benutzerdefinierter Datenstrukturen, die als Objekte bezeichnet werden.<\/li>\n<li>Sie dienen dazu, spezifische Arten von Objekten zu definieren, die Eigenschaften, Methoden und Ereignisse haben k&ouml;nnen.<\/li>\n<li>Klassenmodule erm&ouml;glichen die Erstellung von Objekten mit spezifischen Verhaltensweisen und Datenstrukturen, was die Codeorganisation und -wiederverwendbarkeit verbessert.<\/li>\n<li>Sowohl eingebauten als auch alleinstehenden Klassenmodulen k&ouml;nnen wir benutzerdefinierte Eigenschaften, Methoden und Ereignisse hinzuf&uuml;gen.<\/li>\n<\/ul>\n<h2>Eingebaute Klassenmodule<\/h2>\n<p>Unter eingebauten Klassenmodulen verstehen wir solche Klassenmodule, wie sie beispielsweise in Word, Excel, Outlook oder Access automatisch mit den dortigen Objekten angelegt werden oder dort bereits vorhanden sind, wenn wir den VBA-Editor erstmalig &ouml;ffnen.<\/p>\n<p>Bild 1 zeigt ein Klassenmodul eines Word-Dokuments.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_002.png\" alt=\"Ein eingebautes Klassenmodul, hier in Word.\" width=\"524.6265\" height=\"271.7831\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Ein eingebautes Klassenmodul, hier in Word.<\/span><\/b><\/p>\n<ul>\n<li>Klassenmodule k&ouml;nnen Ereignisse enthalten, die es Objekten erm&ouml;glichen, auf bestimmte Aktionen zu reagieren, wie das &Ouml;ffnen oder Schlie&szlig;en einer Arbeitsmappe in Excel, das &Ouml;ffnen eines Word-Dokuments oder das Anzeigen eines Formulars in Access.<\/li>\n<li>Sie enthalten vorgefertigte Ereignisse, auf deren Basis wir Ereignisprozeduren implementieren k&ouml;nnen.<\/li>\n<\/ul>\n<h2>Alleinstehende Klassenmodule<\/h2>\n<p>Im Gegensatz zu den eingebauten Klassenmodulen k&ouml;nnen wir beliebig viele alleinstehende Klassenmodule erstellen. Dazu nutzen wir den Kontextmen&uuml;befehl <b>Einf&uuml;gen|Klassenmodul <\/b>des Projekt-Explorers (siehe Bild 2) oder den gleichnamigen Befehl der Men&uuml;leiste des VBA-Editors.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_001.png\" alt=\"Hinzuf&uuml;gen eines Klassenmoduls\" width=\"549.6265\" height=\"445.508\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Hinzuf&uuml;gen eines Klassenmoduls<\/span><\/b><\/p>\n<p>Damit erzeugen wir erst einmal einen neuen Eintrag im Projekt-Explorer, der standardm&auml;&szlig;ig <b>Klasse1 <\/b>genannt und direkt als neues Fenster im VBA-Editor angezeigt wird (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_003.png\" alt=\"Das neue Klassenmodul im Projekt-Explorer\" width=\"549.6265\" height=\"224.4309\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Das neue Klassenmodul im Projekt-Explorer<\/span><\/b><\/p>\n<p>In dieses Fenster k&ouml;nnen wir nun Code schreiben, genau wie in einem Standardmodul. Wir k&ouml;nnen den dort enthaltenen Code aber nicht so einfach ausf&uuml;hren in einem Standardmodul. Wir m&uuml;ssen die Klasse erst in Form eines Objekts instanziieren und dieses einer Objektvariablen zuweisen, damit wir auf seine Eigenschaften, Methoden oder Ereignisse zugreifen k&ouml;nnen.<\/p>\n<h2>Klassenmodul umbenennen<\/h2>\n<p>Als Erstes erledigen wir allerdings eine wichtige Aufgabe: Das Klassenmodul soll einen anderen Namen als <b>Klasse1 <\/b>erhalten (siehe Bild 4). <\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_004.png\" alt=\"Umbenennen eines Klassenmoduls\" width=\"474.6267\" height=\"371.2061\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Umbenennen eines Klassenmoduls<\/span><\/b><\/p>\n<p>Zu Beispielzwecken wollen wir die Klasse <b>clsAdresse <\/b>nennen. Das Pr&auml;fix <b>cls <\/b>steht f&uuml;r <b>Class<\/b>, also Klasse. Mit der Klasse wollen wir die typischen Eigenschaften einer Adresse aufnehmen und abfragen k&ouml;nnen. Nach dem Umbenennen sehen wir den neuen Klassennamen gleich an mehreren Stellen (siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_005.png\" alt=\"Der neue Klassenname tritt gleich an drei Stellen in Erscheinung.\" width=\"474.6267\" height=\"332.8331\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Der neue Klassenname tritt gleich an drei Stellen in Erscheinung.<\/span><\/b><\/p>\n<h2>Welche Elemente machen eine Klasse nach au&szlig;en hin aus?<\/h2>\n<p>Es gibt drei verschiedene Elemente, die wir von au&szlig;en nutzen k&ouml;nnen, die eine Klasse charakterisieren:<\/p>\n<ul>\n<li><b>Eigenschaften<\/b>: Eigenschaften erscheinen als lesbare und\/oder schreibbare Eigenschaften. Wir k&ouml;nnen f&uuml;r Klassen beliebig viele Eigenschaften festlegen und durch bestimmte Schreibweisen angeben, ob man diese bei der Programmierung der Klasse lesend, schreibend oder lesend und schreibend zugreifbar m&ouml;chte.<\/li>\n<li><b>Methoden<\/b>\/<b>Funktionen<\/b>: Dies sind im Prinzip <b>Sub<\/b>&#8211; und <b>Function<\/b>-Prozeduren wie in Klassenmodulen, nur dass sie nur aufgerufen werden k&ouml;nnen, wenn es eine Objektvariable mit einem Verweis auf eine Instanz der Klasse gibt, &uuml;ber die wir auf diese Methoden und Funktionen zugreifen k&ouml;nnen. Was Instanzen und Objektvariablen sind, erl&auml;utern wir weiter unten.<\/li>\n<li><b>Ereignisse<\/b>: Ereignisse sind eine echte Besonderheit von Klassenmodulen gegen&uuml;ber Standardmodulen.  Die Ereignisse von eingebauten Standardmodulen werden meist durch Benutzeraktionen ausgel&ouml;st. Wir k&ouml;nnen dann Ereignisprozeduren programmieren, die als Reaktion auf solche Benutzeraktionen gestartet werden sollen &#8211; zum Beispiel beim &Ouml;ffnen eines Dokuments, beim Anklicken einer Schaltfl&auml;che, beim Absenden einer E-Mail et cetera. Bei Klassenmodulen k&ouml;nnen wir allerdings selbst genau festlegen, wann ein solches Ereignis ausgel&ouml;st werden soll. Wie das gelingt und wozu wir das nutzen k&ouml;nnen, zeigen wir ebenfalls weiter unten.<\/li>\n<\/ul>\n<h2>Welche Elemente gibt es noch innerhalb einer Klasse?<\/h2>\n<p>Innerhalb von Klassenmodulen k&ouml;nnen wir all die von herk&ouml;mmlichen Modulen bekannten Elemente nutzen &#8211; Prozeduren, Funktionen, Variablen, Konstanten und so weiter.<\/p>\n<p>Es gibt allerdings einen wichtigen Unterschied zwischen den Eigenschaften, Methoden und Ereignissen, die wir bei Vorhandensein einer Instanz der Klasse nutzen k&ouml;nnen, und den &uuml;brigen Elementen: Die Eigenschaften, Methoden und Ereignisse sind &ouml;ffentliche Elemente, wir m&uuml;ssen diese daher mit dem Schl&uuml;sselwort <b>Public <\/b>deklarieren. Die Elemente, die wir nur innerhalb des Klassenmoduls nutzen wollen, deklarieren wir mit dem Schl&uuml;sselwort <b>Private<\/b>. Diese sind nicht von au&szlig;erhalb sichtbar.<\/p>\n<h2>Instanziieren einer Klasse<\/h2>\n<p>Da unsere Klasse noch keine Elemente enth&auml;lt, also keine Eigenschaften, Methoden oder Ereignisse, behelfen wir uns f&uuml;r die Beschreibung der Instanziierung einer Klasse einer eingebauten Klasse. In diesem Fall wollen wir uns die Klasse <b>Collection <\/b>ansehen. Diese ist eine Klasse, die den Umgang mit Auflistungen vereinfacht. Wir k&ouml;nnen dieser Klasse mit der <b>Add<\/b>-Methode Elemente hinzuf&uuml;gen, mit <b>Remove <\/b>Elemente entfernen, mit <b>Count <\/b>die enthaltenen Elemente z&auml;hlen und mit <b>Item(i) <\/b>auf das Element mit dem Index <b>i <\/b>zugreifen.<\/p>\n<p>Vor allem aber m&uuml;ssen wir, bevor wir das alles erledigen k&ouml;nnen, eine Instanz der Klasse erstellen und diese mit einer Objektvariablen referenzieren. Umgangssprachlich redet man auch von Speichern eines Objekts in einer Objektvariablen, was aber nicht ganz korrekt ist: Tats&auml;chlich wird in einer Objektvariablen n&auml;mlich nur eine Zahl als Zeiger auf die Speicherposition des Objekts gespeichert. Das Objekt selbst befindet sich an der angegebenen Stelle im Speicher.<\/p>\n<p>Doch schreiten wir zur Tat. Wir ben&ouml;tigen zwei Schritte, um eine Objektvariable mit einer neuen Instanz eines Objekts zu f&uuml;llen:<\/p>\n<ul>\n<li>das Deklarieren der Objektvariablen und<\/li>\n<li>das Instanziieren des Objekts auf Basis der Klasse und Zuweisen an die Objektvariable.<\/li>\n<\/ul>\n<p>Bei der Deklaration verwenden wir den Namen der Klasse als Datentyp:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objCollection<span style=\"color:blue;\"> As <\/span>Collection<\/pre>\n<p>Das Instanziieren erfolgt mit dem Schl&uuml;sselwort <b>New <\/b>mit dem Typ des zu erzeugenden Elements, hier <b>Collection<\/b>, und dem Zuweisen an die Objektvariable:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> objCollection = <span style=\"color:blue;\">New<\/span> Collection<\/pre>\n<p>Wir k&ouml;nnen diese beiden Anweisungen sogar in einer einzigen Anweisung zusammenfassen:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objCollection<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> Collection<\/pre>\n<h2>Wo deklarieren und wo instanziieren wir Klassen?<\/h2>\n<p>Bevor wir das Instanziieren anhand der Collection-Klasse ausprobieren, ben&ouml;tigen wir ein Modul, dem wir den Code hinzuf&uuml;gen k&ouml;nnen. Dazu erstellen wir ein neues Standardmodul, das wir unter dem Namen <b>mdlBeispiele <\/b>speichern. Warum ein Standardmodul und nicht etwa ein alleinstehendes Klassenmodul, wo wir doch schon &uuml;ber diesen Modultyp reden? Weil wir diese Anweisungen direkt ausprobieren wollen, und das gelingt am einfachsten in Standardmodulen. Hier legen wir eine Prozedur an, welche die beiden oben genannten Schritte enth&auml;lt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CollectionInstanziieren()\r\n     <span style=\"color:blue;\">Dim <\/span>col<span style=\"color:blue;\"> As <\/span>Collection\r\n     <span style=\"color:blue;\">Set<\/span> col = <span style=\"color:blue;\">New<\/span> Collection\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wenn wir diese Prozedur ausf&uuml;hren, geschieht nichts Sichtbares. Dazu ben&ouml;tigen wir noch einige weitere Anweisungen wie hier:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CollectionInstanziieren()\r\n     <span style=\"color:blue;\">Dim <\/span>objCollection<span style=\"color:blue;\"> As <\/span>Collection\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCollection = <span style=\"color:blue;\">New<\/span> Collection\r\n     objCollection.Add \"Element 1\"\r\n     objCollection.Add \"Element 2\"\r\n     For i = 1 To objCollection.Count\r\n         <span style=\"color:blue;\">Debug.Print<\/span> objCollection.Item(i)\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Dies erstellt ein neues <b>Collection<\/b>-Objekt in der Variablen <b>objCollection<\/b>, f&uuml;gt mit der <b>Add<\/b>-Methode zwei Elemente hinzu und durchl&auml;uft anschlie&szlig;end eine Schleife &uuml;ber alle Elemente, wobei sie deren Inhalt im Direktbereich des VBA-Editors ausgibt. Die Objektvariable wird nach dem Verlassen der Prozedur automatisch zerst&ouml;rt, weil sich der G&uuml;ltigkeitsbereich durch die Deklaration innerhalb der Prozedur auf diese beschr&auml;nkt. Um das zu &auml;ndern, k&ouml;nnen wir nun noch die Deklaration von <b>objCollection <\/b>aus der Prozedur herausziehen und diese im Kopf des Standardmoduls speichern:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objCollection<span style=\"color:blue;\"> As <\/span>Collection<\/pre>\n<p>Dadurch verl&auml;ngern wir die Lebenszeit dieses Objekts. Wir instanziieren es wieder und f&uuml;gen zwei Elemente hinzu:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CollectionFuellen()\r\n     <span style=\"color:blue;\">Set<\/span> objCollection = <span style=\"color:blue;\">New<\/span> Collection\r\n     objCollection.Add \"Element 1\"\r\n     objCollection.Add \"Element 2\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Da die Variable nun au&szlig;erhalb der Prozedur gespeichert wurde, k&ouml;nnen wir von einer weiteren Prozedur aus, die wir anschlie&szlig;end aufrufen, immer noch auf die Inhalte der Collection zugreifen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CollectionAuslesen()\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     For i = 1 To objCollection.Count\r\n         <span style=\"color:blue;\">Debug.Print<\/span> objCollection.Item(i)\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Nun wissen wir schon einmal, wie wir Objekte auf Basis von eingebauten Klassen instanziieren. Nun wollen wir eine eigene Klasse programmieren und diese instanziieren und nutzen.<\/p>\n<h2>Sichtbarkeit der Elemente einer Klasse<\/h2>\n<p>Dazu kehren wir zu der Klasse <b>clsAdresse<\/b> zur&uuml;ck, die wir bereits weiter oben erstellt haben. Dieser Klasse f&uuml;gen wir nun eine erste &ouml;ffentliche Eigenschaft namens <b>Vorname <\/b>hinzu. Diese deklarieren wir einfach als &ouml;ffentliche Variable des Typs <b>String<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Vorname<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Die Klasse sieht bisher also wie in Bild 6 aus. Dennoch k&ouml;nnen wir die Klasse bereits als vollwertige Klasse einsetzen. Dazu erstellen wir ein weiteres Modul, dem wir die Deklaration einer Objektvariablen auf Basis unserer Klasse hinzuf&uuml;gen:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_010.png\" alt=\"Der bisherige Code der Klasse\" width=\"424.6267\" height=\"187.1398\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Der bisherige Code der Klasse<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objAdresse<span style=\"color:blue;\"> As <\/span>clsAdresse<\/pre>\n<p>Instanziieren wir die Klasse nun in einer Prozedur, k&ouml;nnen wir anschlie&szlig;end nach Eingabe des Variablennamens und des Punkts per IntelliSense auf die bisher einzige Eigenschaft der Klasse zugreifen &#8211; siehe Bild 7.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_006.png\" alt=\"Instanziieren und Verwenden einer benutzerdefinierten Klasse\" width=\"424.6267\" height=\"238.609\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Instanziieren und Verwenden einer benutzerdefinierten Klasse<\/span><\/b><\/p>\n<p>Wir weisen der Eigenschaft wie folgt einen Wert zu:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AdresseInstanziieren()\r\n     <span style=\"color:blue;\">Set<\/span> objAdresse = <span style=\"color:blue;\">New<\/span> clsAdresse\r\n     objAdresse.Vorname = \"Andr&eacute;\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>In einer weiteren Prozedur k&ouml;nnen wir nun immer noch auf die Eigenschaft zugreifen, da das Objekt in der Variablen <b>objAdresse <\/b>des Standardmoduls gespeichert und somit immer noch g&uuml;ltig ist:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AdresseAuslesen()\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objAdresse.Vorname\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Damit haben wir unsere erste benutzerdefinierte Klasse programmiert, ein Objekt auf seiner Basis instanziiert und eine Eigenschaft zugewiesen und ausgelesen.<\/p>\n<h2>Zerst&ouml;ren eines Objekts<\/h2>\n<p>In einer weiteren Prozedur sorgen wir nun daf&uuml;r, dass die Objektvariable geleert und somit auch die enthaltene Instanz der Klasse <b>clsAdresse <\/b>zerst&ouml;rt wird:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AdresseZerstoeren()\r\n     <span style=\"color:blue;\">Set<\/span> objAdresse = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wenn wir danach erneut die Prozedur <b>AdresseAuslesen <\/b>aufrufen, erhalten wir die Fehlermeldung aus Bild 8. Die Objektvariable <b>objAdresse <\/b>ist leer, daher k&ouml;nnen wir nicht mehr auf ihre Eigenschaften zugreifen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_007.png\" alt=\"Fehler beim Zugriff auf eine leere Objektvariable\" width=\"649.627\" height=\"274.4455\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Fehler beim Zugriff auf eine leere Objektvariable<\/span><\/b><\/p>\n<h2>Testen, ob eine Objektvariable leer ist<\/h2>\n<p>Wenn wir pr&uuml;fen wollen, ob die Objektvariable ein Objekt enth&auml;lt, k&ouml;nnen wir diese wie folgt mit dem Operator <b>Is Nothing <\/b>untersuchen. <\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AdresseAuslesen()\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objAdresse Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> objAdresse.Vorname\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> \"objAdresse ist leer.\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Weitere Eigenschaften<\/h2>\n<p>Unsere Klasse soll nun nicht nur eine Eigenschaft anbieten, sondern gleich mehrere. Dazu f&uuml;gen wir die Eigenschaften zun&auml;chst als &ouml;ffentliche Variablen hinzu, zum Beispiel so:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Firma<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>Anrede<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>Vorname<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>Nachname<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>Strasse<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>PLZ<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>Ort<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>Land<span style=\"color:blue;\"> As String<\/span><\/pre>\n<h2>Eigenschaften schreib- und\/oder lesbar machen<\/h2>\n<p>Mit den auf diese Weise deklarierten Eigenschaften k&ouml;nnen wir jede Eigenschaft sowohl lesen als auch schreiben. Das ist nicht immer gew&uuml;nscht. Auch bei den eingebauten VBA-Klassen gibt es einige Eigenschaften, die nur gelesen, aber nicht geschrieben werden d&uuml;rfen. Aber wie realisieren wir das? Gibt es bestimmte Schl&uuml;sselw&ouml;rter, mit denen wir dies angeben k&ouml;nnen? Nein, das ist nicht der Fall. Wir m&uuml;ssen dazu einen anderen Weg gehen und schauen uns das anhand der Eigenschaft <b>Firma <\/b>an. Wir gehen in zwei Schritten vor. Im ersten Schritt stellen wir den G&uuml;ltigkeitsbereich von <b>Public <\/b>auf <b>Private <\/b>um. Au&szlig;erdem f&uuml;gen wir dieser nun privaten Variablen das Pr&auml;fix <b>m_ <\/b>hinzu:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Firma<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Nun k&ouml;nnen wir diese Eigenschaft nach dem Erstellen eines Objekts auf Basis der Klasse <b>clsAdresse <\/b>weder lesen noch schreiben. Um dies umzusetzen, legen wir zwei sogenannte <b>Property<\/b>-Prozeduren an. Die erste verwendet neben <b>Public Property <\/b>das Schl&uuml;sselwort <b>Let<\/b>, was bedeutet, dass wir mit dieser Prozedur Werte zuweisen k&ouml;nnen. Diese landen zun&auml;chst im Parameter <b>str<\/b>, den wir dann innerhalb der Prozedur der privaten Variablen <b>m_Firma <\/b>zuweisen:<\/p>\n<pre><span style=\"color:blue;\">Public Property Let <\/span>Firma(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Firma = str\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Damit k&ouml;nnen wir der privaten Variablen aber lediglich Werte zuweisen. Um den Wert von <b>m_Firma <\/b>auch noch auslesen zu k&ouml;nnen, ben&ouml;tigen wir eine weitere <b>Property<\/b>-Prozedur, diesmal mit dem Schl&uuml;sselwort <b>Get<\/b>. Diese hat keinen Parameter, sondern gibt wie eine herk&ouml;mmliche Funktion den Wert zur&uuml;ck, den wir dem Prozedurnamen innerhalb der Prozedur zuweisen -hier also <b>m_Firma<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Public Property Get <\/span>Firma()<span style=\"color:blue;\"> As String<\/span>\r\n     Firma = m_Firma\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Das ist leider ein wenig Aufwand. Der Code f&uuml;r die restlichen Eigenschaften, umgewandelt in private Variablen mit <b>Property Let<\/b>&#8211; und <b>Property Get<\/b>-Prozeduren, ist recht umfangreich. Im Artikel <b>VBA-Editor: Klasseneigenschaften per Mausklick <\/b>(<b>www.vbentwickler.de\/422<\/b>) beschreiben wir allerdings, wie Du mit einem Mausklick die Zeile <b>Public Firma As String <\/b>in das obige Konstrukt umwandeln kannst. Das Ergebnis sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Anrede<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Private <\/span>m_Vorname<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Private <\/span>m_Nachname<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Private <\/span>m_Strasse<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Private <\/span>m_PLZ<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Private <\/span>m_Ort<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Private <\/span>m_Land<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>Anrede(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Anrede = str\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Anrede()<span style=\"color:blue;\"> As String<\/span>\r\n     Anrede = m_Anrede\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>Vorname(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Vorname = str\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Vorname()<span style=\"color:blue;\"> As String<\/span>\r\n     Vorname = m_Vorname\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>Nachname(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Nachname = str\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Nachname()<span style=\"color:blue;\"> As String<\/span>\r\n     Nachname = m_Nachname\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>Strasse(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Strasse = str\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Strasse()<span style=\"color:blue;\"> As String<\/span>\r\n     Strasse = m_Strasse\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>PLZ(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_PLZ = str\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>PLZ()<span style=\"color:blue;\"> As String<\/span>\r\n     PLZ = m_PLZ\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>Ort(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Ort = str\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Ort()<span style=\"color:blue;\"> As String<\/span>\r\n     Ort = m_Ort\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Let <\/span>Land(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Land = str\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Land()<span style=\"color:blue;\"> As String<\/span>\r\n     Land = m_Land\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Was haben wir damit erreicht? Wir k&ouml;nnen nun wie in Bild 9 auf alle Eigenschaften lesend und schreibend zugreifen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_008.png\" alt=\"Nun k&ouml;nnen wir auf alle Eigenschaften per IntelliSense zugreifen.\" width=\"424.6267\" height=\"310.6149\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Nun k&ouml;nnen wir auf alle Eigenschaften per IntelliSense zugreifen.<\/span><\/b><\/p>\n<p>Das ist allerdings wenig spektakul&auml;r, wenn man bedenkt, dass dies auch mit einer Deklaration wie der folgenden m&ouml;glich ist:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Firma<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Wozu also all die zus&auml;tzlichen Anweisungen? Wir gewinnen dadurch mindestens die folgenden M&ouml;glichkeiten:<\/p>\n<ul>\n<li>Indem wir die <b>Property Get<\/b>-Methode weglassen, k&ouml;nnen wir die Eigenschaft nur schreibbar machen und indem wir die <b>Property Let<\/b>\/<b>Set<\/b>-Methode weglassen, machen die Eigenschaft nur lesbar.<\/li>\n<li>Wir k&ouml;nnen beim Zuweisen eines Wertes oder beim Auslesen neben der eigentlichen Aktion noch weitere Schritte durchf&uuml;hren. Diese brauchen wir dazu nur in die <b>Property Get<\/b>&#8211; oder die <b>Property Let<\/b>\/<b>Set<\/b>-Methode einzuf&uuml;gen.<\/li>\n<\/ul>\n<p>Warum schreiben wir hier von <b>Property Let<\/b>\/<b>Set<\/b>-Methode? Das erl&auml;utern wir weiter unten.<\/p>\n<h2>Eigenschaft nur schreibbar machen<\/h2>\n<p>Wenn wir wollen, dass eine Eigenschaft nur gesetzt, aber nicht gelesen werden kann, deklarieren wir diese wie folgt. Wir f&uuml;gen die Deklaration der Eigenschaft <b>NurSchreiben <\/b>unserer Klasse <b>clsAdressen<\/b> hinzu:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_NurSchreiben<span style=\"color:blue;\"> As String<\/span> \r\n<span style=\"color:blue;\">Public Property Let <\/span>NurSchreiben(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_NurSchreiben = str\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Wenn wir die Klasse instanziieren, k&ouml;nnen wir den Wert f&uuml;r <b>NurSchreiben <\/b>zwar setzen. Der Versuch, den Wert dieser Eigenschaft zu lesen, schl&auml;gt allerdings fehl (siehe Bild 10).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_009.png\" alt=\"Fehler beim Versuch, eine nur schreibbare Eigenschaft auszulesen\" width=\"649.627\" height=\"262.7299\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Fehler beim Versuch, eine nur schreibbare Eigenschaft auszulesen<\/span><\/b><\/p>\n<h2>Eigenschaft nur lesbar machen<\/h2>\n<p>Umgekehrt k&ouml;nnen wir Eigenschaften definieren, die nur gelesen werden k&ouml;nnen. Dazu deklarieren wir wie folgt nur die <b>Property Get<\/b>-Prozedur:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_NurLesen<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>NurLesen()<span style=\"color:blue;\"> As String<\/span>\r\n     NurLesen = m_NurLesen\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Wie in Bild 11 zu sehen, erhalten wir hier beim Versuch, die Eigenschaft zu setzen, eine Fehlermeldung.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_011.png\" alt=\"Fehler beim Versuch, eine nur lesbare Eigenschaft zu setzen\" width=\"649.627\" height=\"221.6574\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Fehler beim Versuch, eine nur lesbare Eigenschaft zu setzen<\/span><\/b><\/p>\n<h2>Wann nur schreibbare und wann lesbare Eigenschaften nutzen?<\/h2>\n<p>Die grobe Empfehlung dazu lautet: Verwende nur die Property Let\/Get\/Set-Prozeduren, die f&uuml;r den Einsatz der Klasse n&ouml;tig sind. Nat&uuml;rlich kann man einfach immer beide Property-Prozeduren angeben, was in vielen F&auml;llen okay ist. Wenn es aber Eigenschaften gibt, die nur schreibbar oder nur lesbar sein sollen, stelle auch nur die entsprechenden Property-Prozeduren zur Verf&uuml;gung.<\/p>\n<h2>Warum gibt es Property Let und Property Set-Methoden zum Setzen von Eigenschaften?<\/h2>\n<p>F&uuml;r das Lesen einer Eigenschaft stellen wir jeweils die <b>Property Get<\/b>-Eigenschaft bereit. F&uuml;r das Schreiben von Eigenschaften gibt es jedoch zwe Varianten: Die bisher verwendete <b>Property Let<\/b>-Eigenschaft und die noch vorzustellende <b>Property Set<\/b>-Eigenschaft. Der Unterschied ist einfach zu erkl&auml;ren: <b>Property Let <\/b>verwenden wir f&uuml;r alle skalaren Eigenschaften, also f&uuml;r einfache Datentypen wie <b>Boolean<\/b>, <b>Byte<\/b>, <b>Currency<\/b>, <b>Date<\/b>, <b>Decimal<\/b>, <b>Double<\/b>, <b>Integer<\/b>, <b>Long<\/b>, <b>Single<\/b>, <b>String <\/b>oder <b>Variant<\/b>. <b>Property Set <\/b>verwenden wir, wenn die Eigenschaft eine Objektreferenz aufnehmen soll &#8211; also beispielsweise, wenn wir ein Word-Dokument, einen Excel-Range oder ein Access-Recordset referenzieren wollen, oder auch eine benutzerdefinierte Klasse, wie wir sie gerade erstellen.<\/p>\n<h2>Methoden und Funktionen in Klassen<\/h2>\n<p>Damit kommen wir zu einer weiteren Art von Elementen, die Klassen nach au&szlig;en hinzu f&uuml;r die Interaktion bereitstellen: Methoden und Funktionen. Eine Methode oder Funktion einer Klasse ist nichts anderes als eine herk&ouml;mmliche <b>Sub<\/b>&#8211; oder <b>Function<\/b>-Prozedur &#8211; sie werden lediglich dadurch charakterisiert, dass sie innerhalb einer Klasse definiert werden und durch das Schl&uuml;sselwort <b>Public<\/b> als &ouml;ffentliche Methoden oder Funktionen nach au&szlig;en bereitgestellt werden. Im Gegensatz zu herk&ouml;mmlichen <b>Sub<\/b>&#8211; oder <b>Function<\/b>-Prozeduren aus Standardmodulen, die wir einfach aufrufen k&ouml;nnen, m&uuml;ssen wir vor der Verwendung der Methoden oder Funktionen einer Klasse zuerst ein Objekt auf Basis dieser Klasse erstellen. Erst dann k&ouml;nnen wir &uuml;ber eine &auml;hnliche Syntax wie bei den Eigenschaften auf diese zugreifen. <\/p>\n<h2>Beispiel f&uuml;r eine Methode: Leeren der Eigenschaften<\/h2>\n<p>Ein einfaches Beispiel ist eine Methode namens <b>Leeren<\/b>. Diese definieren wir im Klassenmodul <b>clsAdresse <\/b>wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Leeren()\r\n     m_Firma = \"\"\r\n     m_Anrede = \"\"\r\n     m_Vorname = \"\"\r\n     m_Nachname = \"\"\r\n     m_Strasse = \"\"\r\n     m_PLZ = \"\"\r\n     m_Ort = \"\"\r\n     m_Land = \"\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Methode leert alle privaten Variablen der Klasse, die gegebenenfalls zuvor gef&uuml;llt wurden. Wenn wir den Aufruf dieser Methode programmieren wollen, w&auml;hlen wir diesen nach der Eingabe des Objektnamens gefolgt von einem Punkt wie in Bild 12 per IntelliSense aus. Wenn wir diese Prozedur nun ausf&uuml;hren, erhalten wir bei Abfrage der zuvor gef&uuml;llten Eigenschaften <b>Anrede<\/b>, <b>Vorname <\/b>und <b>Nachname <\/b>leere Zeichenketten als Ergebnis. Die Methode wird in der IntelliSense-Liste mit einem anderen Symbol als die Eigenschaften angezeigt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_02\/pic_423_012.png\" alt=\"Festlegen des Aufrufs einer Methode der Klasse\" width=\"424.6267\" height=\"350.8944\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Festlegen des Aufrufs einer Methode der Klasse<\/span><\/b><\/p>\n<h2>Beispiel f&uuml;r eine Funktion: Zusammenstellen der Adresse<\/h2>\n<p>Ein sch&ouml;nes Beispiel f&uuml;r eine Funktion stellt uns die Adresse auf Basis der zuvor eingegebenen Adressinformationen zusammen. Wir definieren diese Funktion in der Klasse <b>clsAdresse <\/b>wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AdresseHolen()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strAdresse<span style=\"color:blue;\"> As String<\/span>\r\n     strAdresse = strAdresse & m_Firma & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strAdresse = strAdresse & m_Anrede & \" \" _\r\n         & m_Vorname & \" \" & m_Nachname & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strAdresse = strAdresse & m_Strasse & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strAdresse = strAdresse & m_PLZ & \" \" & m_Ort\r\n     AdresseHolen = strAdresse\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Diese Funktion stellt ohne weitere Pr&uuml;fung, ob auch alle Daten angegeben wurden, einen Adressblock zusammen und gibt diesen als Funktionsergebnis zur&uuml;ck. Zu Testzwecken verwenden wir die folgende Prozedur, due zun&auml;chst die Eigenschaften der Adresse &uuml;bergibt und dann die Funktion <b>AdresseHolen <\/b>aufruft. Das Ergebnis landet per <b>Debug.Print <\/b>im Direktbereich:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Adressblock()\r\n     <span style=\"color:blue;\">Set<\/span> objAdresse = <span style=\"color:blue;\">New<\/span> clsAdresse\r\n     objAdresse.Firma = \"Minhorst und Minhorst GbR\"\r\n     objAdresse.Anrede = \"Herr\"\r\n     objAdresse.Vorname = \"Andr&eacute;\"\r\n     objAdresse.Nachname = \"Minhorst\"\r\n     objAdresse.Strasse = \"Borkhofer Str. 17\"\r\n     objAdresse.PLZ = \"47137\"\r\n     objAdresse.Ort = \"Duisburg\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> objAdresse.AdresseHolen\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Auch die Funktion wird in der IntelliSense-Liste mit dem gleichen Symbol wie die Methoden angezeigt.<\/p>\n<h2>Nicht &ouml;ffentliche Sub- und Function-Methoden in Klassen<\/h2>\n<p>Es kann vorkommen, dass wir <b>Sub<\/b>&#8211; oder <b>Function<\/b>-Prozeduren innerhalb der Klasse ben&ouml;tigen, die nicht als &ouml;ffentliche Methoden oder Funktionen angeboten werden sollen. Kein Problem: Diese deklarieren wir einfach mit dem Schl&uuml;sselwort <b>Private<\/b>.<\/p>\n<h2>Unterschiede zwischen Membervariablen und anderen Variablen<\/h2>\n<p>Das Gleiche gilt f&uuml;r Variablen. Weiter oben haben wir einige private Variablen deklariert, deren Name mit dem Pr&auml;fix <b>m_ <\/b>beginnt. Warum eigentlich? Weil wir die Variablen, die eigentlich nur als Aufbewahrung f&uuml;r die &ouml;ffentlichen Eigenschaften dienen, auf besondere Art kennzeichnen wollen.<\/p>\n<p>Wenn wir innerhalb der Klasse weitere Variablen ben&ouml;tigen, die nicht &uuml;ber Eigenschaften verf&uuml;gbar sein, sondern die einfach zum Zwischenspeichern von Informationen dienen sollen, deklarieren wir diese mit den &uuml;blichen Pr&auml;fixen, also beispielsweise <b>str <\/b>f&uuml;r <b>String <\/b>oder <b>lng <\/b>f&uuml;r <b>Long<\/b>. Allerdings erhalten sie, weil wir diese nicht &ouml;ffentlich verf&uuml;gbar machen wollen, das Schl&uuml;sselwort <b>Private<\/b>.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Artikel liefert die Grundlagen zur Klassenprogrammierung. Im Artikel <b>Ereignisse in Klassen programmieren <\/b>(<b>www.vbentwickler.de\/425<\/b>) schauen wir uns an, wie wir Ereignisse programmieren.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>KlassenProgrammierenInVBUndVBA.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/155392F3-DDF2-43DD-BA36-BD5559DE07C7\/vbe_423.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Neben den Standardmodulen gibt es in VBA-Projekten auch noch einen weiteren Typ von Modulen, n&auml;mlich die Klassenmodule. Diese kommen wiederum in zwei Ausf&uuml;hrungen: Es gibt alleinstehende Klassenmodule und eingebaute Klassenmodule, die den Code zu bestimmten Objekten enthalten &#8211; wie beispielsweise die Klassenmodule zu Formularen und Berichten in Access, zu Word-Dokumenten f&uuml;r das Dokument oder in Excel f&uuml;r Worksheet und Workbook. Auch in Outlook gibt es Klassenmodule. Wir wollen uns an dieser Stelle jedoch auf die alleinstehenden Klassenmodule konzentrieren, also auf solche, die wir selbst anlegen m&uuml;ssen. Hier schauen wir uns an, warum man diese &uuml;berhaupt nutzen sollte, welche Anwendungszwecke es gibt und welche Best Practices sich f&uuml;r uns etabliert haben.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66022024,662024,44000004,44000025],"tags":[],"yst_prominent_words":[],"class_list":["post-55000423","post","type-post","status-publish","format-standard","hentry","category-66022024","category-662024","category-Loesungen","category-VBAProgrammierung"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000423","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000423"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000423\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000423"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000423"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000423"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000423"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}