20
MASTER CLASS ADDISON-WESLEY [ in Kooperation mit ] Michael Schwimmer Excel VBA Einstieg für Anspruchsvolle

Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 2: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

91

3Klassen

3.1 Was Sie in diesem Kapitel erwartet

In diesem Kapitel geht es darum, zu zeigen, was Klassen sind und warum Siediese viel häufiger einsetzen sollten.

Ein kleines Beispiel zur Manipulation von Initialisierungsdateien zeigt die Vor-gehensweise, mit der Sie möglichst unkompliziert und ohne umfangreiche Pla-nung kleinere Klassen anlegen können.

Außerdem wird gezeigt, wie Sie Steuerelemente dynamisch in eine Userformund ein Tabellenblatt einfügen und mit den Ereignissen dieser Steuerelementeumgehen. Dazu sind Klassen nämlich unerlässlich.

3.2 Allgemeines

Klassen bilden die Grundlage der objektorientierten Programmierung. Sie kap-seln die Funktionalität von Objekten, machen den Code übersichtlicher und mankann den übergeordneten Programmablauf besser verstehen.

Nahezu alle Objekte, die Sie in Excel benutzen, beruhen auf Klassen. Wenn Sieden Objektkatalog öffnen (Abbildung 3.1), werden Sie hunderte verschiedenerObjektklassen vorfinden.

Wenn Sie Codeteile besitzen, die Sie immer wieder benutzen, sollten Sie sichauf jeden Fall dazu entschließen, dafür eine eigene Klasse anzulegen, auchwenn es Ihnen anfangs etwas umständlich vorkommt. Die Vorteile sind enormund je häufiger Sie selbst Klassen schreiben und einsetzen, umso mehr werdenauch Sie davon überzeugt sein.

Page 3: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

92

Abbildung 3.1Klassen im Objektkatalog

Der wohl größte Vorteil ist der, dass Sie mit einer Klasse ein kompaktes, wie-derverwendbares Objekt mit Eigenschaften und Methoden besitzen und beimEinsatz dieser Klasse nicht mehr wissen müssen, wie die Funktionalität imple-mentiert ist. Es reicht, wenn Sie deren Eigenschaften, Methoden und Funktio-nen kennen.

Arbeiten Sie im Team, müssen Sie gemeinsam lediglich die öffentlichen Eigen-schaften und Methoden der Klassen festlegen. Die anderen Programmierer kön-nen anschließend die von Ihnen geschriebene Klassen benutzen, ohne dass diesesich mit dem Code auseinander setzen müssen, der dahinter steht. Für andere istalso Ihre Klasse eine Blackbox, vergleichbar mit einem Fernseher oder DVD-Player, bei denen man auch nicht unbedingt wissen muss, wie sie funktionieren,um diese Geräte benutzen zu können.

Vielleicht stellt sich irgendwann einmal heraus, dass sich in Ihre Klasse ein Feh-ler eingeschlichen hat. Dann brauchen Sie nicht in jeder Anwendung, die dieseKlasse benutzt, den Code anzupassen. Sie tauschen in den betroffenen Arbeits-mappen lediglich die fehlerhafte Klasse gegen eine fehlerfreie aus. Auch Erwei-terungen der Klasse sind ohne weiteres möglich und beeinflussen die bestehen-den Anwendungen nicht, wenn die vorhandenen Eigenschaften und Methodenbeibehalten werden.

Page 4: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Instanzierung

93

Finden Sie später Möglichkeiten, bestimmte Eigenschaften und Methoden derKlasse effizienter zu gestalten, nur zu. Es hat keine negativen Auswirkungen aufdie Anwendungen, die sich der Klasse bedienen. Sie können auch auf einfacheArt einen Schreibschutz für bestimmte Eigenschaften verwirklichen, indem Siedie Prozeduren �������� ��� und �������� �� ganz einfach weglassen.

Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden,die im Gegensatz zu den normalen Typen eine gewisse Eigenintelligenz besit-zen. Denkbar wären dann beispielsweise Typen, die in verschiedenen Ländernmit unterschiedlichen Maßeinheiten eingesetzt werden können und notwendigeUmrechnungen intern durchführen.

3.3 Instanzierung

Klassen sind keine fertigen Objekte, sie sind quasi die Schablonen dazu. Erstdurch die Instanzierung werden daraus reale Objekte, mit denen man auchetwas anfangen kann. Diese Schablone kann beliebig oft verwendet werdenund jedes erzeugte Objekt ist dabei unabhängig von allen anderen und besitzteinen eigenen Satz von internen Variablen.

Eine Instanz einer Klasse können Sie auf zwei Wegen anlegen:

1. Verwenden der ��-Anweisung zusammen mit ��

��� ������� �� ��� �������

2. Mit der ��-Anweisung eine Objektvariable anlegen, mit �� �����������

���� � �� ������ ein Objekt erstellen und gleichzeitig der Objektvariablenzuweisen

��� ������� �� �������

� ������� � ��� �������

Der Unterschied zwischen beiden Varianten ist der Zeitpunkt, ab dem dasObjekt tatsächlich existiert. Bei der ersten Variante wird das Objekt erst beieinem Zugriff auf eine Methode oder Eigenschaft angelegt. Bei der zweitenMethode wird das Objekt schon bei der ��-Anweisung zum Leben erweckt.

3.4 Eigenschaften und Methoden

Für jede Eigenschaft benötigen Sie zwei ��������-Prozeduren oder eine öffent-liche Variable. Die ��������-Prozeduren stellen eine mögliche Schnittstelle zurAußenwelt der Klasse dar und werden beim Setzen und Lesen ausgeführt, sindalso nicht unbedingt mit öffentlichen Variablen vergleichbar. Beim Auslesenwird die ���-, beim Setzen die ���- und bei Objekten die ��-Prozedur aus-geführt. Wenn Sie für eine Eigenschaft den Schreibschutz benötigen, lassen Sieeinfach die �������� ������-Prozeduren weg.

Page 5: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

94

Zum Einfügen der ��������-Prozeduren können Sie das Menü EINFÜGEN | PRO-ZEDUR | PROPERTY (Abbildung 3.2) in der VBE benutzen.

Abbildung 3.2Property einfügen

Passen Sie die ��������-Prozeduren so an, dass diese

ausschließlich den Datentyp derinternen Variablen aufnehmen

und zurückgeben. Standard-mäßig wird nämlich eine

Property mit dem Datentyp����� erzeugt.

Für jede Eigenschaft, die über eine ��������-Prozedur gesetzt und ausgelesenwird, benötigen Sie zudem noch eine klassenweit gültige Variable, welche dieWerte aufnimmt und für die gesamte Lebensdauer der Klasseninstanz speichert.In der Ereignisprozedur ���� ������� können Sie diese Variablen initiali-sieren, also mit Werten vorbelegen. Diese Ereignisprozedur wird beim Anlegender Klasseninstanz ausgeführt.

Für Methoden können Sie öffentliche Prozeduren oder Funktionen verwenden.Was Sie letztendlich verwenden, bleibt Ihnen überlassen. Eine Funktion bietetsich beispielsweise dann an, wenn als Rückgabewert der Erfolg einer Aktionsignalisiert werden soll.

3.5 Überladen von Parametern

Um ��� � bei Eigenschaftsprozeduren zu vermeiden, können Sie bei Klassenauch ��������-Prozeduren mit gleichen Namen für verschiedene Datentypenschreiben, die je nach übergebenem Datentyp ausgeführt werden. Diese Funk-tionalität nennt man ������� .

Page 6: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Erstellen von Klassen

95

Hier ein kleines Beispiel (Listing 3.1) dazu:

Listing 3.1 Beispiele\03_Klassen\ 03_01_Klassen.xls\mdlÜberladen

��� ���������������� �������� �� � ��� ���������� � ��������

������������� � ��������������� �������������� � ��������� ��� ������

� ������������� � ������������������ �������������� � ������� ��������

��� �� �

��� ���

Die Klasse ��� �������� (Listing 3.2):

Listing 3.2 Beispiele\03_Klassen\ 03_01_Klassen.xls\clsUeberladen

�� ��� �������

����� !���"���� �� � ����

������ ����� � ������������� �� � ����

������������ � !���"������� ����� �

������ ����� � ! ��������������"�� #$�%&���� �� � �����!���"���� � #$�%&����

��� ����� �

������ ����� � � ��������������"�� #$�%&���� �� ����������!���"���� � #$�%&�����$�!�

��� ����� �

Ich glaube aber nicht, dass Sie allzu häufig in die Verlegenheit kommen, mitVBA so etwas zu realisieren.

3.6 Erstellen von Klassen

Es hört sich vielleicht etwas seltsam an, aber der beste Weg, eine Klasse zu pro-grammieren ist der, sie erst zu benutzen und anschließend die Funktionalitätder Klasse zu realisieren. Das will ich an einem kleinen Beispiel demonstrieren,wobei Einträge aus einer .ini-Datei gelesen und Werte in diese hineingeschrie-ben werden können.

3.6.1 Initialisierungsdateien

Auch in Zeiten der Registry haben Initialisierungsdateien noch ihre Daseins-berechtigung. Diese Dateien entlasten die Registry, können mit einem Texteditorbearbeitet werden und sind sehr leicht weiterzugeben. VBA bietet zwar die Mög-lichkeit, mittels ��#������� und '�������� Daten in der Registry abzulegen,leider werden diese Daten dann nur im Zweig HKEY_CURRENT_USER\Software\VB and VBA Program Settings abgelegt. Darauf hat aber ein anderer Benutzer kei-nen Zugriff, weshalb allgemeine Einstellungen für jeden Benutzer separat abgelegtwerden müssen. Das ist dann aber eine redundante Datenvorhaltung in Reinkultur.

Page 7: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

96

Deshalb sollten mittels ����������� und ���������� nur benutzerabhängige Ein-stellungen gespeichert werden. Allgemeine Einstellungen von Software werdenüblicherweise unter HKEY_LOCAL_MACHINE\Software abgelegt, aber das lässtsich unter VBA nicht so einfach realisieren.

Bei dem Weg über die Registry wird zudem noch sehr häufig vergessen, dieseEinträge auch wieder zu löschen, wenn sie nicht mehr benötigt werden. Mit derZeit wird die Registry dann so aufgebläht, dass sogar Performanceproblemeauftreten können.

Man darf auch nicht vergessen, dass es auch nicht sehr sinnvoll ist, dem nor-malen Benutzer das Manipulieren der Registry zuzumuten, um solche überflüs-sigen Einträge zu entfernen. Neben irreparablen Fehlern, die durch Löschenoder die Manipulation der falschen Schlüssel auftreten, sind die meisten Benut-zer mit solch einer Aktion auch schlicht und einfach überfordert.

Eine .ini-Datei können Sie mit dem VBA-Befehl �� öffnen, auslesen und be-arbeiten, Werte werden darin als Strings gespeichert. Wenn man den Aufbaudieser Dateien kennt, ist das Auslesen und Speichern gar kein so großes Problem.

Eine Initialisierungsdatei ist eine einfache Textdatei mit der Dateinamenserwei-terung .ini. Sie ist eingeteilt in Sektoren, in denen sich Schlüssel mit den zuge-hörigen Werten befinden. Nachfolgend beispielhaft der Aufbau, wie Sie ihn ineinem Texteditor sehen würden:

������ ���

����������������

����������������

������ ���

����������������

����������������

Erheblich leichter funktioniert das Auslesen und Speichern von Schlüsselinhal-ten aber mit den Betriebssystemfunktionen �������������� ���������� und������������ ����������, die Sie mit der �������-Anweisung auch unter VBAbenutzen können.

3.6.2 Das Benutzen der Klasse clsIni

In einem Standardmodul – in diesem Beispiel ist es das Modul ��������� –erstellen Sie sich erst einmal eine Prozedur, die eine Instanz der Klasse ������anlegt und welche die gewünschten Eigenschaften und Methoden der Klassebenutzt. Dazu muss die Klasse noch nicht einmal existieren.

Die wichtigste Eigenschaft der zukünftigen Klasse ist sicherlich der Pfad zu derDatei, die als Container für die zu speichernden Werte dienen soll. Diese Eigen-schaft nennen wir sinnigerweise ���� !����.

Des Weiteren benötigt man die Angabe der Sektion, in welcher der Schlüsselgespeichert oder aus der er ausgelesen werden soll. Wichtig ist auch der Namedes Schlüssels, der den Wert aufnehmen soll, und schließlich der Wert selber.Diese drei Eigenschaften bekommen die Namen ����� �" ��������� und ����.

Page 8: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Erstellen von Klassen

97

Die vorher angesprochenen Eigenschaften sollen gesetzt und anschließend indie Datei geschrieben werden. Man könnte schon beim Setzen einer dieserEigenschaften das Schreiben anstoßen, das ist aber keine gute Idee, denn eswerden zum Speichern erst alle Eigenschaften benötigt.

Also brauchen Sie eine Methode, die erst dann aufgerufen wird, wenn die benö-tigten Eigenschaften gesetzt sind. Diese Methode nennen wir �������������,denn eine Sektion, ein Schlüssel und ein Wert kann neu angelegt oder geändertwerden. In diesem Beispiel benutzte ich statt einer Prozedur eine Funktion,denn mit einer Funktion kann man zusätzlich noch einen Wahrheitswertzurückgeben, der Auskunft über den Erfolg der Aktion gibt.

Schlüssel und Sektionen sollte man auch löschen können, also werden dafürauch zwei Methoden benötigt. Hier sind das die Methoden ������� ����und ������� ����, die auch wieder als Funktionen mit Erfolgsmeldung aus-geführt sind.

Schön wäre es noch, wenn man alle Sektionen einer Datei oder alle Schlüsseleiner Sektion auflisten könnte. Also werden auch dafür zwei Eigenschaften mitden Namen ������������� und ����������� angelegt, die in der Klasse alsFunktion ausgeführt sind und jeweils ein Array mit dem Ergebnis liefern sollen.

In dem vorliegendem Beispiel wird im Temp-Pfad eine Initialisierungsdateiangelegt. Zum Ermitteln des Temp-Pfades, das ist das temporäre Verzeichnisdes jeweiligen Benutzers, wird die API-Funktion ���������� benutzt.Anschließend werden in der Initialisierungsdatei zwei Sektionen mit jeweilszwei Schlüsseln und den zugehörigen Werten gespeichert. Zur Demonstrationwerden alle Sektionen dieser Datei, danach alle Schlüssel einer Sektion ausge-lesen und angezeigt.

Anschließend wird einer dieser angelegten Schlüssel gelöscht und alle noch vor-handenen Schlüssel dieser Sektion werden ausgelesen und angezeigt. Danachwird eine Sektion gelöscht und alle Sektionen der Datei werden angezeigt.

Hier also der Code (Listing 3.3), mit dem Sie die noch anzulegende Klasse benutzen:

Listing 3.3 Beispiele\03_Klassen\ 03_01_Klassen.xls\mdlCreate

������� ����� �� ��� ���������� ���� ���������� ���� ������������� � ����� �� !!�� ���� �� �� �" ����� ��� !!�� �� ���� � �# �� �� �

���� ��� ����$�%�����#��� ���&�� �� �� �

��� ������ �� ���� �

��� �'(�� �� ��� ��(����� %�������� �� ����� �

��� %��)�' �� ����� �

��� %��(��� �� ����� �

��� ���*�� �� ���� �

������ + ���� ���,," -#���&�� + ������������� �������#" ������#������ + �����������" ���&��#

Page 9: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

98

Listing 3.3 (Forts.)Beispiele\03_Klassen\

03_01_Klassen.xls\mdlCreate

���� ���������� ��� � �� ��� � ����������

� ���� ����� �������

�������� � ������������������� � ��������������� � � ��� ���� ���� � ����������������

�������� �� �

���������� � ����������!���� � � ��� �!�� ���� � ����������������

�������� �� �

� ���� ����� ��������

�������� � �������������������� � ���������������� � � ��� ����� ���� � ������������������

�������� �� �

���������� � �����������!���� � � ��� ��!�� ���� � ������������������

�������� �� �

� ��� ������ �������

" ������� � ���������������� #�� � ����� �� " ���� �� " �������

�� #�� � �� #�� � " ���� � "$% &� ���

������ �� #��' ' ����� ����������

� ��� ��������� �������

�������� � " �������(�)" *�� � ��������������

�� #�� � ����� �� " ���� �� " *��

�� #�� � �� #�� � " ���� � "$% &� ���

������ �� #��' ' ����� ��������� �� � � ��������

� ���� ��� ������ ������

���������� � " *��(!)����������&+�����

� ��� ��������� �������

" *�� � ���������������� #�� � ����� �� " ���� �� " *��

�� #�� � �� #�� � " ���� � "$% &� ���

Page 10: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Erstellen von Klassen

99

Listing 3.3 (Forts.)Beispiele\03_Klassen\ 03_01_Klassen.xls\mdlCreate

������ ������� � �� �� ��� �� � � �������

������� � ����������������������� �

� ���� ������ �� �� �

��������� � ��������������� � ����� �� ������ � ���������

������ � ������ � ������ � �� ��!����

������ ������� � �� ���������� ����

�� ���

3.6.3 Die Klasse clsIni

Bis jetzt haben Sie noch keine Zeile Code der eigentlichen Klasse geschrieben.Steht fest, welche Eigenschaften und Methoden die Klasse offen legen soll, kön-nen Sie sich an die Programmierung der Klasse machen.

Fügen Sie dazu in Ihr Projekt eine leere Klasse ein und vergeben Sie den Klassen-namen �����. Nachfolgend der Code der Klasse (Listing 3.4)"

Listing 3.4 Beispiele\03_Klassen\ 03_01_Klassen.xls\clsIni

������ ������ �������� #�$�����$��!������� %��� ����&'� ���� �#�$�����$��!��������� � %���� (�((�������)�� �� ������� %���� (*+)�� �� ��+� %���� (,!�-� �� ������� %���� (.�-��/������ �� ������� %���� ���0 �� ����� %���� (1�)�� �� ������ %� �� ����

� ������ �� ������� �� ��������� �� �� �

������ ������ �������� 2���$�����$��!������� %��� ����&'� ���� �2���$�����$��!��������� � %���� �(()�� �� ������� %���� *+)�� �� ������� %���� �+/!�-� �� ������� %���� 1�)�� �� ������ %� �� ����

� ������ �� ������� � ��������� �� �������

������ ����1�(�� �� ������

������ ���������� �� ������

������ ����*+ �� ������

������ ����3�- �� ������

������ �������� ����4�/���� �� ������

2���$�����$��!�������� %����������� ����*+� %

����3�-� ����1�(�� %� 56 � !��� ����4�/�� � !���

�� ��������

Page 11: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

100

Listing 3.4 (Forts.)Beispiele\03_Klassen\

03_01_Klassen.xls\clsIni

������ ������ ������������ � �� ����

�� ������������������������� �

����������� ������������� �

������������� ����������� �

� � ! ���� ������������ " ����

��� ������

������ ������ ����#������� � �� ����

�� ������������������������� �

����������� ���$�%� �

������������� ����������� �

� � ! ���� ����#������� " ����

��� ������

������ ������ &������������ � �� ������

��� ��'����� �� �����

��� ���(�� �� ���

��'����� " ����� )!!!� !�

���(�� " *���������������������� �

������������� ������������� �

+����#�� �����+� ��'������ �

,,,� ������������

&������������ " ����� ���� ��'������ ���(�� - )�� .�� !��

��� ������

������ ������ &�������#�� � �� ������

��� ��'����� �� �����

��� ���(�� �� ���

��'����� " ����� )!!!� !�

���(�� " *���������������������� �

����������� ������������� �

++� ��'������ �

,,,� ������������

&�������#�� " ����� ���� ��'������ ���(�� - )�� .�� !��

��� ������

������ ������ �� ���/0��1�� � �� �����

���/0��1�� " �����������

��� ������

������ ������ �� ���/0��1�� ���� ���23���� �� ������

����������� " ���23����

��� ������

������ ������ �� ������� � �� �����

������� " ����������

��� ������

������ ������ �� ������� ���� ���23���� �� ������

���������� " ���23����

��� ������

Page 12: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Erstellen von Klassen

101

Listing 3.4 (Forts.)Beispiele\03_Klassen\ 03_01_Klassen.xls\clsIni

������ ������ � ����������� �� ������

��������� ��� ������ ������

������ ������ �� ��������������� ��������� �� ���������� ��� ���������

��� ������

������ ������ � �� ��� �� ������

��� �� ����� �� ������

��� ������ �� ����

�� ����� ������������ ��

������ ��� !���� "�!���� !��� #��� ����!"�� ��� ���� #$��������� �����$� �� ����� � #%%%� ��� &!��'����

��� ����� ������ ����� � ��������� � ��� �����

��� ������

������ ������ �� �� ������� ��������� �� ���������� ����� ���������

��� ������

AnlegenÄndern

Die als öffentliche Methode benutzte Funktion (������)�*� � legt eine .ini-Dateian, falls diese noch nicht existiert. Das entsprechende Verzeichnis muss aberbereits existieren. Zuständig dafür ist die API-Funktion � !�� !���� "�!��+�� !��. Dieser Funktion wird als Parameter der Dateipfad inklusive Dateiname,Sektion, Schlüsselname und zugehörigem Wert übergeben. Die API-Funktion� !�� !���� "�!���� !�� liefert als Ergebnis einen Longwert zurück, derungleich null ist, wenn die Funktion erfolgreich war. Dieser wird dazu benutzt,den Wert �(,� als Funktionsergebnis zurückzugeben, wenn alles geklappt hat.

SchlüsselLöschen

Die als öffentliche Methode benutzte Funktion ���������-.����� löscht einenexistierenden Schlüssel. Zuständig dafür ist wiederum die API-Funktion� !�� !���� "�!���� !��. Die an diese Funktion übergebenen Parametersind der Dateipfad inklusive Dateiname, Sektion und Schlüsselname. Damit derSchlüssel gelöscht wird, muss als Parameter für den Wert ein �/������ !��übergeben werden. Wenn alles geklappt hat, was Sie am Rückgabewert von� !�� !���� "�!���� !�� erkennen können, wird als Funktionsergebnis�(,� zurückgegeben.

Page 13: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

102

SektionLöschen

Die als öffentliche Methode benutzte Funktion ������������ löscht eine exis-tierende Sektion in der angegebenen Datei. Zuständig für die eigentliche Arbeitist, wie nicht schwer zu erraten ist, die API-Funktion � ���� ������ �������� ���. Dieser wird diesmal als Parameter der Dateipfad inklusive dem Datei-namen und die zu löschende Sektion übergeben. Damit die Sektion auch tat-sächlich gelöscht wird, muss als Parameter für den Schlüsselnamen und für denWert ein �������� ��� übergeben werden. Wie bei den anderen Methoden wirdals Funktionsergebnis ���� zurückgegeben, wenn alles geklappt hat.

Wert

Die Property ��� �� � liest den Wert eines Schlüssels aus. Zuständig dafür ist dieAPI-Funktion ���� ������ ������� ���. Dieser Funktion wird als Parameter derDateipfad inklusive Dateiname, Sektion und Schlüsselname übergeben. Sie liefertals Ergebnis einen Longwert zurück, der ungleich null ist, wenn die Funktionerfolgreich war. Der eigentliche Wert wird im Parameter ������ ����� ���zurückgeliefert. Dazu wird an dieser Stelle ein ausreichend großer Puffer überge-ben, der den String aufnimmt. Der Parameter ����� gibt die Länge des Puffers anund ��������� ist ein String, der geliefert wird, wenn der Schlüssel nicht existiert.

In der ���-Prozedur bekommt lediglich die interne Variable � !���� den über-gebenen Wert zugewiesen. Das Schreiben übernimmt die Methode ��������"��� �.

AlleSektionen

Diese Property ist schreibgeschützt, da nur eine ���-Prozedur angelegt wurde.Der Code ist fast der gleiche wie in der Property ��� �� �, lediglich der Para-meter für die Sektion muss auf �������� ��� gesetzt werden. In diesem Fallwerden alle Sektionen durch ein � $%& getrennt im Parameter ������ ������ ��� zurückgeliefert. Mit der �����-Funktion wird daraus ein Array gemachtund an den Aufrufer geliefert.

AlleSchlüssel

Diese Property ist schreibgeschützt, da nur eine ���-Prozedur angelegt wurde.Der Code ist fast der gleiche wie in �������������, lediglich der Parameter fürden Schlüssel muss auf �������� ��� gesetzt werden. In diesem Fall werden alleSchlüssel der Sektion durch ein � $%& getrennt im Parameter ������ ������ ��� zurückgeliefert. Mit der �����-Funktion wird daraus ein Array gemachtund an den Aufrufer geliefert.

PfadZurIni, Sektion, Schlüssel

In diesen Property-Prozeduren werden lediglich die internen Variablen ausge-lesen und gesetzt.

Page 14: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Ereignisprozeduren WithEvents

103

3.7 Ereignisprozeduren WithEvents

Eine weitere wichtige Eigenschaft von Klassen ist, dass sie Ereignisse auslösenund auch Ereignisse von Objekten, die mit ���������� deklariert wurden, emp-fangen können. In Klassenmodulen von UserForms oder Tabellenblättern ste-hen Ihnen schon vordefinierte Ereignisprozeduren zur Verfügung. Wenn Siedort Objekte einfügen, können Sie auch deren Ereignisse benutzen.

Wollen Sie aber zum Beispiel Command-Buttons dynamisch in UserForms ein-fügen, d.h. während der Laufzeit und nicht während der Entwicklungszeit, habenSie das Problem, dass Ereignisprozeduren nicht als Arrays ausgeführt werdenkönnen. Sie benötigen also für jedes Objekt eine eigene Ereignisprozedur.

Mit ���������� und einer Klasse können Sie das ohne programmgesteuertesEinfügen von Code realisieren. Das Konzept ist anfangs nicht einfach zu ver-stehen, wenn Sie es aber ein paarmal durchgespielt hat, ist es gar nicht mehr soschwer.

3.7.1 Kontrollkästchen und Tabellenblatt

An folgendem Beispiel, das Schritt für Schritt aufgebaut wird, kann man sichdie Vorgehensweise am besten verdeutlichen. Es sollen programmgesteuertKontrollkästchen (CheckBox) in ein Tabellenblatt eingefügt werden und dieKlick-Ereignisse empfangen und ausgewertet werden:

1. Sie legen fest, von welchem Objekttyp Sie ein Ereignis empfangen wollen.Wir nehmen an, dass es sich dabei um eine ���� � von ��� ��� handelnsoll.

2. Fügen Sie zu Ihrem Projekt eine Klasse hinzu, als Name dafür wird hier������������ vergeben.

3. Im Deklarationsbereich dieser Klasse legen Sie eine öffentliche Objektvariabledes gewünschten Objekttyps an, in diesem Fall ��� �������� �, und zwarmit dem Schlüsselwort ����������. Das Schlüsselwort ���������� legt fest,dass dieses Objekt in dieser Klasse ein Ereignis (Event) empfangen kann.

������ ������� ������ � � ��� �������� �

4. Im Deklarationsbereich der Klasse legen Sie eine weitere Objektvariable an.In diesem von außen übergebenen Objekt soll später eine Prozedur auf-gerufen werden.

������ � ������� � ������

5. Der Objektvariablen � ������� muss man von außen ein Objekt zuweisenkönnen, also legen Sie dafür eine Eigenschaftsprozedur (�� �����) an. Daes sich um ein Objekt handelt, müssen Sie �� ����� ��� benutzen.

������ �������� ��� ����������� ���� !�"� � ������#

��� � ������� $ ���� !�"�

�� ��������

Page 15: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

104

6. Jetzt erstellen Sie in der Klasse die Ereignisprozedur des Objektes. Das Er-eignis ist dabei durch einen Unterstrich vom Objekt getrennt. Die angelegteProzedur wird in diesem Fall durch das Ändern der mit der Objektvariablen���������� verbundenen ������� ausgeführt.

In dieser Prozedur rufen Sie die Zielprozedur ��������� ��������� desals �������� übergebenen Objekts auf und übergeben dabei noch denStatus der Checkbox.

������� � �������������������

� �������� ��� ���

�� ���� ����� ����

� ��� ��������� �������� � ��� ��� ���� ���������

� ������ ��������

������������������ ��������� ����������������

�� �

7. Fügen Sie das Objekt, das ein Ereignis auslösen soll, in ein Tabellenblatt ein.

8. Legen Sie im Klassenmodul des Tabellenblattes eine öffentliche Prozeduran, die bei einem Ereignis aufgerufen werden soll.

���� � ��������� ������������������ �� �������

9. In einer Prozedur erstellen Sie für jede Checkbox in dem Tabellenblatt eineneue Instanz der Klasse ����������. Damit die Instanz nicht nach demBeenden der Prozedur gelöscht wird, haben Sie vorher eine Collection aufKlassenebene deklariert, der Sie die Instanz als neues Element übergeben.

Während der Lebensdauer der Collection, also bis die Codezeile �� ���� !

"�� ���������� oder �� ���� ! "������ ausgeführt wird, bleibt die hin-zugefügte Klasseninstanz am Leben.

Die Eigenschaft ����� der angelegten Klasse bekommt einen Verweis aufdas eigene Tabellenblatt.

���� � #�����������

��� �� �$�������

��� ��������� ! ��� ����������

��� ��� �� %����� ������$��������

�� &�'�"����������� ! (�������( ���

��� �������� ! ��� ��� ���������

��� ������������������� ! �������

��� �������������� ! #�

����������%)) ��������

�� ��

����

�� �

Und hier noch einmal der zusammenhängende Code. In eine Klasse mit Namen��� ��������� (Listing 3.5):

Page 16: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Ereignisprozeduren WithEvents

105

Listing 3.5 Beispiele\03_Klassen\ 03_02_Events.xls\clsSheetEvent

� ������ ��� ���� � ���� ������ ��� ���������� �����

������ ������� ��������� � �� �����������

� � �������� �� ��� �������� ���� ��������

������ ��������� � ������

������ ��� ������������������

� ����������� �� ����� ��

�� ���� �� ��� ����

� ��� ���������� ������ � �� ��� ����� � ���� ����

� !����� ���������

�������������������������� ��� ����������!��"�

�� ���

������ �������� ��� ����������� #��!��"� � �������

� "������ � ��� � ��� �������� ��� �� � ����#

� ��� ��� ��� ������ ���������� ����� ����

��� ��������� $ #��!��"�

�� ��������

In das Klassenmodul eines Tabellenblattes (Listing 3.6):

Listing 3.6 Beispiele\03_Klassen\ 03_02_Events.xls\Tabelle1

� ���������# ��� � � ����� �� $� �� �� ��

������ ����� ���� � ����������

������ ��������� � ��������� ���

������ ��� ���������������� �������!��"� � �������

� %��� ���������� ������ �� ��� ���� ��������

� !����� ���&��������� ���� ���� !��� ����������

� '����� ����� ��

���� ���!��"�

�� ���

������ ��� ����� ������

!�� � �%�������

��� ����� ���� $ ��" ����������

#�� ��� $� &��� ��������%��������

$% '�(�#������������ $ )������) &���

��� ��������� $ ��" ��������� ���

��� ������������������� $ �������

��� ��������������� $ ��

����� �����&** ���������

�� $%

����

�� ���

Page 17: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

106

3.7.2 CommandButton und UserForms

Nachfolgend ein Beispiel zum dynamischen Einfügen von Buttons und Emp-fangen des Klickereignisses in einer Klasse. In der Klasse wiederum kann einEreignis ausgelöst werden, das dann in der Besitzerklasse ausgeführt wird.

Erst einmal der Code der Klasse ������������� (Listing 3.7):

Listing 3.7Beispiele\03_Klassen\

03_02_Events.xls\clsTestEvents

� ������ ��� ���� � ���� ������ ��� ���������� �����

������ ������� �� ���������� � ������� ����������

� ����� ����� ���� � ������ ������� ��������� �����

������ ��� ������������������ � �������

� � �������� �� ��� �������� ���� ��������

������ �������� � ������

������ ��� �� ���������� ������

� ��������� �� ������

�� ���� �� ��� ����

� ��� ���������� !������ � �� ��� ����� � ���� ����

� "���#��� ���������

����������!����� ���������� �� ���������������

� ����� � �� ������������ �������� ��

� $��� � ���� ��

��� ���� ������������� ����������������

�� ���

������ �������� ��� ����������� ����"���� � �������

� ������ � ��� � ��� �������� ��� � "���#���%

���� ��� ��� !������ ���������� ����� ����

��� �������� # ����"����

�� ��������

Hier der Code, der in das Klassenmodul einer UserForm gehört (Listing 3.8). Indiese UserForm gehört noch ein Button mit dem Namen ��� ��������.

Listing 3.8Beispiele\03_Klassen\

03_02_Events.xls\frmEventAll

� ������ �� "���#����

������ ��$ ���� ��� � ����

� & !����� �� "���#���

������ ��$%&� � ����

� ��� ��������� $�������� �� ������

������ �� � ��������� # '���(���)�*����'

� '��������% ��� � � ����� �� (� �� �� ��

������ �������� � ��! ���������

� � �������� �� ������� �� ���������% ��� ��������

� ��)������ ����� ������

������ ������� ������� � �������������

Page 18: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Ereignisprozeduren WithEvents

107

Listing 3.8 (Forts.)Beispiele\03_Klassen\ 03_02_Events.xls\frmEventAll

������� � �����������

� ������ � �� ��� ������

������ ������ � ������ ������ � �

� �� ��� �� �� ��� ����� �� ����

�� ������ ������ � � ��� ���� �

� ��� ���������� �����

��� ��������� � ��� ������������

� ���� ��� �� ���� !����

��� �������������� � �

� �� �� �����

��� �������������������������� � ! ������ ������ !�"#� ������������������"$ !������%��� & ������������� ������$ "'''"

� "��� ��� ��� �� �� ���

���� �����������������������������( � ��)*�����(�+�� � "���������� " & ������ ������

��� ����

��)*�� � ��)*�� � ,-

����������� � #���� ��� �

������������� ������������ �

���� � ���������!.+�/�������� ����/����� �� ������� �� ��� � � ���������� �� ����

� $�� % ��� ����� �� �&� �� �� ���� ���

� �� � � � �� ��' ��� �&��� �! ��� (���

� ����� �� $����������% ���� ���� �

� (��� �������' ��)� ���� ���� ���� '

������ �� ����/�����$ $ "� �+��+�( �0��� "��� �

���� � �1������!.+�/�������� ����/����� �� �������*�� +��� ���� "���� ��� ��� �� ������

������ ���,� $�� � ���� �� ����� �������

�� ��2���3 �� !���

�# �� � ���- - ����

��2���3 � �4���5+�6���� ����/�����$ 7

������� ������

����3 �� ����/����� & " %���� 8" & ��2���3$ $ !"9::���+�6� * �0��� "

��� �

������� � ���� ����%��!�+�/�����������

��� �

Page 19: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

3 Klassen

108

Abbildung 3.3Verschiedene Ansichten

der UserForm

Die Funktionalität der UserForm

Bei einem Klick auf den Button ����������� wird die Prozedur ���������aufgerufen. Wenn bereits mehr als vier Buttons angelegt wurden, wird dieseaber sofort wieder verlassen.

Die auf Klassenebene angelegte Objektvariable � ������� nimmt anschließendmit ��� und �� eine neue Instanz der Klasse ������������� auf. Da diese mitdem Schlüsselwort ���������� deklariert wurde, können Ereignisse des damitverbundenen Objektes empfangen werden.

Anschließend können Sie eine Objektreferenz der UserForm an die soebeninstanzierte Klasse übergeben. Damit wird erreicht, dass die Klasse eine öffent-liche Prozedur der UserForm aufrufen kann.

Zum Einfügen eines Buttons wird die ��-Methode der Controls-Auflistung inder UserForm benutzt. Gleichzeitig bekommt die Klasse über die als öffentlichdeklarierte Variable � �������������� eine Objektreferenz auf den soeben hin-zugefügten Button. In der Klasse ������������� ist diese Variable mit ����������deklariert worden, also kann dort das Objekt Ereignisse auslösen. Anschließendwird die Position des Buttons festgelegt werden, ich erhöhe aber jeweils nur dieY-Position.

Würde man an dieser Stelle die Prozedur einfach beenden, hätte man beimnächsten Einfügen eines Buttons ein Problem: Wenn Sie mit ��� und �� eineneue Instanz der Klasse ������������� anlegen und sie der Objektvariablen� ������� zuweisen, wird die ältere, mit der Objektvariablen verbundene Klas-seninstanz aus dem Speicher gelöscht.

Page 20: Michael Schwimmer Excel VBA - Pearsondie Prozeduren und ganz einfach weglassen. Sie können sogar mithilfe von Klassen benutzerdefinierte Typen nachbilden, die im Gegensatz zu den

Ereignisprozeduren WithEvents

109

Also benutzen Sie eine klassenweit gültige Collection und fügen die Objekt-variable als Element hinzu. Dadurch wird erreicht, dass noch zusätzlich eineReferenz auf das Klassenobjekt angelegt wird, die so lange bestehen bleibt, bissie aus der Collection entfernt wird oder die Objektvariable der Collection auf������� gesetzt wird. Wird die Objektvariable ������� für eine neue Klassen-instanz benutzt, bleibt wegen der noch bestehenden Referenz auch die ältereInstanz noch im Speicher.

Die Prozedur ��������� �������� ist eine Ereignisprozedur, die von dem mitder Objektvariablen ������� verbundenen Objekt ausgelöst wird. Deshalbwurde auch bei der Deklaration das Schlüsselwort ���������� benutzt.

Die Prozedur �������� �������� ist eine öffentliche Prozedur. Diese wird beieinem Klick auf einen Button von der damit verbundenen Klasse aufgerufen.

clsTestEvents

Die Objektvariable �������������� vom Typ ������������������� ist mitdem Schlüsselwort ���������� deklariert worden.

Im Deklarationsteil dieser Klasse wird noch das Event � �������� angelegt, dasman innerhalb der Klasse feuern kann. Feuern bedeutet, dass Sie in der Klasse,die eine Instanz auf diese Klasse hält, eine Ereignisprozedur auslösen können.Dazu muss die Objektvariable, die eine Instanz auf die feuernde Klasse hält, alsoin der UserForm die Variable ������� mit dem Schlüsselwort ����������,deklariert sein.

Wenn Sie in der UserForm als Prozedurnamen den Objektnamen benutzen, einenUnterstrich und den Ereignisnamen dranhängen, kann die feuernde Klasse dieseProzedur aufrufen und ihr sogar Parameter übergeben. Ausgelöst wird das durchdie Anweisung ���������� � ��������!�������������������".

Umgekehrt kann das mit der Objektvariablen �������������� verbundeneObjekt – in diesem Beispiel ein eingefügter Button – eine Ereignisprozedur inder verbundenen Klasse aufrufen. Dazu wird wieder der Objektname mit demEreignisnamen durch einen Unterstrich verbunden und als Prozedurnamebenutzt (���������������� ���).

In der Property-Prozedur #��$���� ��� %&��� wird eine Referenz auf die User-Form an die Klasse übergeben und in der Variablen ����%&��� gespeichert.Damit ist es möglich, eine öffentliche Prozedur des aufrufenden Objektes aus-führen zu lassen. Die Zeile ����%&������������ �������� ruft dann die ent-sprechende Prozedur in der UserForm auf.

Durch diesen kleinen Kniff können Sie in der UserForm eine einzige Prozedur füralle Klickereignisse realisieren. Damit unterschieden werden kann, welcher But-ton gerade angeklickt wurde, übergeben Sie zusätzlich den Namen des Buttons.