09.02.2014 Aufrufe

Ein VBA-Programm in Excel

Ein VBA-Programm in Excel

Ein VBA-Programm in Excel

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Inhaltsverzeichnis<br />

1 Vorwort .................................................................................................................................. 3<br />

1.1 Wie alles begann ........................................................................................................ 3<br />

1.2 Was leistet das <strong>Programm</strong> ......................................................................................... 4<br />

1.3 Inhalt und Ziele der Ausarbeitung .............................................................................. 5<br />

1.4 <strong>Programm</strong>-Umgebung ............................................................................................... 6<br />

1.5 Weitere (persönliche) Anmerkungen ......................................................................... 6<br />

2 Das <strong>Programm</strong> ...................................................................................................................... 6<br />

2.1 Grundsätzliches zur <strong>Programm</strong>ierung <strong>in</strong> <strong>VBA</strong> ............................................................ 6<br />

2.1.1 Variablendeklarationen ......................................................................................... 6<br />

2.1.2 Makros ................................................................................................................... 8<br />

2.1.3 Unterprogrammtechnik ....................................................................................... 10<br />

2.1.4 Objekte, Eigenschaften und Methoden ............................................................... 10<br />

2.1.4.1 Objekte und ihre Hierarchie ........................................................................ 11<br />

2.1.4.2 Eigenschaften ............................................................................................. 13<br />

2.1.4.3 Methoden ................................................................................................... 13<br />

2.2 Die Gäste kommen ................................................................................................... 14<br />

2.3 Die Entwicklungsumgebung von <strong>VBA</strong> ...................................................................... 16<br />

2.4 Ereignisse <strong>in</strong> <strong>VBA</strong> ...................................................................................................... 17<br />

2.5 Der Kern des <strong>Programm</strong>s: die Auslosung ................................................................. 20<br />

2.5.1 Eigene Dialoge entwerfen und programmieren................................................. 23<br />

2.5.2 Die neuen Tabellenblätter ................................................................................... 32<br />

2.5.2.1 Das Tabellenblatt "Liste" ........................................................................... 32<br />

2.5.2.2 Pro Durchgang je e<strong>in</strong> Tabellenblatt ............................................................ 33<br />

2.5.2.3 Das Tabellenblatt "Ergebnis" ...................................................................... 34<br />

2.5.3 Das Mischprogramm: wer kommt <strong>in</strong> welchem Durchgang an welchem Tisch an<br />

welchem Platz? ................................................................................................................. 36<br />

2.5.4 Zusatzfunktionen ................................................................................................. 41<br />

3 Ausblick/Nachbetrachtung ................................................................................................ 49<br />

3.1 Neuralgische Punkte ................................................................................................ 49<br />

3.2 Mögliche Weiterentwicklungen ............................................................................... 51<br />

4 Literatur- und Quellenverzeichnis ..................................................................................... 52<br />

2


1 Vorwort<br />

1.1 Wie alles begann<br />

Jedes Jahr zwischen Weihnachten und Silvester f<strong>in</strong>det bei me<strong>in</strong>em<br />

Schwager e<strong>in</strong> privates Doppelkopfturnier statt. Seit ca. 20 Jahren erfreut<br />

es sich e<strong>in</strong>er immer größeren Beliebtheit; es ist zur Tradition geworden.<br />

Die ersten Jahre fand das Turnier noch <strong>in</strong> e<strong>in</strong>em kle<strong>in</strong>en<br />

Rahmen – jeder kannte jeden – statt. In der Zwischenzeit hat es sich<br />

zu e<strong>in</strong>er Mammutveranstaltung ausgeweitet - das Turnier zählte im<br />

letzten Jahr genau 101 Teilnehmer. Da bei e<strong>in</strong>er Tischanzahl von maximal<br />

25 die räumlichen Kapazitäten restlos ausgeschöpft s<strong>in</strong>d, ist damit<br />

dann wohl auch das Ende der Fahnenstange erreicht. Die e<strong>in</strong>ladende<br />

Raumatmosphäre sowie die ausgezeichnete Organisation (als<br />

e<strong>in</strong> Beispiel sei nur die erstklassige Verpflegung mit Speisen und Getränken<br />

genannt) haben dafür gesorgt, dass sich der Teilnehmerkreis<br />

Jahr für Jahr erweitert hat. Dieser permanente Zuwachs an Teilnehmern<br />

hat aber auch dazu geführt, dass der manuelle Aufwand für die<br />

anfallenden Tätigkeiten - von der Auslosung über die Erfassung der<br />

Punktzahlen bis h<strong>in</strong> zur Auswertung der Spielergebnisse - immer größer<br />

wurde. Das wiederum veranlasste me<strong>in</strong>en Schwager als Ausrichter<br />

des Turniers nach möglichen Alternativen im PC-Bereich Ausschau zu<br />

halten, um diese manuellen Tätigkeiten durch Automatismen zu ersetzen.<br />

So kam es, dass er vor 10 Jahren auf mich zukam mit der Bitte,<br />

mir hierüber mal Gedanken zu machen.<br />

Als spontane Idee, per <strong>Programm</strong> e<strong>in</strong>e Verbesserung zu erzielen, fielen<br />

mir - wie konnte es auch anders se<strong>in</strong> - die Möglichkeiten von Microsoft<br />

<strong>Excel</strong> e<strong>in</strong>. Das, was mir dabei zunächst vorschwebte, war allerd<strong>in</strong>gs<br />

noch recht rudimentär. Der e<strong>in</strong>zige Fortschritt, den <strong>Excel</strong> mir <strong>in</strong> me<strong>in</strong>en<br />

ersten Überlegungen bot, schien dar<strong>in</strong> zu bestehen,<br />

‣ e<strong>in</strong>e Liste mit allen Teilnehmern zu erstellen,<br />

‣ diese Liste zu e<strong>in</strong>er Tabelle zu erweitern, <strong>in</strong>dem pro Durchgang e<strong>in</strong>e<br />

zusätzliche Spalte genutzt wurde, <strong>in</strong> der die Punktzahlen der<br />

Teilnehmer pro Durchgang e<strong>in</strong>getragen wurden,<br />

‣ um <strong>Excel</strong> danach diese Punktzahlen für jeden Teilnehmer addieren<br />

zu lassen,<br />

‣ und die Liste anschließend nach erreichter Gesamtpunktzahl zu<br />

sortieren.<br />

Nun hätte ich es natürlich auch dabei bewenden lassen können. Die<br />

Umsetzung <strong>in</strong> <strong>Excel</strong> wäre <strong>in</strong> wenigen M<strong>in</strong>uten fertig gewesen. Der<br />

größte Aufwand hätte wohl noch dar<strong>in</strong> bestanden, die Teilnehmerliste<br />

e<strong>in</strong>zutippen. Das kam mir aber alles e<strong>in</strong> bisschen "zu mager" vor. <strong>E<strong>in</strong></strong>e<br />

deutliche Verbesserung gegenüber Bleistift und Papier hätte das zudem<br />

auch nicht bedeutet.<br />

H<strong>in</strong>weis/Bemerkung 1<br />

Die gute Stimmung der Teilnehmer<br />

sorgt für e<strong>in</strong>e hohe<br />

Spendenbereitschaft. Das an<br />

den Tischen e<strong>in</strong>gespielte<br />

Geld wandert - neben zusätzlichen<br />

freiwilligen Beiträgen -<br />

als Spende <strong>in</strong> e<strong>in</strong>en geme<strong>in</strong>samen<br />

Topf und wird e<strong>in</strong>er<br />

geme<strong>in</strong>nützigen<br />

humanitären<br />

Organisation <strong>in</strong> Afrika<br />

zugeführt.<br />

3


Ich beschäftigte mich nun fortan <strong>in</strong>tensiver mit den Möglichkeiten von<br />

<strong>Excel</strong> und deren <strong>Programm</strong>iermöglichkeiten und kam letztendlich zu<br />

dem Entschluss, es nicht bei dieser e<strong>in</strong>fachen Liste bewenden zu lassen.<br />

Ich kannte zwar weder die <strong>VBA</strong>-Umgebung für <strong>Excel</strong> (<strong>VBA</strong> = Visual<br />

Basic for Applications), noch dessen Sprachkern Visual Basic,<br />

hatte aber zum<strong>in</strong>dest <strong>Programm</strong>iererfahrung <strong>in</strong> prozeduraler <strong>Programm</strong>iertechnik.<br />

Außerdem bot mir <strong>Excel</strong> ja bekanntermaßen die<br />

Möglichkeit, viele Tätigkeiten durch den <strong>E<strong>in</strong></strong>satz des Makrorekorders<br />

zu automatisieren. Der dabei erzeugte Quellcode der Makros half mir<br />

zudem beim <strong>E<strong>in</strong></strong>stig <strong>in</strong> <strong>VBA</strong>. Zusätzliche Literatur sowie Recherchen<br />

im Internet trugen zusätzlich dazu bei, mich recht schnell <strong>in</strong> der Umgebung<br />

zurechtzuf<strong>in</strong>den.<br />

Fortan machte ich mich an die Arbeit; herausgekommen ist dabei e<strong>in</strong><br />

komplettes Turnierprogramm, 2002 erstmalig erstellt und 2010 verbessert<br />

und um e<strong>in</strong>ige Funktionen erweitert. Das <strong>Programm</strong> wird mittlerweile<br />

nicht nur e<strong>in</strong>mal im Jahr bei dem besagten Turnier e<strong>in</strong>gesetzt,<br />

sondern auch immer dann, wenn im Freundes- und Bekanntenkreis<br />

e<strong>in</strong>e derartige Veranstaltung angesagt ist.<br />

1.2 Was leistet das <strong>Programm</strong><br />

Kurz zusammengefasst bietet das <strong>Programm</strong> folgende Funktionen:<br />

‣ Mischprogramm bei der Auslosung: die Teilnehmer bekommen per<br />

Zufallsgenerator e<strong>in</strong>en Tischplatz zugewiesen<br />

‣ Anzahl der Durchgänge sowie Anzahl der Runden pro Durchgang<br />

jeweils zwischen 1 und 10 frei wählbar<br />

‣ die Gesamtanzahl der Tische kann durch e<strong>in</strong>e vermehrte Anzahl an<br />

5er-Tischen reduziert werden (für den Fall, dass die Räumlichkeiten<br />

ke<strong>in</strong>e weiteren Tische mehr zulassen)<br />

‣ Generierung neuer <strong>Excel</strong>-Tabellenblätter nach der Auslosung:<br />

<br />

<br />

<br />

e<strong>in</strong>e alphabetisch sortierte Liste aller Teilnehmer zum Ausdrucken,<br />

aus der jeder für sich ablesen kann, <strong>in</strong> welchem Durchgang<br />

er an welchem Tisch an welchem Platz spielt<br />

pro Durchgang e<strong>in</strong> Tabellenblatt für die <strong>E<strong>in</strong></strong>tragung der erreichten<br />

Punktzahl pro Spieler; die Tische (mit ihren Teilnehmern)<br />

werden nach Tisch-Nr sortiert aufgelistet<br />

e<strong>in</strong> Ergebnis-Tabellenblatt mit e<strong>in</strong>er Liste aller Teilnehmer, <strong>in</strong><br />

der nach Spielende (oder auch schon früher, um Zwischenstände<br />

abzurufen) per Knopfdruck die Ergebnisse aus den e<strong>in</strong>zelnen<br />

Durchgängen übernommen werden<br />

4


‣ die Spielzettel s<strong>in</strong>d komplett vorformatiert und enthalten bereits die<br />

Namen der Spieler. Für den Ausdruck stehen zwei Varianten zur<br />

Auswahl:<br />

<br />

<br />

e<strong>in</strong>fache Version für den Privatgebrauch und<br />

offizielle Spielzettel-Version vom Deutschen Doppelkopf Verband<br />

für gehobene Ansprüche<br />

1.3 Inhalt und Ziele der Ausarbeitung<br />

Bei der vorliegenden Arbeit stehen die folgenden drei Aspekte im Vordergrund:<br />

‣ Darstellung der Bestandteile des Turnierprogramms<br />

‣ Kurze<strong>in</strong>weisung <strong>in</strong> <strong>VBA</strong><br />

‣ Workshop-Charakter<br />

Im Focus steht dabei natürlich die Absicht, die wesentlichen<br />

Bestandteile des <strong>Programm</strong>s vorzustellen, verbunden mit dem Ziel,<br />

deren Implementierung <strong>in</strong> <strong>VBA</strong> herauszuarbeiten. Auf e<strong>in</strong> komplettes<br />

Code-List<strong>in</strong>g wird allerd<strong>in</strong>gs verzichtet (e<strong>in</strong> Workshop soll auch e<strong>in</strong><br />

Workshop bleiben); bei Interesse kann es aber natürlich auf Anfrage<br />

(email: hehrenbr<strong>in</strong>k@yahoo.de) von mir bezogen werden.<br />

Denjenigen Lesern, die bisher noch ke<strong>in</strong>erlei Erfahrungen <strong>in</strong> <strong>VBA</strong> gesammelt<br />

haben, aber Interesse daran haben, das <strong>Programm</strong> nachzuvollziehen,<br />

soll der <strong>E<strong>in</strong></strong>stieg dadurch erleichtert werden, dass <strong>in</strong> groben Zügen<br />

die wesentlichen Sprachelemente und <strong>Programm</strong>iertechniken <strong>in</strong><br />

<strong>VBA</strong> vorgestellt werden, (Kapitel 2.1) und dass auch auf die Bedienung<br />

der Entwicklungsumgebung (Kapitel 2.3) sowie auf den <strong>E<strong>in</strong></strong>satz von<br />

Dialogtechniken (Kapitel 2.5.1) e<strong>in</strong>gegangen wird.<br />

Den Hauptteil dieser Abhandlung bildet zwangsläufig das Ma<strong>in</strong>-<br />

<strong>Programm</strong> Sub Auslosung(): Struktur und wesentliche Bestandteile<br />

werden thematisiert.<br />

Abschließend werden noch e<strong>in</strong>ige <strong>in</strong>teressante Zusatzfunktionen des<br />

<strong>Programm</strong>s vorgestellt.<br />

Der Intention e<strong>in</strong>es Workshops entsprechend, s<strong>in</strong>d für diejenigen Leser,<br />

die Interesse an dem <strong>Programm</strong> gefunden haben und sich mit der Materie<br />

vertraut machen wollen, am Ende e<strong>in</strong>iger Kapitel/Abschnitte e<strong>in</strong>ige<br />

Übungen (ohne Lösungen) e<strong>in</strong>gestreut.<br />

5


1.4 <strong>Programm</strong>-Umgebung<br />

Die erste Version des <strong>Programm</strong>s wurde von mir <strong>in</strong> VBE Office XP erstellt.<br />

Lauffähig war das <strong>Programm</strong> auch – ohne jegliche Anpassungen<br />

– <strong>in</strong> den Nachfolge-Versionen Office <strong>Excel</strong> 2003 und 2007. Unter Office<br />

<strong>Excel</strong> 2007 erfolgte im Jahr 2010 e<strong>in</strong>e Ergänzung/Verbesserung. Auf<br />

diese Office-Version beziehen sich auch alle <strong>in</strong> diesem Workshop verwendeten<br />

<strong>VBA</strong>-/<strong>Excel</strong>-Elemente.<br />

Als Betriebssystemumgebungen des Turnier-<strong>Programm</strong>s wurden bisher<br />

W<strong>in</strong>dows XP und Microsoft W<strong>in</strong>dows 7 Professional e<strong>in</strong>gesetzt.<br />

H<strong>in</strong>weis 2<br />

VBE (= Visual Basic Editor) ist<br />

das Entwicklertool der <strong>VBA</strong>-<br />

<strong>Programm</strong>ierung. Mit der<br />

Tastenkomb<strong>in</strong>ation<br />

gelangt man <strong>in</strong><br />

die Entwicklungsumgebung<br />

(und wieder zurück).<br />

1.5 Weitere (persönliche) Anmerkungen<br />

Wenn im Folgenden von "den Spielern" oder "den Teilnehmern" die<br />

Rede ist, so ist damit natürlich das weibliche Geschlecht implizit immer<br />

mit e<strong>in</strong>geschlossen. Würde ich stattdessen jedesmal von "den SpielerInnen"<br />

oder "den Spielern und Spieler<strong>in</strong>nen" bzw. von "den TeilnehmerInnen"<br />

oder "den Teilnehmern und Teilnehmer<strong>in</strong>nen" sprechen, so<br />

hätte darunter die Lesbarkeit des Dokumentes zu leiden. <strong>E<strong>in</strong></strong>e Diskrim<strong>in</strong>ierung<br />

des weiblichen Personenkreises bzgl. des Doppelkopfspiels<br />

liegt mir absolut fern.<br />

Zusätzlich sei noch angemerkt, dass alle Namen der <strong>in</strong> diesem Dokument<br />

erwähnten Personen frei erfunden s<strong>in</strong>d.<br />

2 Das <strong>Programm</strong><br />

2.1 Grundsätzliches zur <strong>Programm</strong>ierung <strong>in</strong> <strong>VBA</strong><br />

2.1.1 Variablendeklarationen<br />

<strong>E<strong>in</strong></strong>e Variablendeklaration beg<strong>in</strong>nt mit der Anweisung Dim, gefolgt von<br />

dem frei wählbaren Variablen-Namen. Danach gibt man mit dem<br />

Schlüsselwort As an, welchen Datentyp die Variable enthalten soll.<br />

Konstante Größen lassen sich noch e<strong>in</strong>facher deklarieren, da sie ke<strong>in</strong>en<br />

Datentyp besitzen. Statt mit der Anweisung Dim beg<strong>in</strong>nen sie mit<br />

Const.<br />

6


Möchte man e<strong>in</strong>en array anlegen, so geschieht das ebenfalls mit Dim,<br />

gefolgt von dem Variablennamen und anschließender Klammerung ().<br />

Damit lässt man sich aber die Dimensionierung und die Länge des<br />

arrays noch offen.<br />

Beispiele:<br />

Dim Zahl1 As Integer 'Integer-Variable namens Zahl<br />

Const Zahl2 = 10 'Speicherplatz Zahl2 mit festem Wert 10<br />

Dim Zahl() As Integer 'Integer-array ohne Dimension und ohne Länge<br />

Es gibt drei mögliche Gültigkeitsbereiche für e<strong>in</strong>e Variable:<br />

a) Wird die Variable nur <strong>in</strong>nerhalb e<strong>in</strong>er Prozedur benötigt, handelt es<br />

sich um e<strong>in</strong>e lokale Variable. Die Deklaration steht dann am Anfang<br />

e<strong>in</strong>er Prozedur.<br />

Sub Test()<br />

Dim Me<strong>in</strong>eVariable As Long<br />

gültig<br />

Anweisung<br />

...<br />

Anweisung<br />

End Sub<br />

'Me<strong>in</strong>eVariable ist nur <strong>in</strong>nerhalb der Prozedur Test()<br />

b) Wird die Variable <strong>in</strong> mehreren Prozeduren e<strong>in</strong>es Moduls benötigt, so<br />

muss sie als globale Variable am Anfang des Moduls deklariert werden<br />

mit Dim oder Private als Anweisung. Unter dem Begriff "Modul"<br />

muss man sich e<strong>in</strong>fach e<strong>in</strong>en Conta<strong>in</strong>er vorstellen, der Quellcode<br />

enthält – der Code muss ja schließlich irgendwo untergebracht se<strong>in</strong>. Je<br />

nachdem, wofür so e<strong>in</strong> Modul genutzt wird, wird unterschieden z.B.<br />

zwischen e<strong>in</strong>em Modul für Userformen (siehe 2.5.1 Eigene Dialoge entwerfen<br />

und programmieren) oder e<strong>in</strong>em Modul für e<strong>in</strong> Tabellenblatt<br />

(siehe 2.5 Der Kern des <strong>Programm</strong>s: die Auslosung) oder e<strong>in</strong>em Modul<br />

für die Ereignissteuerung (siehe 2.4 Ereignisse <strong>in</strong> VBE) oder ...<br />

Dim Me<strong>in</strong>eVariable As Long 'Me<strong>in</strong>eVariable ist auf Modulebene gültig<br />

Private Me<strong>in</strong>eVariable1 As Long 'ebenso Me<strong>in</strong>eVariable1<br />

Sub Test()<br />

Anweisung<br />

...<br />

Anweisung<br />

End Sub<br />

c) Soll die Variable auch <strong>in</strong> anderen Modulen des Projektes Gültigkeit<br />

haben, muss sie als öffentliche Variable mit Public deklariert werden.<br />

Public Me<strong>in</strong>eVariable As Long 'Me<strong>in</strong>eVariable ist im ganzen Projekt gültig<br />

Sub Test()<br />

Anweisung<br />

...<br />

Anweisung<br />

End Sub<br />

7


2.1.2 Makros<br />

Der e<strong>in</strong>fachste Weg, sich e<strong>in</strong>en ersten <strong>E<strong>in</strong></strong>blick <strong>in</strong> die <strong>VBA</strong>-<br />

<strong>Programm</strong>ierung zu verschaffen, ist der, dass man sich die Makro-<br />

<strong>Programm</strong>ierung e<strong>in</strong>mal näher anschaut.<br />

Im folgenden Beispiel wird per Makro-Recorder (Aufruf über<br />

"ENTWICKLERTOOLS/MAKRO AUFZEICHNEN") der Zellenbereich<br />

"A1:C2" mit Inhalt gefüllt:<br />

Abbildung 1<br />

Makro MwSt<br />

Die Schaltfläche Bearbeiten<br />

öffnet die Entwicklungsumgebung<br />

und man gelangt<br />

direkt <strong>in</strong> den Quellcode des<br />

Makros<br />

Das aufgezeichnete Makro lässt sich nun nachträglich weiter bearbeiten.<br />

Durch den Aufruf der Schaltfläche Bearbeiten ersche<strong>in</strong>t allerd<strong>in</strong>gs<br />

nicht mehr der Makro-Recorder, sondern man hat den <strong>VBA</strong>-Quellcode<br />

<strong>in</strong> der Entwicklungsumgebung vor sich. Für obiges Beispiel wurden folgende<br />

Zeilen generiert:<br />

Sub MwSt()<br />

Range("A1").Select<br />

ActiveCell.FormulaR1C1 = "MwSt"<br />

Range("B1").Select<br />

ActiveCell.FormulaR1C1 = "Brutto"<br />

Range("C1").Select<br />

ActiveCell.FormulaR1C1 = "Netto"<br />

Range("A2").Select<br />

ActiveCell.FormulaR1C1 = "0.19"<br />

Range("B2").Select<br />

ActiveCell.FormulaR1C1 = "50"<br />

Range("C2").Select<br />

ActiveCell.FormulaR1C1 = "=RC[-1]*(1+RC[-2])"<br />

Range("A1:C1").Select<br />

'Name des Makros<br />

'Netto-Berechnung <strong>in</strong><br />

Zelle C2<br />

List<strong>in</strong>g 1<br />

Makro MwSt<br />

Die <strong>in</strong> grün gehaltenen Bemerkungen<br />

s<strong>in</strong>d Kommentare<br />

8


2.1.3 Unterprogrammtechnik<br />

Um den <strong>Programm</strong>code <strong>in</strong> kle<strong>in</strong>e unabhängige und überschaubare <strong>E<strong>in</strong></strong>heiten<br />

zu unterteilen, stehen <strong>in</strong> <strong>VBA</strong> zwei Varianten zur Verfügung –<br />

Prozeduren und Funktionen.<br />

Prozeduren beg<strong>in</strong>nen, wie im vorherigen Beispiel e<strong>in</strong>es Makros zu sehen,<br />

immer mit Sub, gefolgt von dem Prozedurnamen, und enden immer<br />

mit End Sub.<br />

Sub Prozedurname [(Argumente)]<br />

Anweisung<br />

...<br />

Anweisung<br />

End Sub<br />

Die (optionalen) Argumente können Referenzen (nicht der Wert selber<br />

wird übergeben, sondern der Zeiger, also die Adresse im Arbeitsspeicher)<br />

oder Werte se<strong>in</strong>. Zudem kann ihnen der Datentyp mitgegeben<br />

werden.<br />

Beispiel:<br />

Sub TestProzedur (ByRef Argument1 As Integer, ByVal Argument2 As Long)<br />

Zeiger = Argument1<br />

Wert = Argument2<br />

End Sub<br />

Der Aufruf dieser Prozedur sieht dann entweder so aus:<br />

TestProzedur Parameter1, Parameter2 oder so:<br />

Call TestProzedur(Parameter1, Parameter2)<br />

Prozeduren können Aktionen unterschiedlicher Art ausführen, sie können<br />

aber ke<strong>in</strong>e Werte zurückgeben. Hierzu bedarf es e<strong>in</strong>er Funktion.<br />

Die Syntax e<strong>in</strong>er Funktion ist ähnlich wie bei e<strong>in</strong>er Sub: sie beg<strong>in</strong>nen<br />

mit Function und enden mit End Function:<br />

[Public] [Private] [Static] Function Funktionsname [(Argumente)] [As<br />

Typ]<br />

Anweisung<br />

...<br />

Anweisung<br />

End Function<br />

2.1.4 Objekte, Eigenschaften und Methoden<br />

An dieser Stelle möchte ich die Gelegenheit nutzen, herauszustellen,<br />

warum <strong>VBA</strong> für viele Anwendungen e<strong>in</strong>e gute Alternative zu den etab-<br />

10


lierten Sprachen wie etwa C++ oder Java ist. Hierfür gibt es i.w. zwei<br />

handfeste Gründe:<br />

‣ Zum e<strong>in</strong>en s<strong>in</strong>d es die Makros, die dem <strong>Programm</strong>ierer nicht nur<br />

viel Arbeit abnehmen können, sondern die auch – wie bereits erwähnt<br />

– die Möglichkeit bieten, sich der Skriptsprache <strong>VBA</strong> Schritt<br />

für Schritt zu nähern.<br />

‣ Der zweite Grund ist der, dass <strong>in</strong> vielen Anwendungen – wie z.B. <strong>in</strong><br />

diesem <strong>Programm</strong> – fast ausschließlich mit Tabellen gearbeitet<br />

wird. Da bietet e<strong>in</strong>e Tabellenverarbeitung wie <strong>Excel</strong>, die etwa die<br />

200 wichtigsten Objekte mit ihren Eigenschaften und Methoden für<br />

jedermann frei zugänglich macht, e<strong>in</strong>e ideale Plattform für eigene<br />

Entwicklungen. <strong>E<strong>in</strong></strong> Großteil der Arbeit, die bei der Software-<br />

Entwicklung anfällt, nämlich die Planung der Objekte (Tabellenblätter,<br />

Zellen etc.), ist bereits erledigt, bevor man überhaupt damit angefangen<br />

hat, da sie bereits vorhanden s<strong>in</strong>d und genutzt werden<br />

können.<br />

Nun aber zum Thema - Objekte, Eigenschaften und Methoden <strong>in</strong> <strong>VBA</strong>.<br />

Was verbirgt sich eigentlich h<strong>in</strong>ter diesen Begriffen und – noch wichtiger<br />

- wie kann man diese Bauste<strong>in</strong>e für sich nutzen? Für den <strong>in</strong> der Objektorientierung<br />

erfahrenen Entwickler s<strong>in</strong>d die Begrifflichkeiten natürlich<br />

klar, dennoch profitiert auch der unerfahrene <strong>Programm</strong>ierer<br />

von den folgenden Ausführungen, da er praktisch gar ke<strong>in</strong>e Klassen<br />

und Objekte selbst def<strong>in</strong>ieren muss, weil ja alle notwendigen Bauteile<br />

bereits vorhanden s<strong>in</strong>d.<br />

2.1.4.1 Objekte und ihre Hierarchie<br />

Da <strong>VBA</strong> e<strong>in</strong>e - zum<strong>in</strong>dest teilweise - objektorientierte <strong>Programm</strong>iersprache<br />

(fehlende Implementierungsvererbung) ist, lassen sich natürlich<br />

eigene Klassen def<strong>in</strong>ieren und somit eigene Objekte erstellen. In<br />

den allerhäufigsten Fällen (so auch <strong>in</strong> diesem <strong>Programm</strong>) s<strong>in</strong>d es jedoch<br />

die MS-Office eigenen Objekte mit ihren Eigenschaften und Methoden,<br />

die <strong>in</strong> der Anwendung zum <strong>E<strong>in</strong></strong>satz kommen. Sie sollen hier <strong>in</strong> Kurzform<br />

dargestellt werden.<br />

Zu den wichtigsten Objekten zählen:<br />

APPLICATION <strong>Excel</strong> selbst / <strong>Excel</strong> – Fenster<br />

WORKBOOK Die <strong>Excel</strong> – Arbeitsmappe<br />

WORKSHEET <strong>E<strong>in</strong></strong> Tabellenblatt<br />

RANGE<br />

Zellenbereich , bestehend aus e<strong>in</strong>er oder mehrerer<br />

Zellen<br />

11


Die Objekte stehen <strong>in</strong> hierarchischer Abhängigkeit zue<strong>in</strong>ander. Objekte<br />

höherer Stufe be<strong>in</strong>halten Objekte untergeordneter Stufe(n). Für o.g.<br />

Objekte gilt die Hierarchieordnung.<br />

Application<br />

Workbook<br />

Worksheet<br />

Range<br />

Die gesamte Objekthierarchie ist natürlich wesentlich komplizierter und<br />

umfangreicher. Für die <strong>Programm</strong>ierung ist es wichtig zu wissen, dass<br />

die Objekthierarchie nicht nur e<strong>in</strong> willkürliches Ordnungsschema ist.<br />

Die Kenntnis der festgelegten Position e<strong>in</strong>es Objektes <strong>in</strong> der Hierarchie<br />

ist nötig, um das Objekt zu referenzieren – darauf zuzugreifen.<br />

Beispiel: Worksheets(list).Range("A1").EntireColumn.ColumnWidth = 22<br />

Der Objektkatalog enthält e<strong>in</strong>e Übersicht aller <strong>Excel</strong>-Objekte, ihrer Eigenschaften<br />

und Methoden. So rufen Sie den Objektkatalog auf:<br />

1. Öffnen Sie den <strong>VBA</strong>-Editor über die Tastenkomb<strong>in</strong>ation <br />

.<br />

2. Drücken Sie die Taste , um den Objektkatalog aufzurufen.<br />

3. Stellen Sie <strong>in</strong> der oberen Auswahlliste den <strong>E<strong>in</strong></strong>trag <strong>Excel</strong> e<strong>in</strong>.<br />

H<strong>in</strong>weis 3<br />

In dem Tabellenblatt Liste<br />

(Const list = "Liste") wird für<br />

die Spalte der Zelle "A1" die<br />

Spaltenbreite auf den Wert<br />

22 gesetzt.<br />

Abbildung 2<br />

Der Objektkatalog<br />

12


2.1.4.2 Eigenschaften<br />

Eigenschaften s<strong>in</strong>d die Attribute, die das Objekt beschreiben. Sie legen<br />

z.B. fest, wie das Objekt aussieht, welche Farbe oder welchen Wert es<br />

hat, ob es sichtbar ist oder nicht, usw. Es gibt Eigenschaften, die lesbar<br />

und veränderbar s<strong>in</strong>d, z.B. Value (Wert) oder Name (Name), andere<br />

lassen sich nur abfragen, aber nicht verändern.<br />

Beispiel:<br />

Sp_Name = Worksheets(1).Range("M" & (Zuf_Nr(d, n))).Value<br />

2.1.4.3 Methoden<br />

Zu den Objekten gehören neben Eigenschaften auch METHODEN. Über<br />

Methoden lässt sich das Verhalten von Objekten steuern / verändern.<br />

<strong>E<strong>in</strong></strong>e Methode ist e<strong>in</strong>e Aktion, die e<strong>in</strong>e Operation auf e<strong>in</strong>em Objekt ausführen<br />

kann. Zu den am häufigsten benutzten Methoden gehören:<br />

‣ OPEN öffnet e<strong>in</strong>e Arbeitsmappe<br />

‣ CLOSE schließt e<strong>in</strong>e Arbeitsmappe (e<strong>in</strong> Workbook-Objekt)<br />

oder <strong>Excel</strong> (e<strong>in</strong> Application-Objekt).<br />

‣ CLEAR löscht e<strong>in</strong>en Zellbereich oder e<strong>in</strong> Diagramm.<br />

‣ ACTIVATE<br />

‣ SELECT<br />

aktiviert e<strong>in</strong> Objekt<br />

wählt e<strong>in</strong> Objekt aus<br />

H<strong>in</strong>weis 4<br />

Der Variablen Sp_Name wird<br />

der Wert zugewiesen, der<br />

sich <strong>in</strong> Spalte "M" <strong>in</strong> der Zeile<br />

Zuf_Nr(d, n) bef<strong>in</strong>det<br />

Für den <strong>E<strong>in</strong></strong>steiger ist es oft problematisch zwischen Eigenschaften und<br />

Methoden zu unterscheiden (<strong>in</strong>sbesondere wenn Methoden die gleichen<br />

Namen tragen wie beispielsweise Auflistungen). So s<strong>in</strong>d beispielsweise<br />

die beiden Anweisungen<br />

Assistant.Visible = true<br />

Assistant.Move 250,275<br />

zum<strong>in</strong>dest optisch sehr ähnlich. Es stellt sich die Frage - s<strong>in</strong>d Visible<br />

und Move Eigenschaften oder Methoden und wenn nicht, welches Element<br />

von beiden ist e<strong>in</strong>e Methode und welches e<strong>in</strong>e Eigenschaft. Die<br />

Antwort ist hier relativ e<strong>in</strong>fach: Bei Zuweisungen von Eigenschaften<br />

wird das Gleichheitszeichen benutzt, bei Methoden benutzt man (optionale)<br />

Parameter ohne Gleichheitszeichen.<br />

13


Füllen Sie den Tabellenbereich "A1:A10" mit beliebigen Zahlen. Markieren<br />

Sie e<strong>in</strong>ige Zellen dieses Bereiches mit der H<strong>in</strong>tergrundfarbe "Rot".<br />

Fügen Sie <strong>in</strong> der Entwicklungsumgebung e<strong>in</strong> neues Modul e<strong>in</strong>, <strong>in</strong>dem<br />

Sie im Projekt-Explorer mit der rechten Maustaste klicken und den<br />

Kontextmenübefehl EINFÜGEN/MODUL wählen.<br />

Übung 2<br />

Benutzerdef<strong>in</strong>ierte Funktion<br />

schreiben<br />

Schreiben Sie e<strong>in</strong>e Funktion Function SummeRoteZellen(Zelle<br />

As Range), die nur die Zellen mit roter H<strong>in</strong>tergrundfarbe addiert.<br />

H<strong>in</strong>weise:<br />

1) Setzen Sie als erstes die Anweisung Application.Volatile.<br />

Hierdurch wird bewirkt, dass die Funktion immer neu berechnet<br />

wird, wenn <strong>in</strong> e<strong>in</strong>er beliebigen Zelle des Tabellenblattes e<strong>in</strong>e Berechnung<br />

durchgeführt wird<br />

2) Um jede Zelle e<strong>in</strong>es Bereiches zu erreichen, verwenden Sie die<br />

for-Schleife: For Each Zelle In Zelle.Cells<br />

3) Addieren Sie nur dann, wenn die Zelle e<strong>in</strong>en numerischen Wert<br />

enthält: If IsNumeric(Zelle)<br />

4) Abfrage der H<strong>in</strong>tergrundfarbe e<strong>in</strong>er Zelle des Bereiches auf die<br />

Farbe "Rot" mit If Zelle.Interior.ColorIndex = 3<br />

5) Addition der Funktionswerte: SummeRoteZellen = Summe-<br />

RoteZellen + Zelle.Value<br />

6) Prüfen Sie die Funktion, <strong>in</strong>dem Sie <strong>in</strong> Zelle "A11" die Formel e<strong>in</strong>geben<br />

"=SummeRoteZellen(A1:A10)"<br />

2.2 Die Gäste kommen<br />

Nun wieder zurück zu unserem Doppelkopfturnierprogramm. Die Teilnehmer<br />

melden sich größtenteils vor dem Turnier telefonisch oder per<br />

Mail, so dass sie bereits vorab <strong>in</strong> e<strong>in</strong>er Liste im <strong>Programm</strong> (<strong>in</strong> Spalte<br />

"A") aufgenommen werden können (das gesamte <strong>Excel</strong>-Sheet besteht zu<br />

diesem Zeitpunkt lediglich aus e<strong>in</strong>em Tabellenblatt). Es genügt dann<br />

am Turnierabend nur e<strong>in</strong> Klick, um die betreffende Person real am Turnier<br />

teilnehmen zu lassen.<br />

14


Abbildung 3<br />

Die Teilnehmerliste <strong>in</strong> Spalte<br />

"F"<br />

Rechtsklick oder Doppelklick <strong>in</strong><br />

e<strong>in</strong>e Zelle der Spalte "B" oder<br />

"C" aktiviert das ereignisgesteuerte<br />

Makro<br />

Sub<br />

Worksheet_BeforeRightClick<br />

bzw.<br />

Sub<br />

Worksheet_BeforeRightClick (s.<br />

2.4)<br />

H<strong>in</strong>weis 5<br />

Die "Häkchen" <strong>in</strong> Spalte B und<br />

C werden erzeugt mit dem<br />

Zeichen "ü" (= Chr (252)) <strong>in</strong> der<br />

Schriftart W<strong>in</strong>gd<strong>in</strong>gs (siehe<br />

auch List<strong>in</strong>g 2)<br />

Dieser Tabellenausschnitt macht deutlich, wie die Teilnehmerliste realisiert<br />

wird. In Spalte "A" können bereits vor Turnierbeg<strong>in</strong>n die Namen<br />

der möglichen Teilnehmer, sofern bekannt, e<strong>in</strong>getragen werden. Es genügt<br />

dann nur noch e<strong>in</strong> Doppelklick (oder Rechtsklick) <strong>in</strong> Spalte "B" (=<br />

bezahlt) oder "C" (= anwesend), um die betreffende Person <strong>in</strong> die tatsächliche<br />

Teilnehmerliste (Spalte "F") aufzunehmen. Die Teilnehmer<br />

werden mit e<strong>in</strong>er Spieler-Nummer (Spalte "E") versehen, welche aber<br />

im weiteren Verlauf des Turniers seitens des Teilnehmers nicht benötigt<br />

wird; die Spieler-Nr dient lediglich programm<strong>in</strong>ternen Zwecken (s. 2.4<br />

Ereignisse <strong>in</strong> <strong>VBA</strong>).<br />

Die programmtechnische Umsetzung dieses Vorgangs - die Erstellung<br />

der Spielerliste <strong>in</strong> Spalte "F" - muss noch e<strong>in</strong> wenig warten (2.4 Ereignisse<br />

<strong>in</strong> <strong>VBA</strong>).<br />

Vielmehr soll für all diejenigen, die bisher noch ke<strong>in</strong>erlei <strong>VBA</strong>-<br />

Erfahrung besitzen, im Folgenden e<strong>in</strong>e weitere kurze <strong>E<strong>in</strong></strong>führung <strong>in</strong><br />

<strong>VBA</strong> und der Entwicklungsumgebung gegeben werden.<br />

15


Der Projekt-Explorer: er enthält – hierarchisch gegliedert – alle Objekte,<br />

die zum <strong>VBA</strong>-Projekt "DokoTurnier.xlsx" gehören.<br />

Das Eigenschaftenfenster: <strong>in</strong> ihm werden alle Eigenschaften des ausgewählten<br />

Steuerelements angezeigt - <strong>in</strong> obiger Abbildung die Eigenschaften<br />

der Tabelle3. In der l<strong>in</strong>ken Spalte dieses Fensters steht der Name<br />

der Eigenschaft und <strong>in</strong> der rechten Spalte der zugehörige aktuelle Wert.<br />

Diese Werte können, wie wir bei den Steuerelementen von Formularen<br />

noch sehen werden, den eigenen Bedürfnissen angepasst werden, und<br />

zwar entweder durch das Überschreiben im Eigenschaftenfenster selbst<br />

oder aber per Quellcode-<strong>Programm</strong>ierung.<br />

Das Code-Fenster: <strong>in</strong> diesem Fenster (meistens werden mehrere gleichzeitig<br />

bearbeitet) bef<strong>in</strong>det sich der Quelltext des <strong>Programm</strong>s aus dem<br />

betreffenden Modul. Wie bereits <strong>in</strong> obigem Beispiel gesehen, ist der<br />

Makro-Recorder - <strong>in</strong>sbesondere für den <strong>VBA</strong>-Neul<strong>in</strong>g - e<strong>in</strong>e sehr gute<br />

Hilfe bei der Generierung des List<strong>in</strong>gs. Ohne jegliche VB-Kenntnisse zu<br />

besitzen, kann man sich so auf e<strong>in</strong>fache und schnelle Art und Weise e<strong>in</strong>en<br />

ersten Überblick über die gängigen Befehle verschaffen.<br />

Für darüber h<strong>in</strong>ausgehende Anpassungen s<strong>in</strong>d dann natürlich tiefergehende<br />

VB/<strong>VBA</strong>-Kenntnisse notwendig. Die wichtigsten Elemente hatte<br />

ich bereits <strong>in</strong> Kapitel 2.1 Grundsätzliches zur <strong>Programm</strong>ierung <strong>in</strong> <strong>VBA</strong><br />

vorgestellt. Ich halte es allerd<strong>in</strong>gs für unverhältnismäßig, im Rahmen<br />

dieses Workshops noch tiefer <strong>in</strong> diese Materie e<strong>in</strong>zusteigen. Für formale<br />

Elemente wie Datentypen, Variablen sowie sprachliche Konstrukte wie<br />

Schleifen, Verzweigungen etc. verweise ich zum e<strong>in</strong>en auf Onl<strong>in</strong>e-<br />

Recherchen im Internet sowie natürlich auf die <strong>in</strong> ausreichendem Maße<br />

vorhandene Literatur zur <strong>Excel</strong>-<strong>VBA</strong>-<strong>Programm</strong>ierung an. Nicht zuletzt<br />

können auch die List<strong>in</strong>gs hierzu e<strong>in</strong>en guten Beitrag leisten.<br />

2.4 Ereignisse <strong>in</strong> <strong>VBA</strong><br />

Nun aber wie versprochen zur Realisierung der Teilnehmerliste <strong>in</strong> <strong>VBA</strong>.<br />

Benötigt wird zu diesem Zweck e<strong>in</strong> bstimmtes technisches Hilfsmittel,<br />

und zwar die ereignisgesteuerte <strong>E<strong>in</strong></strong>gabemöglichkeit, z.B. per Rechtsklick<br />

(Sub Worksheet_BeforeRightClick) oder per Doppelklick (Sub<br />

Worksheet_BeforeDoubleClick). Diese beiden Funktionen überwachen<br />

die betreffenden Mausklicks und es lassen sich die gewünschten Aktionen<br />

mit ihnen verb<strong>in</strong>den. Schauen wir uns beispielhaft e<strong>in</strong>mal den<br />

Worksheet_BeforeDoubleClick an (die Tastenkomb<strong>in</strong>ation für die Entwicklungsumgebung<br />

ist uns nun bereits geläufig: < F11>):<br />

17


Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel<br />

As Boolean)<br />

Cancel = True<br />

Dim rng As Range<br />

If Intersect(Target, Worksheets(1).Range("B:C")) Is Noth<strong>in</strong>g Then<br />

Exit Sub<br />

If Target.Row = 1 Then Exit Sub<br />

If Target.Column = 2 Then<br />

If Target.Interior.ColorIndex = 4 Then<br />

'Color 4 = Farbe Grün<br />

Cells(Target.Offset(0, 2) + 1, 6) = "" 'Sp-Name löschen<br />

Cells(Target.Offset(0, 2) + 1, 5) = "" 'Sp-Nr löschen<br />

Target.Offset(0, 2).Value = ""<br />

'Nr <strong>in</strong> Spalte D löschen<br />

Target.Interior.ColorIndex = 0<br />

'Farbe zurücksetzen<br />

Target.Offset(0, 1).Interior.ColorIndex = 0<br />

Target.Offset(0, 1).Value = ""<br />

Target.Value = ""<br />

Range("I8").Value = Range("I8").Value - 1 'Anzahl Spieler<br />

Range("I9").Value = Range("I8").Value \ 4 'Anzahl Tische<br />

Range("I10").Value = Range("I8").Value Mod 4 'Anzahl 5er-Tische<br />

Else<br />

'<strong>in</strong> Liste aufnehmen<br />

If Target.Offset(0, 2) "" Then<br />

Target.Interior.ColorIndex = 4<br />

Target.Value = Chr(252)<br />

Exit Sub<br />

Else<br />

If Target.Offset(0, -1).Value = "" Then<br />

Exit Sub<br />

End If<br />

End If<br />

For Each rng In Worksheets(1).Range("F:F").Cells<br />

If IsEmpty(rng) Then<br />

lz = rng.Row<br />

rng = Target.Offset(0, -1).Value<br />

Target.Offset(0, 2).Value = lz - 1<br />

Cells(lz, 5).Value = lz - 1<br />

Target.Value = Chr(252)<br />

Target.Offset(0, 1).Value = Chr(252)<br />

Target.Interior.ColorIndex = 4<br />

Target.Offset(0, 1).Interior.ColorIndex = 4<br />

Range("I8").Value = Range("I8").Value + 1<br />

'erste freie Zelle <strong>in</strong><br />

Spalte "F"<br />

'Anzahl Spieler<br />

'Anzahl Tische<br />

Range("I9").Value = Range("I8").Value \ 4<br />

Range("I10").Value = Range("I8").Value Mod 4 'Anzahl<br />

5er-Tische<br />

End<br />

End If<br />

Next rng<br />

End If<br />

List<strong>in</strong>g 2<br />

Sub<br />

Worksheet_BeforeDouble<br />

Click(ByVal Target As<br />

Range, Cancel As<br />

Boolean)<br />

Abfrage e<strong>in</strong>er angeklickten<br />

Zelle <strong>in</strong> Spalte "B" auf Farbh<strong>in</strong>tergrund:<br />

falls grün (ColorIndex=4),<br />

dann Teilnehmer aus Liste <strong>in</strong><br />

Spalte "F"<br />

löschen, sonst<br />

Spieler neu <strong>in</strong> Spalte "F"<br />

aufnehmen<br />

Zu diesem List<strong>in</strong>g bedarf es nun e<strong>in</strong>iger Erläuterungen.<br />

Mit der Methode Intersect wird sichergestellt, dass nur dann weitere<br />

Aktionen stattf<strong>in</strong>den, wenn sich die aktuell markierte Zelle im Zielbereich<br />

Range("B:C") bef<strong>in</strong>det. Auch der Doppelklick <strong>in</strong> die 1. Zeile Target.Row<br />

= 1 soll ke<strong>in</strong>e weitere Aktion nach sich ziehen.<br />

Was passiert nun aber, wenn <strong>in</strong> Spalte "B" oder "C" e<strong>in</strong>e Zelle angeklickt<br />

wird? Der <strong>E<strong>in</strong></strong>fachheit halber soll hier nur das Vorgehen für die Spalte<br />

"B" (= bezahlt) erläutert werden: If Target.Column = 2 . Die Codierung<br />

für Spalte "C" (= anwesend") kann als Übung (s. Übung 3) dienen.<br />

18


Wird nun beispielsweise die Zelle "B88" rechtsgeklickt und ist die Zelle<br />

"A88" leer, so ist wiederum nichts zu tun: If Target.Offset(0, -1).Value =<br />

"" Then Exit Sub. Gibt es aber <strong>in</strong> Zelle "A88" e<strong>in</strong>en Teilnehmere<strong>in</strong>trag,<br />

so müssen zwei Fälle unterschieden werden: entweder die Zelle "B88"<br />

ist bereits mit e<strong>in</strong>em Häkchen markiert und mit grüner H<strong>in</strong>tergrundfarbe<br />

versehen, d.h. der Teilnehmer ist bereits aufgenommen und soll<br />

jetzt wieder gelöscht werden, oder die Zelle ist nicht markiert und der<br />

Teilnehmer aus "A88" muss noch <strong>in</strong> die Teilnehmerliste, also <strong>in</strong> Spalte<br />

"F" aufgenommen werden.<br />

Fall A: <strong>E<strong>in</strong></strong> Teilnehmer wird neu aufgenommen, Beispiel "Tanja Evers"<br />

durch Doppelklick <strong>in</strong> "B13"<br />

Es wird zunächst nach der ersten freien Zelle <strong>in</strong> Spalte "F" Ausschau<br />

gehalten For Each rng In Worksheets(1).Range("F:F").Cells If IsEmpty(rng)<br />

und die entsprechende Zeilennummer <strong>in</strong> der Variablen lz (steht<br />

für leerzelle) gespeichert lz = rng.Row. Der Spielername "Tanja Evers"<br />

wird aus "A13" <strong>in</strong> der Variablen rng zwischengespeichert rng = Target.Offset(0,<br />

-1).Value, und die - nur <strong>in</strong>tern vorgehaltene - Spielernummer<br />

<strong>in</strong> der Zelle "D13" (nicht sichtbar im Tabellenblatt, da für den Anwender<br />

ohne Belang) gemerkt (Target.Offset(0, 2).Value = lz - 1), um<br />

die Möglichkeit e<strong>in</strong>es Löschvorgangs nicht zu verbauen. Anschließend<br />

werden lediglich noch die Zellen "B13" und "C13" mit e<strong>in</strong>em Häkchen<br />

Target.Value = Chr(252) sowie der grünen Füllfarbe Target.Interior.ColorIndex<br />

= 4 versehen und es werden e<strong>in</strong>ige weitere Zellen<br />

("I8", "I9" und "I10" für die spätere Auslosung bereits mit Werten<br />

gefüllt, und zwar enthalten<br />

‣ "I8" die Anzahl der Spieler (bisherigen Wert um 1 erhöhen)<br />

Range("I8").Value = Range("I8").Value + 1<br />

‣ "I9" die Anzahl der benötigten Tische (= Anzahl der Spieler dividiert<br />

durch 4 als Integer-Wert)<br />

Range("I9").Value = Range("I8").Value \ 4<br />

‣ "I10" die Anzahl der benötigten 5er Tische (als Restwert der Division<br />

durch 4)<br />

Range("I10").Value = Range("I8").Value Mod 4<br />

H<strong>in</strong>weis 6<br />

Chr (252) entspricht dem<br />

Zeichen "ü" und liefert <strong>in</strong> der<br />

Schriftart W<strong>in</strong>gd<strong>in</strong>gs das<br />

Häkchen<br />

Fall B: <strong>E<strong>in</strong></strong> bereits aufgenommener Teilnehmer wird wieder aus der<br />

Liste entfernt, Beispiel "Gerd Förster" (etwa weil man sich "verklickt"<br />

hat)<br />

In diesem Fall ist die Zelle "B18" grün markiert: If Target.Interior.ColorIndex<br />

= 4. Der Spieler muss nun wieder aus der Liste<br />

<strong>in</strong> Spalte "F" gelöscht werden.<br />

19


Die Zeile, <strong>in</strong> der er <strong>in</strong> Spalte "F" e<strong>in</strong>getragen wurde, ist leicht wieder<br />

auff<strong>in</strong>dbar, da die Spieler-Nummer <strong>in</strong> "D13" zwischengespeichert wurde:<br />

Offset(0, 2). Der Löschvorgang wird ausgelöst über die Anweisung<br />

Cells(Target.Offset(0, 2) + 1, 6) = "", also das Löschen derjenigen Zelle,<br />

dessen Zeile um den Wert 1 erhöht <strong>in</strong> "D13" steht und dessen Spalte<br />

gleich 6 ist. Ebenso muss die <strong>in</strong> "C13" vorgenommene Markierung wieder<br />

entfernt werden, und es muss die Anzahl der Spieler, die Anzahl der<br />

Tische und die Anzahl der 5er-Tische korrigiert werden.<br />

Vervollständigen Sie den Quellcode für den Doppelklick auf e<strong>in</strong> Zelle<br />

<strong>in</strong> Spalte "C".<br />

Übung 3<br />

Ereignissteuerung<br />

2.5 Der Kern des <strong>Programm</strong>s: die Auslosung<br />

Nachdem sich die Teilnehmer angemeldet haben und <strong>in</strong> die Spielerliste<br />

<strong>in</strong> Spalte "F" aufgenommen wurden, erfolgt die<br />

Auslosung, d.h. die Zuordnung der e<strong>in</strong>zelnen<br />

Spieler zu den Spieltischen. Hierfür steht im<br />

Tabellenblatt Auslosung e<strong>in</strong> Button mit dem Text Auslosung starten<br />

bereit (erstellen lässt er sich über die Menüleiste mit<br />

ENTWICKLERTOOLS, EINFÜGEN aus der Gruppe<br />

STEUERELEMENTE, Element BEFEHLSSCHALTFLÄCHE). <strong>E<strong>in</strong></strong><br />

Klick auf diesen Button startet das Ma<strong>in</strong>-<strong>Programm</strong> Sub Auslosung() im<br />

Modul des Tabellenblattes Auslosung.<br />

An dieser Stelle ist nun der Zeitpunkt gekommen, den Aufbau und die<br />

wesentlichen Bestandteile des Auslosungsprogramms zunächst e<strong>in</strong>mal<br />

<strong>in</strong> groben Zügen vorzustellen, um anschließend <strong>in</strong> den Kapiteln 2.5.1 bis<br />

2.5.3 auf die e<strong>in</strong>zelnen Teile näher e<strong>in</strong>zugehen.<br />

Zu Beg<strong>in</strong>n des <strong>Programm</strong>s Sub Auslosung() sollen vom Anwender über<br />

e<strong>in</strong>en Dialog (s. Abbildung 5, Seite 22) die Startparameter "Anzahl der<br />

Durchgänge" und "Anzahl der Runden pro Durchgang" festgelegt werden.<br />

Anschließend besteht die wesentliche Aufgabe des <strong>Programm</strong>s dar<strong>in</strong><br />

‣ e<strong>in</strong> Tabellenblatt Liste zu erstellen, aus der hervorgeht, wer <strong>in</strong> welchem<br />

Durchgang an welchem Tisch mit welcher Platz-Nr teilnimmt<br />

(s. 2.5.2.1 Das Tabellenblatt "Liste")<br />

‣ pro Durchgang e<strong>in</strong> Tabellenblatt für die <strong>E<strong>in</strong></strong>gabe der erreichten<br />

Punkte zu erstellen (s. 2.5.2.2 Pro Durchgang je e<strong>in</strong> Tabellenblatt)<br />

20


‣ den Teilnehmern per Mischprogramm e<strong>in</strong>en Platz an e<strong>in</strong>em Tisch<br />

zuzuweisen: Sub Tischzuweisung() (s. 2.5.3 Das Mischprogramm)<br />

‣ e<strong>in</strong> Tabellenblatt Ergebnis mit e<strong>in</strong>er sortierten Rangfolge der Teilnehmer<br />

zu erzeugen: Sub ergebnis() (s. 2.5.2.3 Das Tabellenblatt "Ergebnis")<br />

Diese vier Aspekte werden – wie erwähnt - ausführlich als <strong>E<strong>in</strong></strong>zelthemen<br />

<strong>in</strong> den genannten Abschnitten gesondert behandelt.<br />

Um mit dem Ma<strong>in</strong>-<strong>Programm</strong> vertraut zu werden, werfen wir zunächst<br />

e<strong>in</strong>en Blick<br />

a) auf die global def<strong>in</strong>ierten Variablen und<br />

b) auf die <strong>E<strong>in</strong></strong>gabemaske für die Startparameter<br />

Zu a) Die global def<strong>in</strong>ierten Variablen und Konstanten stehen ganz am<br />

Anfang des Moduls (Modul des Tabellenblattes Auslosung) und s<strong>in</strong>d<br />

für alle <strong>in</strong> diesem Modul e<strong>in</strong>gesetzten Prozeduren verfügbar.<br />

Const MaxAnzDg = 10<br />

Const MaxAnzRd = 10<br />

Const ZeilBeg = 3<br />

Const SpBeg = 2<br />

Const HGrFaSp = 6<br />

Const HGrFaTi = 32<br />

Const list = "Liste"<br />

Const dg = "Durchgang"<br />

Const erg = "Ergebnis"<br />

Const wf4e = "Wert-Form4e"<br />

Const wf4v = "Wert-Form4v"<br />

Const wf5e = "Wert-Form5e"<br />

Const wf5v = "Wert-Form5v"<br />

Const AnzTiProBlock = 4<br />

'maximale Anzahl Durchgänge<br />

'maximale Anzahl Runden pro Durchgang<br />

'<strong>in</strong> den Durchgangsblättern beg<strong>in</strong>nen<br />

die Tischüberschriften ab Zeile 3<br />

'und Spalte B<br />

'H<strong>in</strong>tergrundfarbe <strong>in</strong> SpielerZelle<br />

(Durchgangs-Tabelle)<br />

'H<strong>in</strong>tergrundfarbe <strong>in</strong> TischüberschriftZelle<br />

(Durchgangs-Tabelle)<br />

'Name des Tabellenblattes "Liste"<br />

'Name für Durchgangs-Tabellenblätter<br />

'Name des Tabellenblattes "Ergebnis"<br />

'Name der Tabellenblätter für die<br />

Standard-Spielzettel mit 4 Spielern<br />

'Name der Tabellenblätter für die<br />

DDV-Spielzettel mit 4 Spielern<br />

'Name der Tabellenblätter für die<br />

Standard-Spielzettel mit 5 Spielern<br />

'Name der Tabellenblätter für die<br />

DDV-Spielzettel mit 5 Spielern<br />

'Anzahl Tische im 16-er Block<br />

List<strong>in</strong>g 3<br />

Globale <strong>Programm</strong>-Variable<br />

des Auslosungsprogramms<br />

Public Anz_Dg As Integer 'Anzahl Durchgänge<br />

Public DurchBeg As Integer 'Bei welchem Durchgang soll begonnen<br />

werden<br />

Dim Zuf_Nr() As Integer '2-dimensionale Tabelle, enthält<br />

Zufalls-Nr und Durchgangs-Nr<br />

Dim Anz_Sp() As Integer 'e<strong>in</strong>dimensionale Tabelle mit Anzahl<br />

Spielern pro Durchgang<br />

Dim Max_AnzSp As Variant 'maximale Anzahl an Spielern<br />

(alle Durchgänge)<br />

Dim Anz_5erTi() As Integer 'Anzahl der 5-er Tische pro Durchgang<br />

Dim Max_Anz_5erTi() As Integer 'max. Anzahl an möglichen 5-er Tischen<br />

pro Durchgang<br />

Dim Anz_16Bl() As Integer 'Anzahl 16-er Blöcke<br />

Dim Anz_Tische() As Integer 'Anzahl benötigter Tische<br />

...<br />

21


Leicht zu erkennen an der Variablen-Deklaration Const MaxAnzDg = 10<br />

sowie Const MaxAnzRd = 10 ist die Festlegung auf maximal 10 Durchgänge<br />

sowie 10 Runden pro Durchgang. Bei e<strong>in</strong>em "normalen" Turnier<br />

s<strong>in</strong>d i.A. nicht mehr als 4 Durchgänge und 4 Runden pro Durchgang<br />

üblich, so dass diese Werte allemal ausreichend s<strong>in</strong>d.<br />

Alle weiteren Deklarationen s<strong>in</strong>d h<strong>in</strong>sichtlich ihrer Funktion anhand<br />

der Kommentierung zu erkennen bzw. werden noch im weiteren Verlauf<br />

im jeweiligen Zusammenhang erläutert.<br />

Zu b) Nun wieder zurück zum Auslosungsprogramm. Wie bereits erwähnt,<br />

ersche<strong>in</strong>t nach dem Start für den Anwender e<strong>in</strong>e <strong>E<strong>in</strong></strong>gabemaske<br />

mit der Abfrage nach der gewünschten Anzahl der Durchgänge und der<br />

Anzahl der Runden pro Durchgang (s. Abbildung 5).<br />

H<strong>in</strong>weis 7<br />

Im List<strong>in</strong>g 3 wird deutlich,<br />

wie Kommentare im Queltext<br />

<strong>in</strong>nerhalb e<strong>in</strong>er Zeile<br />

gesetzt werden: durch e<strong>in</strong>en<br />

Apostroph<br />

Abbildung 5<br />

Die Userform Startparameter<br />

Auslosung<br />

Zusätzlich lässt sich, falls die Vore<strong>in</strong>stellung nicht übernommen werden<br />

soll, die Anzahl der <strong>in</strong>sgesamt benötigten Tische durch e<strong>in</strong>e Erhöhung<br />

der 5er-Tische verr<strong>in</strong>gern (s. 2.5.4 Zusatzfunktionen, Punkt (2)).<br />

Aktiviert wird diese selbst erstellte <strong>E<strong>in</strong></strong>gabemaske, e<strong>in</strong>e sogenannte<br />

UserForm, im <strong>Programm</strong> durch den Befehl StartAuslosung.Show.<br />

StartAuslosung ist hierbei der Name dieser Dialogmaske. Dieser Name<br />

f<strong>in</strong>det sich wieder im Eigenschaftenfenster dieser UserForm <strong>in</strong> der Entwicklungsumgebung<br />

(s. Abbildung 9).<br />

Das ist ja nun soweit alles gut und schön, wirft aber viele neue Fragen<br />

auf, wie z.B. "womit und wie lässt sich so e<strong>in</strong>e Dialog-Box erstellen",<br />

"wie lässt sie sich im <strong>Programm</strong> anzeigen/aktivieren", "wie kann man<br />

22


sie programmieren", "wie werden Daten entgegengenommen und wieder<br />

zurückgegeben", usw.<br />

Diesem Thema wollen wir uns nun <strong>in</strong> 2.5.1 Schritt für Schritt nähern.<br />

2.5.1 Eigene Dialoge entwerfen und programmieren<br />

Zunächst e<strong>in</strong>mal muss e<strong>in</strong>e sogenannte Userform erzeugt und anschließend<br />

den eigenen Bedürfnissen entsprechend angepasst werden. Hierfür<br />

wechselt man wieder <strong>in</strong> die Entwicklungsumgebung (Tastenkomb<strong>in</strong>ation<br />

wie gehabt ).<br />

Abbildung 6<br />

Der Projekt-Explorer<br />

Im Projekt-Explorer (wird standardmäßig <strong>in</strong> der Entwicklunksumgebung<br />

oben l<strong>in</strong>ks e<strong>in</strong>geblendet, siehe auch 2.3 Die Entwicklungsumgebung<br />

von <strong>VBA</strong> sowie Abbildung 2) werden die Objekte und Dateien angezeigt,<br />

die zum Projekt gehören. Man sieht, dass die Arbeitsmappe zurzeit nur<br />

aus e<strong>in</strong>er Tabelle (mit dem Namen Auslosung) und zwei Formularen<br />

(DruckenSpielzettel und StartAuslosung) besteht. Der Doppelklick<br />

auf e<strong>in</strong> Objekt öffnet die Möglichkeit zu ihrer Bearbeitung, beispielsweise<br />

öffnet sich beim Tabellenmodul Tabelle1(Auslosung) der Editor mit<br />

dem Quellcode des Hauptprogramms.<br />

Hier <strong>in</strong> diesen Bereich des Projekt-Explorers klickt man mit der rechten<br />

Maustaste; falls der Projekt-Explorer nicht ersche<strong>in</strong>t, muss er noch über<br />

den Menüpunkt ANSICHT aufgerufen werden (alternativ Tastenkomb<strong>in</strong>ation<br />

).<br />

23


In dem darauffolgenden Kontextmenü wählt man den Befehl<br />

EINFÜGEN/USERFORM (Abbildung 7).<br />

Abbildung 7<br />

UserForm e<strong>in</strong>fügen<br />

Nun bekommt man e<strong>in</strong> leeres Formular namens UserForm1 zur Verfügung<br />

gestellt, zusammen mit e<strong>in</strong>er Werkzeugsammlung, die die wichtigsten<br />

Steuerelemente enthält (Abbildung 8). Über das Menü<br />

EXTRAS/ZUSÄTZLICHE STEUERELEMENTE können bei Bedarf<br />

weitere Elemente h<strong>in</strong>zugefügt werden. Damit steht dem Entwickler e<strong>in</strong><br />

großes Repertoire an Hilfsmitteln zur Verfügung, mit denen er sich se<strong>in</strong>e<br />

Dialogmaske den eigenen Vorstellungen entsprechend zusammenbasteln<br />

kann.<br />

Abbildung 8<br />

UserForm mit<br />

Werkzeugsammlung<br />

Für unsere Userform StartAuslosung (die derzeit noch UserForm1<br />

heißt), werden folgende Steuerelemente benötigt:<br />

24


‣ sechs Bezeichnungsfelder (Label) für die Beschriftungen "Wieviel<br />

Durchgänge <strong>in</strong>sgesamt", "Tische gesamt", etc.<br />

‣ fünf Textfelder (TextBox) für die Anzeige und <strong>E<strong>in</strong></strong>gabe von Daten<br />

wie z.B. Anzahl der Durchgänge<br />

‣ für drei der fünf Textfelder (s. Abbildung 5) jeweils e<strong>in</strong> Drehfeld<br />

(Sp<strong>in</strong>Button) für das schrittweise Hochzählen der Werte <strong>in</strong> den<br />

Textfeldern<br />

‣ zwei Befehlsschaltflächen<br />

(CommandButton) für die Ausführung<br />

von Befehlen (z.B. )<br />

<strong>E<strong>in</strong></strong> e<strong>in</strong>zelnes Steuerelement kann, nachdem es <strong>in</strong> der Werkzeugsammlung<br />

ausgewählt wurde, <strong>in</strong> der Userform platziert und den eigenen Bedürfnissen<br />

angepasst werden. Die Anpassungen erfolgen zum e<strong>in</strong>en<br />

über die Mausoperationen, um etwa das Element zu vergrößern oder zu<br />

verkle<strong>in</strong>ern und an die richtige Stelle zu setzen, zum anderen aber auch<br />

über das Editieren im zugehörigen Eigenschaften-Fenster (sichtbar unterhalb<br />

des Projektexplorers per oder Menü ANSICHT/<br />

EIGENSCHAFTENFENSTER).<br />

Die beiden folgenden Abbildungen 9 und 10 zeigen <strong>in</strong> Ausschnitten zwei<br />

Beispiele von Eigenschaften-Fenstern.<br />

Beispiel 1: Das Eigenschaften-Fenster StartAuslosung<br />

Abbildung 9<br />

Eigenschaftenfenster<br />

StartAuslosung<br />

Hier handelt es sich um die Userform selbst. Der von <strong>VBA</strong> bei der Erstellung<br />

der UserForm vorgeschlagene Name UserForm1 wurde <strong>in</strong>zwischen<br />

<strong>in</strong> StartAuslosung geändert.<br />

25


Beispiel 2: Das Eigenschaften-Fenster TextBox3<br />

Abbildung 10<br />

Eigenschaftenfenster<br />

TextBox3<br />

Diese TextBox enthält das Steuerelement zur <strong>E<strong>in</strong></strong>gabe der Tischanzahl.<br />

In diesem Fall wurde der von <strong>VBA</strong> vorgeschlagene Name Text-<br />

Box3 beibehalten.<br />

Kommen wir nun zur Makro-<strong>Programm</strong>ierung dieser Steuerelemente,<br />

also der Möglichkeit, sie per Quellcode zu bearbeiten/"steuern".<br />

Um das Formular StartAuslosung zu <strong>in</strong>itialisieren bzw. zu ändern,<br />

führen wir zunächst e<strong>in</strong>en Doppelklick <strong>in</strong>nerhalb des Formulars (oder<br />

Kontextmenü CODE ANZEIGEN) aus. <strong>Excel</strong> generiert automatisch<br />

e<strong>in</strong>en leeren <strong>Programm</strong>rahmen zum Editieren(Abbildung 11).<br />

Abbildung 11<br />

<strong>Programm</strong>rahmen e<strong>in</strong>er User-<br />

Form<br />

Am oberen Rand sieht man<br />

zwei Listenfelder. Im rechten<br />

Listenfeld hat man neben dem<br />

(ereignisgesteuerten) Click<br />

u.a. auch die Möglichkeit e<strong>in</strong>er<br />

Initialisierung. Die Auswahl<br />

dieses Elementes erzeugt<br />

automatisch den Text<br />

Private Sub userform_<strong>in</strong>itialize()<br />

Die Textboxen der <strong>in</strong> Abbildung 5 (Seite 22) dargestellten UserForm<br />

(TextBox1 = Anzahl der Durchgänge, TextBox2 = Anzahl der Runden<br />

und TextBox3 = Anzahl der Tische) sollten nun mit Standard-Werten<br />

<strong>in</strong>itialisiert werden. Während die Textboxen 1 und 2 bereits im jeweiligen<br />

Eigenschaftenfenster mit den Anfangswerten 3 (= Anzahl Durch-<br />

End Sub<br />

26


gänge) und 4 (= Anzahl Runden) versehen werden können, ist dies bei<br />

der Anzahl der Tische nicht möglich; die Anzahl der Tische ist abhängig<br />

von der Anzahl der Teilnehmer und muss daher per Quellcode-<br />

<strong>Programm</strong>ierung berechnet werden:<br />

Private Sub userform_<strong>in</strong>itialize()<br />

Dim AnzSp As Integer<br />

Dim MaxAnzTi As Integer<br />

...<br />

If Worksheets(1).Range("M1").Value = "" Then<br />

AnzSp = 0<br />

Else<br />

AnzSp = Range Worksheets(1).Range("I8").Value 'Anzahl Spieler<br />

End If<br />

List<strong>in</strong>g 4<br />

Sub<br />

userform_<strong>in</strong>itialize()<br />

Vorbelegung Anzahl der<br />

Tische <strong>in</strong> TextBox3 mit dem<br />

maximal möglichen Wert<br />

MaxAnzTi = AnzSp \ 4<br />

Sp<strong>in</strong>Button3.Value = MaxAnzTi<br />

TextBox3.Value = Sp<strong>in</strong>Button3.Value<br />

Sp<strong>in</strong>Button1.M<strong>in</strong> = Worksheets(1).Range("I11").Value + 1<br />

End Sub<br />

Im nächsten Schritt geht es darum, e<strong>in</strong> Makro für die Änderung der<br />

Tischanzahl zu schreiben. Da die Änderung über das nebenstehende<br />

Drehfeld Sp<strong>in</strong>Button3 erfolgen soll, ist für die TextBox3 selber ke<strong>in</strong>e<br />

Codierung notwendig, wohl aber für das nebenstehende Drehfeld. Führen<br />

wir zunächst e<strong>in</strong>en Doppelklick auf die Schaltfläche Sp<strong>in</strong>Button3 <strong>in</strong><br />

der Userform StartAuslosung aus, generiert <strong>Excel</strong> wiederum automatisch<br />

e<strong>in</strong>en leeren <strong>Programm</strong>rahmen, diesmal mit der Option Change:<br />

Private Sub Sp<strong>in</strong>Button3_Change()<br />

End Sub<br />

In diesem Rahmen werden nun die gewünschten Anpassungen bzw.<br />

Berechnungen vorgenommen (s. auch List<strong>in</strong>g 16, Seite 43):<br />

Private Sub Sp<strong>in</strong>Button3_Change()<br />

Dim Max_AnzSp As Integer<br />

Dim AnzSp As Integer<br />

Dim i As Integer<br />

Dim MaxAnzTi As Integer<br />

Dim M<strong>in</strong>AnzTi As Integer<br />

Dim Anz5erTi() As Integer<br />

Dim Anz4erTi() As Integer<br />

Dim Anz_Tische() As Integer<br />

'Max-Anzahl Spieler alle Durchgänge<br />

'Anzahl Spieler <strong>in</strong> e<strong>in</strong>em Durchgang<br />

'Anzahl Tische Maximum<br />

'Anzahl Tische M<strong>in</strong>imum<br />

'Anzahl 5er-Tische<br />

'Anzahl 4er-Tische<br />

'Anzahl benötigter Tische <strong>in</strong>sgesamt<br />

List<strong>in</strong>g 5<br />

Sub<br />

Sp<strong>in</strong>Button3_Change()<br />

If Worksheets(1).Range("M1").Value = "" Then<br />

AnzSp = 0<br />

Else<br />

AnzSp = Worksheets(1).Range("I8").Value 'Anzahl Spieler<br />

End If<br />

27


If AnzSp > Max_AnzSp Then<br />

Max_AnzSp = AnzSp<br />

Worksheets(1).Range("H3").Value = Max_AnzSp<br />

End If<br />

MaxAnzTi = AnzSp \ 4<br />

If AnzSp Mod 5 = 0 Then<br />

M<strong>in</strong>AnzTi = AnzSp \ 5<br />

Else<br />

M<strong>in</strong>AnzTi = AnzSp \ 5 + 1<br />

End If<br />

Sp<strong>in</strong>Button3.M<strong>in</strong> = M<strong>in</strong>AnzTi<br />

Sp<strong>in</strong>Button3.Max = MaxAnzTi<br />

TextBox3.Text = Sp<strong>in</strong>Button3.Value<br />

ReDim Preserve Anz5erTi(M<strong>in</strong>AnzTi To MaxAnzTi)<br />

ReDim Preserve Anz4erTi(M<strong>in</strong>AnzTi To MaxAnzTi)<br />

For i = M<strong>in</strong>AnzTi To MaxAnzTi<br />

Anz4erTi(i) = 5 * i - AnzSp<br />

Anz5erTi(i) = i - Anz4erTi(i)<br />

Next i<br />

TextBox4.Value = Anz5erTi(Sp<strong>in</strong>Button3.Value)<br />

TextBox5.Value = Anz4erTi(Sp<strong>in</strong>Button3.Value)<br />

End Sub<br />

Durch die Variablen Max_AnzSp und AnzSp soll man sich nicht irritieren<br />

lassen. Sie dienen im <strong>Programm</strong> nur zur Differenzierung nach Anzahl<br />

der Spieler pro Durchgang, falls mal jemand nach e<strong>in</strong>em Durchgang<br />

aussteigt oder neu dazu kommt (s. 2.5.4 Zusatzfunktionen). Es soll<br />

hier eigentlich nur deutlich werden, wie die Eigenschaften dieses Elementes<br />

durch die Makro-<strong>Programm</strong>ierung gesteuert werden können.<br />

Zunächst e<strong>in</strong>mal werden die maximale und m<strong>in</strong>imale Anzahl an benötigten<br />

Tischen berechnet (MaxAnzTi und M<strong>in</strong>AnzTi) und ihre Werte<br />

den Variablen Sp<strong>in</strong>Button3.M<strong>in</strong> und Sp<strong>in</strong>Button3.Max zugewiesen.<br />

Damit hat das Drehfeld Sp<strong>in</strong>Button3 die Eigenschaften maximal möglicher<br />

Wert und m<strong>in</strong>imal möglicher Wert zugewiesen bekommen. Da<br />

über die Anweisung TextBox3.Text = Sp<strong>in</strong>Button3.Value die TextBox3<br />

mit dem Drehfeld Sp<strong>in</strong>Button3 verbunden ist, kann somit die Text-<br />

Box3 jetzt nur noch Werte <strong>in</strong>nerhalb dieses Intervalls annehmen. Aus<br />

diesen Ausführungen wird auch deutlich, dass <strong>in</strong> diesem Fall e<strong>in</strong>e<br />

Quellcode-<strong>Programm</strong>ierung unumgänglich ist, da Maximal- und M<strong>in</strong>imal-Wert<br />

jeweils variabel s<strong>in</strong>d. <strong>E<strong>in</strong></strong> <strong>E<strong>in</strong></strong>trag im Eigenschaften-Fenster<br />

macht somit ke<strong>in</strong>en S<strong>in</strong>n, auch wenn diese Optionen im Eigenschaftenfenster<br />

von Sp<strong>in</strong>Button3 mit Max bzw. M<strong>in</strong> vorgesehen s<strong>in</strong>d und somit<br />

auch möglich wären.<br />

Aus dem Quelltext geht ferner hervor, dass für jeden möglichen Wert<br />

zwischen der m<strong>in</strong>imalen und maximalen Anzahl an Tischen e<strong>in</strong>e Aufteilung<br />

<strong>in</strong> Anzahl 4er-Tische (= TextBox4) und Anzahl 5er-Tische (=<br />

28


2.5.2 Die neuen Tabellenblätter<br />

Zu Beg<strong>in</strong>n des <strong>Programm</strong>s existiert lediglich das Tabellenblatt mit dem<br />

Namen Auslosung. Es besteht i.w. aus der Teilnehmerliste (s. Abbildung<br />

3) und dem Button Auslosung starten. Mit dem Klick auf diesen<br />

Button wird das <strong>Programm</strong> Sub Auslosung() ausgeführt. Es ist das<br />

Haupt-<strong>Programm</strong>. Es sorgt zunächst e<strong>in</strong>mal dafür, dass jeder Teilnehmer<br />

für jeden e<strong>in</strong>zelnen Durchgang e<strong>in</strong>en zufällig ausgewählten Tisch-<br />

Platz zugewiesen bekommt. Nachdem das erfolgt ist, können neue zusätzliche<br />

Tabellenblätter generiert werden, und zwar<br />

‣ e<strong>in</strong> Tabellenblatt Liste als Übersicht<br />

‣ je e<strong>in</strong> Tabellenblatt pro Durchgang zur <strong>E<strong>in</strong></strong>gabe der erreichten<br />

Punktzahl pro Spieler<br />

‣ e<strong>in</strong> Tabellenblatt Ergebnis, <strong>in</strong> dem die Punktzahlen e<strong>in</strong>es jeden<br />

Teilnehmers übersichtlich dargestellt werden<br />

<strong>E<strong>in</strong></strong> neues Tabellenblatt wird <strong>in</strong> <strong>VBA</strong> mit der Funktion Worksheets.Add<br />

erzeugt.<br />

2.5.2.1 Das Tabellenblatt "Liste"<br />

Dieses Tabellenblatt enthält e<strong>in</strong>e übersichtliche Liste aller Teilnehmer,<br />

aus der hervorgeht, welcher Spieler <strong>in</strong> welchem Durchgang an welchem<br />

Tisch mit welcher Tisch-Nr spielt.<br />

Mit der Anweisung Worksheets.Add<br />

After:=Worksheets(Worksheets.Count) wird h<strong>in</strong>ter dem letzten Tabellenblatt<br />

e<strong>in</strong> neues angehängt. Es bekommt den Namen Liste. list ist<br />

e<strong>in</strong>e globale Konstante: Const list = "Liste".<br />

Worksheets(1).Cells(2, 9).Value = Anz_Dg<br />

Worksheets(1).Cells(1, 9).Value = Worksheets(1).Cells(11, 9).Value<br />

Worksheets.Add After:=Worksheets(Worksheets.Count)<br />

Worksheets(Worksheets.Count).Name = list 'Erstellung des Tabellenblattes<br />

"Liste"<br />

Worksheets(1).Range("M:M").Copy<br />

Dest<strong>in</strong>ation:=Worksheets(list).Range("A:A")<br />

Worksheets(list).Range("A1").Insert<br />

Worksheets(list).Range("A1").EntireColumn.ColumnWidth = 22<br />

Dieses Tabellenblatt dient dazu, e<strong>in</strong>e übersichtliche, alphabetisch sortierte<br />

Liste zu erstellen, aus der für jeden Spieler hervorgeht, <strong>in</strong> welchem<br />

Durchgang er an welchem Tisch spielt. Aus dieser Liste kann z.B.<br />

die Teilnehmer<strong>in</strong> Marlies Bäumer erkennen, dass sie im ersten Durchgang<br />

am Tisch 4 spielt mit der Tisch-Nr 2 (s. Abbildung 13).<br />

List<strong>in</strong>g 7<br />

Tabellenblatt Liste h<strong>in</strong>zufügen<br />

H<strong>in</strong>weis 10<br />

Die Spielerliste wurde <strong>in</strong> der<br />

Zwischenzeit im Tabellenblatt<br />

Auslosung<br />

(=Worksheets(1) von Spalte<br />

"F" nach Spalte "M" kopiert.<br />

32


Durch e<strong>in</strong>en Klick auf den Button Liste drucken kann die Liste (evtl.<br />

mehrfach) ausgedruckt werden und als Aushang (an evtl. verschiedenen<br />

Örtlichkeiten) angebracht werden.<br />

Abbildung 13<br />

Tabellenblatt Liste<br />

bereits vorformatiert und<br />

nach Namen sortiert<br />

2.5.2.2 Pro Durchgang je e<strong>in</strong> Tabellenblatt<br />

Im Anschluss an das Listentabellenblatt folgt pro Durchgang je e<strong>in</strong> weiteres<br />

Tabellenblatt für die <strong>E<strong>in</strong></strong>gabe der erreichten Punkte jedes e<strong>in</strong>zelnen<br />

Spielers.<br />

For d = DurchBeg To Anz_Dg<br />

'Erstellung der<br />

Durchgangstabellenblätter<br />

Worksheets.Add After:=Worksheets(Worksheets.Count)<br />

Worksheets(d + 2).Name = d & ". " & dg 'Name des Durchgangs-<br />

Tabellenblattes: const dg = Durchgang<br />

Sheets(d + 2).Range("A1").EntireColumn.ColumnWidth = 5 'es folgen<br />

weitere Formatierungen<br />

Sheets(d + 2).Range("B1").EntireColumn.ColumnWidth = 22<br />

...<br />

...<br />

Next d<br />

List<strong>in</strong>g 8<br />

Je e<strong>in</strong> Tabellenblatt pro<br />

Durchgang h<strong>in</strong>zufügen<br />

<strong>E<strong>in</strong></strong> komplett durchformatiertes Tabellenblatt hat dann folgendes Aussehen<br />

(Abbildung 14):<br />

Abbildung 14<br />

Tabellenblatt 1. Durchgang<br />

33


Aus der Abbildung lässt sich schon mal grob erkennen, was bei der Codierung<br />

alles zu beachten ist:<br />

‣ Spaltenbreiten festlegen<br />

‣ Überschriften berücksichtigen<br />

‣ Unterscheidung zwischen 5er- und 4er-Tischen<br />

‣ Werden alle Tische nebene<strong>in</strong>ander auf dem Bildschirm platziert,<br />

wird die spätere <strong>E<strong>in</strong></strong>gabe der Punkte umständlich; übersichtlicher<br />

wird es, wenn jeweils 4 Tische zu e<strong>in</strong>em Block zusammengefasst<br />

werden, und die Blöcke jeweils untere<strong>in</strong>ander zu stehen<br />

‣ Neben den Formatierungen der e<strong>in</strong>zelnen Zellen erfolgt die Zuweisung<br />

der Teilnehmer zu den e<strong>in</strong>zelnen Tischen. Auf die Implementierung<br />

dieses Vorganges, dem Mischvorgang, wird im<br />

Abschnitt "2.5.3 Wer kommt <strong>in</strong> welchem Durchgang an welchem<br />

Platz?" näher e<strong>in</strong>gegangen.<br />

‣ Die Zellen mit dem Wert 0 enthalten als Formel die Summe aller<br />

Punkte pro Tisch<br />

Worksheets(d + 2).Cells(zeile, spalte + 1).FormulaR1C1 =<br />

"=SUM(R[-5]C:R[-1]C)"<br />

Sie muss <strong>in</strong> jedem Falle als Ergebnis den Wert 0 ergeben (sofern<br />

an den Tischen die Punkte mit Plus/M<strong>in</strong>us notiert werden). Der<br />

Nutzen dieser Summenformel liegt dar<strong>in</strong>, dass direkt bei <strong>E<strong>in</strong></strong>gabe<br />

der Punktzahl ersichtlich wird, ob an dem betreffenden Tisch<br />

korrekt gezählt wurde.<br />

H<strong>in</strong>weis 11<br />

Anzahl der Tische pro Block<br />

s. List<strong>in</strong>g 3 (Glob. Variable)<br />

Const AnzTiProBlock=4<br />

'Anzahl Tische im 16-er Block<br />

List<strong>in</strong>g 9<br />

Summenformel pro Tisch<br />

2.5.2.3 Das Tabellenblatt "Ergebnis"<br />

Nachdem der Anwender die Punktzahlen der Spieler <strong>in</strong> die Durchgangs-<br />

Tabellenblätter e<strong>in</strong>getragen hat, möchte er sich natürlich die Gesamtergebnisse<br />

<strong>in</strong> e<strong>in</strong>er Übersicht anschauen können. Hierzu dient das Tabellenblatt<br />

Ergebnis, welches als letztes vom Haupt-<strong>Programm</strong> Sub Auslosung<br />

erzeugt wird (s. Abbildung 15).<br />

Worksheets.Add After:=Worksheets(Worksheets.Count)<br />

Worksheets(Worksheets.Count).Name = erg<br />

'Tabellenblatt "Ergebnis"<br />

ganz am Ende<br />

Worksheets(erg).Range("A1").EntireColumn.ColumnWidth = 4.43<br />

Worksheets(1).Range("M:M").Copy<br />

Dest<strong>in</strong>ation:=Worksheets(erg).Range("B:B")<br />

...<br />

List<strong>in</strong>g 10<br />

Tabellenblatt Ergebnis h<strong>in</strong>zufügen<br />

34


Abbildung 15<br />

Tabellenblatt Ergebnis<br />

Die Formatierung der Zellen hält sich hier <strong>in</strong> Grenzen. Es werden i.w.<br />

lediglich die Teilnehmer nach Spalte "B" kopiert und es wird e<strong>in</strong> Button<br />

Punkte aus allen Durchgängen generiert. H<strong>in</strong>ter diesem Button verbirgt<br />

sich das Unterprogramm Sub Ergebnis. Dieser <strong>Programm</strong>teil sorgt<br />

dafür, dass die Punktzahlen e<strong>in</strong>es jeden Spielers aus den e<strong>in</strong>zelnen<br />

Durchgängen <strong>in</strong> die Ergebnisliste übernommen werden. Die Spalte "B"<br />

<strong>in</strong> dem Ergebnis-Tabellenblatt mit den Spielernamen wird Zeile für Zeile<br />

abgearbeitet, wobei für jeden Durchgang nach dem entsprechenden<br />

Namen <strong>in</strong> der Spalte "K" der Durchgangstabelle (s. auch "2.5.3 Wer<br />

kommt <strong>in</strong> welchem Durchgang an welchem Platz?") gesucht wird; wurde<br />

er gefunden, wird die betreffende Punktzahl für den Spieler <strong>in</strong> die Ergebnisliste<br />

übernommen.<br />

H<strong>in</strong>weis 12<br />

Spalte "A" ist reserviert für<br />

die Rangfolge (s. Abbildung<br />

16, Seite 36)<br />

Außerdem werden noch zwei weitere Buttons generiert:<br />

ErgSortRangButtonErstellen<br />

ErgDruckButtonErstellen<br />

'Ergebnisliste nach Punktzahl sortieren<br />

'Ergebnisliste ausdrucken<br />

Die sich h<strong>in</strong>ter ihnen verbergenden Makros s<strong>in</strong>d selbsterklärend und<br />

recht e<strong>in</strong>fach zu implemetieren.<br />

Der Quellcode der Ergebnis-Prozedur sieht nun wie folgt aus:<br />

Sub ergebnis()<br />

ErgSortNameButtonErstellen<br />

ErgSortRangButtonErstellen<br />

ErgDruckButtonErstellen<br />

List<strong>in</strong>g 11<br />

Quellcode Sub Ergebnis()<br />

Anz_Dg = Worksheets(1).Range("I6")<br />

Max_AnzSp = Worksheets(1).Range("H3").Value<br />

Sheets(list).Range("A:A").Copy Dest<strong>in</strong>ation:=Sheets(erg).Range("B:B")<br />

For n = 1 To Anz_Dg + 3<br />

'und noch e<strong>in</strong> bisschen die<br />

Tabelle formatieren<br />

Worksheets(erg).Cells(1, n).Interior.ColorIndex = HGrFaSp<br />

Worksheets(erg).Cells(1, n).Font.Bold = True<br />

35


For m = 1 To Worksheets(erg).Range("B" &<br />

Rows.Count).End(xlUp).Row<br />

Worksheets(erg).Cells(m, n).Borders.L<strong>in</strong>eStyle = xlCont<strong>in</strong>uous<br />

Next m<br />

Next n<br />

Worksheets(erg).Cells(1, 2).Value = "Name Vorname"<br />

With Worksheets(erg)<br />

Set bereich = .Range(.Cells(2, 3), .Cells(Max_AnzSp + 1, Anz_Dg<br />

+ 2))<br />

bereich.Value = ""<br />

End With<br />

Sheets(erg).Range("A2:A" & Max_AnzSp + 1).Value = ""<br />

Dim Mat As Variant<br />

For d = 1 To Anz_Dg<br />

For n = 2 To Max_AnzSp + 1<br />

Mat = Application.Match(Sheets(erg).Range("B" & n), Sheets(d &<br />

". " & dg).Range("K:K"), 0)<br />

If Not IsError(Mat) Then<br />

Sheets(erg).Cells(n, d + 2).Value = Sheets(d & ". " &<br />

dg).Range("L" & Mat).Value<br />

End If<br />

Next n<br />

Next d<br />

H<strong>in</strong>weis 13<br />

Übernahme der Punktzahl<br />

aus den Durchgangs-<br />

Tabellenblättern<br />

Die Ergebnis-Tabelle könnte nach der Übernahme der Punktzahl und<br />

anschließender Sortierung etwa folgendes Aussehen haben:<br />

Abbildung 16<br />

Tabellenblatt Ergebnis<br />

komplett durch formatiert<br />

2.5.3 Das Mischprogramm: wer kommt <strong>in</strong> welchem Durchgang an welchem<br />

Tisch an welchem Platz?<br />

Machen wir nun wieder e<strong>in</strong>en Sprung zurück zum Haupt-<strong>Programm</strong><br />

Sub Auslosung() und kommen zum eigentlichen Kern.<br />

Nachdem der Anwender im Start-Dialog StartAuslosung (s. Abbildung<br />

5) se<strong>in</strong>e <strong>E<strong>in</strong></strong>gaben gemacht hat, steht nun für das Turnier fest, wie viel<br />

Durchgänge gespielt werden, wie viel Runden pro Durchgang gespielt<br />

werden und wie viel Personen auf wie viel 4er-Tische und 5er-Tische<br />

verteilt werden müssen. Die eigentliche Auslosung kann nun beg<strong>in</strong>nen.<br />

36


Im Mischprogramm Sub Tischzuweiung bekommt jeder e<strong>in</strong>zelne Teilnehmer<br />

für jeden e<strong>in</strong>zelnen Durchgang per Zufallsgenerator e<strong>in</strong>en Platz<br />

an e<strong>in</strong>em Tisch zugewiesen.<br />

Sub Tischzuweisung()<br />

ReDim Zuf_Nr(1 To Anz_Dg, 1 To Anz_Sp(d))<br />

Dim q As Integer, z As Integer, tmp As Integer<br />

For q = 1 To Anz_Sp(d)<br />

Zuf_Nr(d, q) = q<br />

Next<br />

For q = Anz_Sp(d) To 1 Step -1<br />

Randomize<br />

z = Int(Rnd * q) + 1<br />

'Vorbelegung der Zuf_Nr-Tabelle<br />

mit 1, 2, 3,...,q<br />

'neuer Startwert für Rnd-Funktion<br />

'z = Zufallszahl zwischen 1 und q<br />

tmp = Zuf_Nr(d, z) 'tausche Zuf_Nr(d, z)<br />

Zuf_Nr(d, z) = Zuf_Nr(d, q) 'mit<br />

Zuf_Nr(d, q) = tmp 'Zuf_Nr(d, q)<br />

Next<br />

...<br />

List<strong>in</strong>g 12<br />

Quellcode Sub Tischzuweisung<br />

Mit der ReDim-Anweisung wird der bereits deklarierte array Zuf_Nr()<br />

zum e<strong>in</strong>en als 2-dimensionale Tabelle deklariert und zum zweiten wird<br />

die array-Länge def<strong>in</strong>iert ( Länge der 1.Dimension = Anz_Dg = Anzahl<br />

der Durchgänge, Länge der 2.Dimension = Anz_Sp(d)= Anzahl Spieler<br />

<strong>in</strong> Durchgang d).<br />

Der Mischalgorithmus br<strong>in</strong>gt e<strong>in</strong>e Zahlenfolge von 1 bis Anz_Sp(d) <strong>in</strong><br />

e<strong>in</strong>e zufällige Anordnung. Dies kann man sich wie folgt vorstellen: man<br />

hat e<strong>in</strong>en Kartenstapel vor sich mit Anz_Sp(d) (=Anzahl Spieler pro<br />

Durchgang) Karten. Nun wird die unterste Karte mit e<strong>in</strong>er zufälligen<br />

anderen über ihr liegenden Karte getauscht, dann die zweit-unterste,<br />

danach die dritt-unterste usw.<br />

Anschließend hat man also pro Durchgang e<strong>in</strong>e Zahlenfolge von 1 bis<br />

Anz_Sp(d) generiert, die per Zufallsgenerator <strong>in</strong> e<strong>in</strong>e zufällig angeordnete<br />

Reihenfolge gebracht wurde. Jetzt kann man daran gehen, diese<br />

Liste sukzessive von vorne bis h<strong>in</strong>ten abzuarbeiten und dabei die Teilnehmer<br />

(sie s<strong>in</strong>d <strong>in</strong> der Zwischenzeit nach Spalte "M" kopiert worden)<br />

<strong>in</strong> dieser zufällig ausgewählten Reihenfolge auf die e<strong>in</strong>zelnen Tische zu<br />

verteilen:<br />

Sp_Name = Worksheets(1).Range("M" & (Zuf_Nr(d, n))).Value (s.<br />

Quellcode <strong>in</strong> der Unterprozedur Sub ZelleMitNameFuellen() <strong>in</strong> List<strong>in</strong>g<br />

13)<br />

In dieser Reihenfolge werden nun die Spieler auf die e<strong>in</strong>zelnen Tische<br />

verteilt, zuerst die 5er-Tische, danach die 4er-Tische.<br />

37


Optisch aufbereitet sollen die Durchgangs-Tabellenblätter das <strong>in</strong> der<br />

Abbildung 14 (Seite 33) dargestellte Aussehen haben. Vier Tische, nebene<strong>in</strong>ander<br />

dargestellt – jeder Tisch besteht aus zwei Spalten, nämlich<br />

Name und Punktzahl – bilden dabei jeweils e<strong>in</strong>en Block. Die Blöcke<br />

wiederum werden untere<strong>in</strong>ander platziert, wobei zwischen zwei Blöcken<br />

jeweils zwei Zeilen frei gelassen werden (aus der Abbildung 14 nicht ersichtlich,<br />

da <strong>in</strong> unserem Beispiel nur e<strong>in</strong> Block benötigt wurde).<br />

Die Implementierung erfolgt naturgemäß über mehrere Schleifen:<br />

‣ ganz außen die Schleife der Blöcke For i16b = 1 To Anz_16Bl(d)<br />

‣ <strong>in</strong>nerhalb e<strong>in</strong>es Blockes 4 Tische For itb = 1 To AnzTiProBlock<br />

(beachte globale Konstante Const AnzTiProBlock = 4)<br />

‣ <strong>in</strong>nerhalb e<strong>in</strong>es Tisches 7 Zeilen For j = 1 To 7 'bei den<br />

4er-Tischen 6 Zeilen<br />

Es folgt nun der komplette Quellcode für die 5er-Tische <strong>in</strong> der Prozedur<br />

Sub Tischzuweisung() (= Fortsetzug von List<strong>in</strong>g 12):<br />

n = 1<br />

'Zähler für Spieler<br />

it = 1<br />

'Laufvariable für Tische<br />

i5t = 1<br />

'Laufvariable für 5er-Tische<br />

(für 4er-Tische nicht erforderlich, da es nur diese beiden Möglichkeiten gibt)<br />

For i16b = 1 To Anz_16Bl(d)<br />

'Abarbeitung blockweise: mehrere Tische<br />

pro Block (Vore<strong>in</strong>stellung = 4)<br />

For itb = 1 To AnzTiProBlock<br />

'weitere Abarbeitung tischweise<br />

(AnzTiProBlock = 4)<br />

spalte = SpBeg + 2 * (itb - 1) 'Festlegung der Spalte pro Tisch<br />

If it


Case 2 To 6<br />

ZelleMitNameFuellen<br />

'Zeile 2 bis 6 = Befüllung mit Namen<br />

'<strong>E<strong>in</strong></strong>trag des Teilnehmers <strong>in</strong> die<br />

entsprechende Zelle<br />

Case 7 '7.Zeile = Summ-formel für Zeilen 2 bis 6<br />

Worksheets(d + 2).Cells(zeile, spalte + 1).FormulaR1C1 =<br />

"=SUM(R[-5]C:R[-1]C)"<br />

Worksheets(d + 2).Cells(zeile, spalte +<br />

1).FormatConditions.Delete<br />

Worksheets(d + 2).Cells(zeile, spalte +<br />

1).FormatConditions.Add _<br />

Type:=xlCellValue, Operator:=xlNotEqual, Formula1:="0"<br />

With Worksheets(d + 2).Cells(zeile, spalte +<br />

1).FormatConditions(1).Font<br />

.Bold = True<br />

.Italic = False<br />

.ColorIndex = 3<br />

End With<br />

Worksheets(d + 2).Cells(zeile, spalte +<br />

1).FormatConditions(1).Interior.ColorIndex = 5<br />

Worksheets(d + 2).Cells(zeile, spalte +<br />

1).HorizontalAlignment = xlCenter<br />

End Select<br />

Next j<br />

i5t = i5t + 1 'nach Abarbeitung 5er-Tisch Zähler um 1<br />

erhöhen<br />

Else ... 'Abarbeitung der 4er-Tische nach dem<br />

gleichen Schema<br />

Sub ZelleMitNameFuellen()<br />

Dim Sp_Name As Str<strong>in</strong>g<br />

Dim MatchZeile As Variant<br />

Sp_Name = Worksheets(1).Range("M" & (Zuf_Nr(d, n))).Value 'Zeile aus<br />

Spalte "M" entspricht Zufallszahl<br />

Worksheets(d + 2).Cells(zeile, spalte) = Sp_Name<br />

'<strong>E<strong>in</strong></strong>tragung<br />

des Spielers <strong>in</strong> der Durchgangs-Tabelle<br />

Worksheets(d + 2).Cells(zeile, spalte).Locked = True 'entsprechende<br />

Zelle sperren<br />

Worksheets(d + 2).Cells(zeile, spalte).Borders.L<strong>in</strong>eStyle =<br />

xlCont<strong>in</strong>uous<br />

Worksheets(d + 2).Cells(zeile, spalte).HorizontalAlignment =<br />

xlCenter<br />

Worksheets(d + 2).Cells(zeile, spalte).Interior.ColorIndex = HGrFaSp<br />

Worksheets(d + 2).Cells(zeile, spalte + 1).Borders.L<strong>in</strong>eStyle =<br />

xlCont<strong>in</strong>uous<br />

Worksheets(d + 2).Cells(zeile, spalte + 1).HorizontalAlignment =<br />

xlCenter<br />

Worksheets(d + 2).Cells(zeile, spalte + 1).Interior.ColorIndex =<br />

HGrFaSp<br />

Worksheets(d + 2).Cells(n, 11).Value = Sp_Name 'zusätzlich<br />

den Namen <strong>in</strong> Spalte "K" der Durchgangstabelle e<strong>in</strong>tragen<br />

Worksheets(d + 2).Cells(n, 11).Locked = True<br />

'und die<br />

betreffende Zelle sperren<br />

Worksheets(d + 2).Cells(n, 12).Formula = "=R" & zeile & "C" & spalte<br />

+ 1 & "" 'außerdem die Punktzahl des Spielers automatisch übernehmen lassen<br />

Worksheets(d + 2).Cells(n, 12).Locked = True 'und auch diese Zelle<br />

(gleiche Zeile, aber Spalte "L"), sperren lassen<br />

MatchZeile = Application.Match(Sp_Name, Sheets(list).Range("A:A"), 0)<br />

'Spielernamen <strong>in</strong> Tabelle "Liste", Spalte "A" suchen<br />

If IsError(MatchZeile) Then 'falls noch nicht vorhanden<br />

lz = Sheets(list).Range("A" & Rows.Count).End(xlUp).Row + 1<br />

'neue Zeile "aufmachen"<br />

39


Sheets(list).Range("A" & lz).Value = Sp_Name 'und <strong>in</strong> dieser den Namen<br />

e<strong>in</strong>tragen<br />

Worksheets(list).Cells(lz, d + 1).Value = it & "(" & j - 1 & ")"<br />

'mit <strong>E<strong>in</strong></strong>trag der Tisch- und Platz-Nr <strong>in</strong> der betreffenden Durchgangsspalte<br />

Else 'falls schon vorhanden<br />

Worksheets(list).Cells(MatchZeile, d + 1).Value = it & "(" & j - 1<br />

& ")"<br />

'<strong>E<strong>in</strong></strong>trag der Tisch- und Platz-Nr <strong>in</strong> der betreffenden Durchgangsspalte<br />

End If<br />

n = n + 1<br />

'Nach <strong>E<strong>in</strong></strong>tragung <strong>in</strong> Durchgangs-Tabelle<br />

Spierzähler um 1 erhöhen<br />

End Sub<br />

Für jeden Tisch wird zunächst e<strong>in</strong>mal e<strong>in</strong>e Überschrift erzeugt (Case 1),<br />

dann <strong>in</strong> der Unterprozedur ZelleMitNameFuellen() die Spielernamen<br />

e<strong>in</strong>getragen (Case 2 To 6) und zum Schluss (Case 7) noch e<strong>in</strong>e Summenformel<br />

notiert, <strong>in</strong> der die Summe der erreichten Punktzahl pro<br />

Tisch berechnet wird (s. auch List<strong>in</strong>g 9). Sie dient lediglich als Kontrolle,<br />

da bekanntermaßen bei e<strong>in</strong>er Plus-M<strong>in</strong>us-Wertung die Gesamtsumme<br />

immer Null se<strong>in</strong> muss.<br />

Sukzessive holt sich die Unterprozedur ZelleMitNameFuellen() aus dem<br />

1.Tabellenblatt (=Tabellenblatt mit dem Namen Auslosung) e<strong>in</strong>e zuvor<br />

zufällig ausgewählte Zelle der Spalte "M"<br />

Sp_Name = Worksheets(1).Range("M" & (Zuf_Nr(d, n))).Value<br />

und überträgt dessen Inhalt – den Spielernamen – <strong>in</strong> die dafür vorgesehene<br />

Zelle der Durchgangstabelle:<br />

Worksheets(d + 2).Cells(zeile, spalte) = Sp_Name<br />

Der gleiche Spieler(name) wird zusätzlich noch <strong>in</strong> Spalte "K" e<strong>in</strong>getragen,<br />

Worksheets(d + 2).Cells(n, 11).Value = Sp_Name<br />

und mit ihm noch <strong>in</strong> der Zelle rechts daneben, also <strong>in</strong> Spalte "L" der<br />

gleichen Zeile e<strong>in</strong>e Formel zur Übernahme der Punkte; somit werden<br />

alle Änderungen <strong>in</strong> der Punktezahl-Zelle des Spielers mit übernommen:<br />

Worksheets(d + 2).Cells(n, 12).Formula = "=R" & zeile & "C" & spalte +<br />

1 & ""<br />

Die beiden Spalten "K" und "L" spielen später bei Übernahme der<br />

Punktzahl e<strong>in</strong>es Spielers <strong>in</strong> das Tabellenblatt Ergebnis noch e<strong>in</strong>e wichtige<br />

Rolle.<br />

H<strong>in</strong>weis 14<br />

Die Spielerliste wurde bereits<br />

zu Beg<strong>in</strong>n des Ma<strong>in</strong>-<strong>Programm</strong>s<br />

Sub Auslosung von<br />

Spalte "F" nach Spalte "M"<br />

kopiert.<br />

H<strong>in</strong>weis 15<br />

s. List<strong>in</strong>g 11 bzw. H<strong>in</strong>weis<br />

13, Seite 36<br />

Im weiteren Verlauf wird <strong>in</strong> dem Tabellenblatt Liste nach dem betreffenden<br />

Spielernamen gesucht:<br />

MatchZeile = Application.Match(Sp_Name, Sheets(list).Range("A:A"),<br />

0)<br />

40


Wurde er nicht gefunden, wird er neu <strong>in</strong> die Liste mit aufgenommen.<br />

Dies ersche<strong>in</strong>t zunächst e<strong>in</strong>mal umständlich programmiert; es hat lediglich<br />

damit zu tun, dass <strong>in</strong> diesem <strong>Programm</strong> die Möglichkeit berücksichtigt<br />

wird, dass <strong>in</strong> e<strong>in</strong>em Durchgang Spieler neu h<strong>in</strong>zukommen oder<br />

- aus welchen Gründen auch immer - nicht weiter am Turnier teilnehmen<br />

(s. auch das folgende Kapitel 2.5.4 Zusatzfunktionen, Punkt (1)).<br />

2.5.4 Zusatzfunktionen<br />

Die Schwerpunkte des <strong>Programm</strong>s wurden <strong>in</strong> allen wichtigen Punkten<br />

vorgestellt. Das Rüstzeug für die Implementierung <strong>in</strong> <strong>VBA</strong> steht nunmehr<br />

bereit.<br />

Das komplette <strong>Programm</strong> bietet allerd<strong>in</strong>gs noch e<strong>in</strong>ige Sonderfunktionen,<br />

die im Folgenden vorgestellt werden sollen.<br />

(1) Teilnehmer können nach e<strong>in</strong>em gespielten Durchgang ausfallen<br />

oder neu h<strong>in</strong>zukommen.<br />

Abbildung 17<br />

Die Zellen I6 bis I11 im Tabellenblatt<br />

"Auslosung"<br />

Die Zellen I6 und I7 werden<br />

nach <strong>E<strong>in</strong></strong>gabe der Startparameter<br />

gefüllt, die Zellen I8 bis<br />

I10 bereits vor Beg<strong>in</strong>n des<br />

Auslosungsprogramms (s. 2.4<br />

Ereignisse <strong>in</strong> VBE)<br />

In diesem Fall bietet das <strong>Programm</strong> die Möglichkeit, ab e<strong>in</strong>em bestimmten,<br />

selbst gewählten Zeitpunkt e<strong>in</strong>en oder mehrere noch<br />

nicht gespielte Durchgänge neu zu mischen. Hierzu dient im Tabellenblatt<br />

Auslosung die Zelle "I11" (s. Abbildung 17), <strong>in</strong> dem die Anzahl<br />

der bereits gespielten Durchgänge manuell hochgesetzt werden<br />

kann. Wenn dann erneut die Schaltfläche Auslosung starten gedrückt<br />

wird, werden nur noch die nicht gespielten Durchgänge neu<br />

gemischt.<br />

Zu diesem Zweck wird im <strong>Programm</strong> e<strong>in</strong>e Variable DurchBeg deklariert,<br />

die aus der Zelle "I11" e<strong>in</strong>gelesen und um 1 erhöht wird:<br />

DurchBeg = Worksheets(1).Range("I11") + 1<br />

41


Außerdem werden bei Spielbeg<strong>in</strong>n (DurchBeg = 1) alle Tabellenblätter<br />

entfernt, jedoch bei e<strong>in</strong>er erneuten Auslosung ab dem zweiten<br />

Durchgang nur die noch nicht benutzten Durchgangstabellenblätter.<br />

Die Tabellenblätter Liste und Ergebnis werden ohneh<strong>in</strong> <strong>in</strong> jedem<br />

Fall neu generiert.<br />

Public DurchBeg As Integer 'bei welchem Durchgang soll<br />

begonnen werden<br />

...<br />

DurchBeg = Worksheets(1).Range("I11") + 1<br />

...<br />

If DurchBeg = 1 Then<br />

'bei Spielbeg<strong>in</strong>n alle Tabellenblätter löschen bis auf das<br />

"Auslosung"s-Tabellenblatt<br />

For d = 1 To (ActiveWorkbook.Sheets.Count - 1)<br />

Sheets(2).Delete<br />

Next<br />

End If<br />

...<br />

If DurchBeg > 1 Then<br />

On Error Resume Next<br />

For d = DurchBeg To MaxAnzDg<br />

Sheets(d & ". " & dg).Delete<br />

Next<br />

End If<br />

...<br />

'falls erneute Auslosung (ab<br />

Durchgang 2),<br />

'die Durchgangstabellenblätter<br />

löschen,<br />

'die anschließend per Auslosung<br />

'neu erstellt werden<br />

List<strong>in</strong>g 14<br />

Nach e<strong>in</strong>em bereits gespielten<br />

Durchgang soll neu gemischt<br />

werden<br />

(2) Die Gesamtanzahl der Tische lässt sich dadurch reduzieren, dass<br />

die Anzahl der 5er-Tische erhöht wird auf das maximal Mögliche<br />

Die Möglichkeit hierzu wurde bereits bei der Erläuterung der Dialogbox<br />

für die Startparameter der Auslosung im Kapitel 2.5 Der<br />

Kern des <strong>Programm</strong>s: die Auslosung erwähnt.<br />

Die Zellen "I9" = Anzahl 4er-Tische und "I10" = Anzahl 5er-Tische<br />

(s. Abbildung 17) werden direkt bereits bei der (ereignisgesteuerten)<br />

Aufnahme e<strong>in</strong>es Spielers <strong>in</strong> die Teilnehmerliste (s. Kap. "2.4 Ereignisse<br />

<strong>in</strong> VBE") berechnet. Da es sich um ganzzahlig def<strong>in</strong>ierte Zellen<br />

handelt, ist die Berechnung auf recht e<strong>in</strong>fache Weise zu bewerkstelligen:<br />

H<strong>in</strong>weis 16<br />

Im Kapitel "2.4 Ereignisse<br />

<strong>in</strong> VBE" wurden bereits die<br />

<strong>in</strong> Abbildung 17 zu sehenden<br />

Zellen "I8", "I9" und "I10" im<br />

Tabellenblatt "Auslosung"<br />

vorgestellt.<br />

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel<br />

As Boolean)<br />

...<br />

Range("I9").Value = Range("I8").Value \ 4<br />

'I8 = Anzahl der<br />

Teilnehmer<br />

Range("I10").Value = Range("I8").Value Mod 4 'Rest bei Division<br />

durch 4<br />

List<strong>in</strong>g 15<br />

Berechnung der Werte für<br />

Zellen "I9" und "I10"<br />

42


Somit s<strong>in</strong>d die beiden Zellen "I9" und "I10" mit Inhalt gefüllt, bevor<br />

das Hauptprogramm Sub Auslosung startet. Die Sub Auslosung<br />

kann nun diese Zellen e<strong>in</strong>lesen und die entsprechenden Variablen<br />

mit dessen Inhalt <strong>in</strong>itialisieren, z.B.:<br />

Anz_5erTi(d) = Worksheets(1).Cells(10, 9).Value<br />

Für den Anwender besteht nun über die bereits <strong>in</strong> Kapitel 2.5 (siehe<br />

auch Abbildung 5, Seite 22) erwähnte Dialog-Box Startparameter<br />

Auslosung die Möglichkeit, e<strong>in</strong>e Änderung vorzunehmen und zwar<br />

<strong>in</strong> der Textbox TextBox3. Dies geschieht – wir er<strong>in</strong>nern uns – über<br />

das Drehfeld Sp<strong>in</strong>Button3. Die Prozedur zum Ändern lautet Private<br />

Sub Sp<strong>in</strong>Button3_Change(). Sie enthält die Berechnung der 4erund<br />

5er-Tische:<br />

H<strong>in</strong>weis 17<br />

Bzgl. TextBox3 und Sp<strong>in</strong>-<br />

Button3 vgl. die Ausführungen<br />

Seite 26/27<br />

Private Sub Sp<strong>in</strong>Button3_Change()<br />

...<br />

MaxAnzTi = AnzSp \ 4<br />

If AnzSp Mod 5 = 0 Then<br />

M<strong>in</strong>AnzTi = AnzSp \ 5<br />

Else<br />

M<strong>in</strong>AnzTi = AnzSp \ 5 + 1<br />

End If<br />

List<strong>in</strong>g 16<br />

Quellcode zur Änderung der<br />

Tischanzahl (s. auch List<strong>in</strong>g<br />

5)<br />

Sp<strong>in</strong>Button3.M<strong>in</strong> = M<strong>in</strong>AnzTi<br />

Sp<strong>in</strong>Button3.Max = MaxAnzTi<br />

TextBox3.Text = Sp<strong>in</strong>Button3.Value<br />

ReDim Preserve Anz5erTi(M<strong>in</strong>AnzTi To MaxAnzTi)<br />

ReDim Preserve Anz4erTi(M<strong>in</strong>AnzTi To MaxAnzTi)<br />

For i = M<strong>in</strong>AnzTi To MaxAnzTi<br />

Anz4erTi(i) = 5 * i - AnzSp<br />

Anz5erTi(i) = i - Anz4erTi(i)<br />

Next i<br />

TextBox4.Value = Anz5erTi(Sp<strong>in</strong>Button3.Value)<br />

TextBox5.Value = Anz4erTi(Sp<strong>in</strong>Button3.Value)<br />

Hier werden zunächst die m<strong>in</strong>imale und maximale Anzahl der Tische<br />

festgelegt (berechnet) und <strong>in</strong> Sp<strong>in</strong>Button3.M<strong>in</strong> sowie Sp<strong>in</strong>Button3.Max<br />

als Extremwerte e<strong>in</strong>getragen, damit der Anwender diese<br />

Grenzen nicht unter-/überschreiten kann. Innerhalb dieses Intervalls<br />

werden <strong>in</strong> e<strong>in</strong>er M<strong>in</strong>i-Tabelle für jeden e<strong>in</strong>zelnen Wert die Anzahl<br />

der 4er- und 5er-Tische berechnet und <strong>in</strong> den beiden folgenden<br />

Textboxen ausgegeben.<br />

(3) Zwei Spielzettelversionen<br />

Wie aus der Abbildung 13 <strong>in</strong> "2.5.2.1 Das Tabellenblatt Liste" zu ersehen<br />

ist, werden zusammen mit der Generierung des Tabellenblattes<br />

noch zwei Buttons/Makros erzeugt zur Druckausgabe: zum e<strong>in</strong>en die<br />

43


Teilnehmerliste mit Tisch- und Platz-Nr und zum zweiten für jeden<br />

Tisch e<strong>in</strong> vorgefertigter Spielzettel, der die Namen der Teilnehmer<br />

bereits be<strong>in</strong>haltet.<br />

Die Besonderheit dieser Spielzettel liegt nun dar<strong>in</strong>, dass der Anwender<br />

e<strong>in</strong>e Auswahl treffen kann zwischen zwei Varianten, und zwar<br />

zwischen e<strong>in</strong>em recht e<strong>in</strong>fach gehaltenen Spielzettel und dem offiziellen<br />

Spielzettel des DDV (Deutscher Doppelkopf Verband).<br />

Abbildung 18<br />

UserForm Drucken<br />

<strong>E<strong>in</strong></strong>gabemaske für die Auswahl<br />

der Spielzettel<br />

("privat/e<strong>in</strong>fach" oder<br />

"offiziell nach DDV")<br />

Als Gastgeber e<strong>in</strong>es <strong>in</strong>offiziellen privaten Turniers empfiehlt sich die<br />

e<strong>in</strong>fachere Variante. Möchte man jedoch streng nach den Turnierspiel-Regeln<br />

des DDV das Turnier ausrichten, so wählt man den offiziellen<br />

DDV-Spielzettel.<br />

Damit man sich e<strong>in</strong>e Vorstellung von den Spielzetteln machen kann,<br />

werden beide Varianten beispielhaft für e<strong>in</strong>en 5er-Tisch (jeweils für<br />

den 1. Durchgang mit vier Runden bzw. – als Extrembeispiel – mit<br />

zehn Runden) auf den Folgeseiten abgebildet.<br />

44


Die programmtechnische Umsetzung dieser Spielzettel ist – <strong>in</strong>sbesondere<br />

beim DDV-Spielzettel – re<strong>in</strong>e Fleißarbeit. Da für jede Variante<br />

je e<strong>in</strong> Spielzettel für e<strong>in</strong>en 4er- und e<strong>in</strong>en 5er-Tisch benötigt<br />

wird, bedarf es der Generierung von <strong>in</strong>sgesamt 4 Spielzetteln. Auf<br />

die Codierung soll hier <strong>in</strong> diesem Workshop nicht näher e<strong>in</strong>gegangen<br />

werden; zum e<strong>in</strong>en ist sie zu umfangreich und zum anderen entspricht<br />

dies auch nicht der Intention dieses Workshops, die wesentlichen<br />

Elemente des <strong>Programm</strong>s darzustellen und zu erläutern.<br />

Glücklicherweise muss man auch nicht die <strong>VBA</strong>-Befehle für die vielfältigen<br />

Formatierungen im <strong>E<strong>in</strong></strong>zelnen kennen, da man sich ja für<br />

diese Arbeit der Hilfe des Makrorekorders bedienen kann.<br />

Die Spielzettel könnte man natürlich auch auf e<strong>in</strong>fache Weise über<br />

das Internet beziehen und es ließe sich dadurch e<strong>in</strong>e Menge Arbeit<br />

sparen. Allerd<strong>in</strong>gs wäre man damit nicht so flexibel, denn<br />

a) zum e<strong>in</strong>en ist die Anzahl der Runden pro Durchgang bei e<strong>in</strong>er<br />

Spielzettel-Vorlage festgelegt - i.A. auf vier. Im <strong>Programm</strong> jedoch<br />

ist die Anzahl der Runden variierbar; wobei natürlich bei e<strong>in</strong>er<br />

Rundenanzahl von beispielsweise zehn die Darstellung auf e<strong>in</strong>e<br />

DIN-A4-Seite relativ stark komprimiert wird (s. Abbildung Seite<br />

47), aber immerh<strong>in</strong> für den praktischen <strong>E<strong>in</strong></strong>satz noch brauchbar<br />

ist. Dass allerd<strong>in</strong>gs bei e<strong>in</strong>em Turnier so viel Runden gespielt<br />

werden, ist auch wohl eher die große Ausnahme.<br />

b) zum zweiten werden bei dem <strong>Programm</strong> die Namen der Spieler<br />

bereits e<strong>in</strong>getragen. Dies hat neben der besseren Lesbarkeit den<br />

Vorteil, dass die Punkte der Spielzettel der e<strong>in</strong>zelnen Spieler <strong>in</strong><br />

der Reihenfolge von l<strong>in</strong>ks nach rechts auf dem Spielzettel der<br />

Reihenfolge im <strong>Programm</strong> im Durchgangs-Tabellenblatt von<br />

oben nach unten entsprechen. Bei Abgabe der Spielzettel kann<br />

die Übernahme der Punkte vom Spielzettel <strong>in</strong> das <strong>Programm</strong> somit<br />

schneller erfolgen, als wenn die Spieler die <strong>E<strong>in</strong></strong>tragungen<br />

selbst vorgenommen hätten, da dann die korrekte Reihenfolge<br />

nicht mehr gewährleistet ist.<br />

c) zum dritten ist man bzgl. der Ausgestaltung der Spielzettel bei<br />

der selbst programmierten Variante flexibler als bei e<strong>in</strong>er Vorlage.<br />

So pflege ich z.B. bei dem bereits im Vorwort erwähnten Turnier,<br />

welches immer zum Jahresende stattf<strong>in</strong>det, noch zur Auflockerung<br />

e<strong>in</strong> oder zwei Grafiken mit den besten Wünschen für das<br />

neue Jahr im Fußbereich der Spielzettel e<strong>in</strong>.<br />

H<strong>in</strong>weis 18<br />

<strong>E<strong>in</strong></strong> Nachteil bei der Generierung<br />

des Quellcodes per<br />

Makrorecorder ist allerd<strong>in</strong>gs<br />

die Tatsache, dass immer alle<br />

Optionen e<strong>in</strong>es FormatierungsDialogs<br />

übernommen<br />

werden, auch wenn diese<br />

Optionen zum größten Teil<br />

gar nicht genutzt werden.<br />

Viele überflüssige Informationen<br />

machen den Quellcode<br />

dadurch schnell unübersichtlich.<br />

48


3 Ausblick/Nachbetrachtung<br />

Die mit dem Schreiben dieses Dokumentes zwangsläufige verbundene<br />

Beschäftigung mit dem <strong>Programm</strong> hat mir gezeigt, dass an e<strong>in</strong>igen Stellen<br />

des Quelltextes doch noch e<strong>in</strong>iges verbesserungsbedürftig ist. Zwar<br />

läuft das <strong>Programm</strong> fehlerfrei, es s<strong>in</strong>d me<strong>in</strong>es Wissens ke<strong>in</strong>e logischen<br />

Fehler vorhanden. Es ist allerd<strong>in</strong>gs so, dass man – so war es jedenfalls<br />

bei mir – als Entwickler vielfach zufrieden ist, wenn das <strong>Programm</strong> genau<br />

das tut, was es soll. Dass man evtl. dabei e<strong>in</strong> wenig "geschlampt"<br />

hat, kümmert dann gar nicht mehr. Man hat ja, was man wollte.<br />

Um diesbezüglich Abhilfe zu schaffen, habe ich mir vorgenommen, das<br />

komplette <strong>Programm</strong> e<strong>in</strong>mal (wann auch immer das se<strong>in</strong> wird) e<strong>in</strong>er<br />

gründlichen "Re<strong>in</strong>igung" zu unterziehen, <strong>in</strong>sbesondere h<strong>in</strong>sichtlich Datendeklaration,<br />

logischer (Um)Strukturierung sowie Kommentierung.<br />

3.1 Neuralgische Punkte<br />

An dieser Stelle möchte ich auf e<strong>in</strong>ige Punkte für den Anwender h<strong>in</strong>weisen,<br />

die man bei der Bedienung des <strong>Programm</strong>s beachten sollte.<br />

a) Korrekte Erfassung der Teilnehmer<br />

Wie bereits <strong>in</strong> Kapitel 2.2 Die Gäste kommen sowie Kapitel 2.4<br />

Ereignisse <strong>in</strong> VBE) vorgestellt sowie aus Abbildung 3 (Seite 15) ersichtlich,<br />

werden die Teilnehmer an dem Turnier dadurch festgelegt,<br />

dass <strong>in</strong> Spalte "B" oder "C" neben dem Namen e<strong>in</strong> Rechtsklick<br />

oder e<strong>in</strong> Doppelklick ausgeführt wird. Hierbei bedarf es e<strong>in</strong>er<br />

besonderen Achtsamkeit, damit man nicht versehentlich<br />

durch das Klicken <strong>in</strong> e<strong>in</strong>er falschen Zeile e<strong>in</strong>en anderen Spieler <strong>in</strong><br />

die Liste aufnimmt. Wird der Fehler rechtzeitig vor Beg<strong>in</strong>n der<br />

Auslosung bemerkt, so ist das ke<strong>in</strong> Problem: der Zug lässt sich<br />

durch e<strong>in</strong>en erneuten Rechts- oder Doppelklick wieder rückgängig<br />

machen (s. 2.4 Ereignisse <strong>in</strong> <strong>VBA</strong>). Wurde aber bereits ausgelost<br />

und die Spieler begeben sich zu ihren Tischen, gilt es zu<br />

überlegen, e<strong>in</strong>e Korrektur des betreffenden Teilnehmers vorzunehmen<br />

und erneut auszulosen oder – alternativ - den Spieler<br />

unter dem nun falschen Namen spielen zu lassen.<br />

Noch ärgerlicher wird die ganze Geschichte, wenn e<strong>in</strong> Spieler gar<br />

nicht <strong>in</strong> die Liste aufgenommen wurde. Dann hilft nur noch:<br />

Nachträglich Spieler <strong>in</strong> die Teilnehmerliste aufnehmen und erneut<br />

auslosen.<br />

Ist man sich nicht sicher, ob alle Spieler korrekt e<strong>in</strong>getragen s<strong>in</strong>d,<br />

kann man direkt nach der Auslosung und dem Ausdruck der Liste,<br />

noch bevor die ersten beg<strong>in</strong>nen, sich an die Tische zu setzen,<br />

49


die Teilnehmer bitten, zu überprüfen, ob sie <strong>in</strong> der Liste aufgeführt<br />

s<strong>in</strong>d.<br />

Derartige Anwendungsfehler lassen sich me<strong>in</strong>er Me<strong>in</strong>ung nach<br />

auch durch <strong>Programm</strong>änderungen nicht gänzlich vermeiden.<br />

Möchte man hier vorbeugende Maßnahmen treffen, sehe ich die<br />

e<strong>in</strong>zige Möglichkeit, programmtechnische Vorkehrungen zu treffen<br />

dar<strong>in</strong>, dass man nach dem Rechts- oder Doppelklick für den<br />

Anwender e<strong>in</strong> Meldungsfenster (Funktion MsgBox) aufmacht<br />

mit dem H<strong>in</strong>weis: "Möchten Sie wirklich, dass ... <strong>in</strong> die Liste aufgenommen<br />

wird?"<br />

b) Datensicherung<br />

Um möglichen Datenverlusten vorzubeugen, sollte immer wieder<br />

zwischendurch gesichert werden. Man ist ja nie 100%-ig vor<br />

Stromausfällen, System- oder <strong>Programm</strong>hängern (letzteres hoffentlich<br />

nicht) geschützt.<br />

Automatische Sicherungen lassen sich natürlich auch programmtechnisch<br />

umsetzen (ActiveWorkbook.SaveAs Filename :=<br />

"Name der Datei"), z.B. direkt nach der Auslosung. Zudem könnte<br />

man dem Anwender e<strong>in</strong>en Button zur Verfügung stellen zur<br />

zwischenzeitlichen Sicherung, evtl. auch mit e<strong>in</strong>er fortlaufenden<br />

Sicherungsnummer im Date<strong>in</strong>amen. Dies wäre z.B. s<strong>in</strong>nvoll <strong>in</strong><br />

den Durchgangstabellen.<br />

c) Drucker versagt den Dienst<br />

Dass e<strong>in</strong> Drucker streikt, die T<strong>in</strong>te oder der Toner zur Neige geht,<br />

kommt leider <strong>in</strong> der Praxis immer wieder vor. Um dem vorzubeugen,<br />

ist es e<strong>in</strong>e Überlegung wert, sich vorab über e<strong>in</strong>en Ersatzdrucker<br />

mit dem bereits e<strong>in</strong>gespielten passenden Druckertreiber<br />

Gedanken zu machen.<br />

Hat man ke<strong>in</strong>en Ersatzdrucker parat, und sollte es beim Ausdruck<br />

der Spielzettel Probleme geben, ist das nicht ganz so tragisch;<br />

entweder hat man vorgesorgt und passende Vordrucke bereits<br />

mitgebracht oder aber die Teilnehmer fertigen die Spielzettel<br />

selber an ihren Tischen an.<br />

Richtig ärgerlich ist eigentlich nur der Fall, dass sich die Liste aus<br />

dem Tabellenblatt Liste nicht ausdrucken lässt.<br />

<strong>Programm</strong>technisch lassen sich diesbezüglich ke<strong>in</strong>e geeigneten<br />

vorbeugenden Maßnahmen treffen.<br />

50


3.2 Mögliche Weiterentwicklungen<br />

Neben e<strong>in</strong>er "Grundre<strong>in</strong>igung" des Quellcodes s<strong>in</strong>d natürlich auch noch<br />

Weiterentwicklungen des <strong>Programm</strong>s e<strong>in</strong>e zusätzliche Option. Folgende<br />

Varianten wären denkbar:<br />

‣ Das vorliegende <strong>Programm</strong> sieht lediglich e<strong>in</strong>e <strong>E<strong>in</strong></strong>zelwertung der<br />

Spieler vor. Nicht nur bei Vere<strong>in</strong>sturnieren, sondern auch im privaten<br />

Umfeld s<strong>in</strong>d vielfach auch Mannschaftswertungen von<br />

Interesse. Offen gestanden, habe ich mir diesbezüglich über e<strong>in</strong>en<br />

geeigneten Ansatz bisher noch ke<strong>in</strong>e Gedanken gemacht,<br />

würde aber diesen Gesichtspunkt bei e<strong>in</strong>er möglichen Erweiterung<br />

<strong>in</strong> der Prioritätenliste ganz nach oben setzen.<br />

‣ Die Abbildungen <strong>in</strong> diesem Skript lassen erkennen/erahnen, dass<br />

an der <strong>Excel</strong>-Oberfläche ke<strong>in</strong>e Veränderungen vorgenommen<br />

worden s<strong>in</strong>d. Der Funktion an sich tut das natürlich ke<strong>in</strong>en Abbruch,<br />

bzgl. der Optik ist es allerd<strong>in</strong>gs e<strong>in</strong>e Frage des Geschmacks,<br />

ob man das möchte. <strong>VBA</strong> stellt zum<strong>in</strong>dest die Mittel<br />

dafür bereit, die <strong>Excel</strong>-Oberfläche auszublenden, so dass ke<strong>in</strong>e<br />

Statusleiste, ke<strong>in</strong>e Menüleiste, und auch sonst ke<strong>in</strong>e Reste e<strong>in</strong>er<br />

<strong>Excel</strong>-Oberfläche mehr sichtbar s<strong>in</strong>d.<br />

‣ Vom Doppelkopf bis zum Skat ist der Weg zwar relativ weit, nicht<br />

ganz so weit entfernt ist jedoch die Entwicklung e<strong>in</strong>es Skatturnier-<strong>Programm</strong>s,<br />

wenn man die Vorlage für e<strong>in</strong> Doppelkopfturnier<br />

bereits besitzt.<br />

‣ Sehr aufwendig h<strong>in</strong>gegen stelle ich mir die Entwicklung des<br />

<strong>Programm</strong>s <strong>in</strong> e<strong>in</strong>er anderen <strong>Programm</strong>iersprache wie z.B. Java<br />

vor. Alle Objekte mit ihren Eigenschaften und Methoden, die <strong>in</strong><br />

<strong>Excel</strong>/<strong>VBA</strong> bereits vorhanden s<strong>in</strong>d und die der Entwickler nur<br />

noch je nach Bedarf e<strong>in</strong>setzen muss, müssten komplett neu konzipiert<br />

und def<strong>in</strong>iert werden.<br />

51


4 Literatur- und Quellenverzeichnis<br />

Literatur<br />

(1) Bernd Held: <strong>Excel</strong>-<strong>VBA</strong> <strong>Programm</strong>ierung, Markt+Technik Verlag,<br />

ISBN-10: 3827261856<br />

Onl<strong>in</strong>e-Quellen<br />

(1) www.merkwerk.de/files/exvba.pdf<br />

Andreas Kle<strong>in</strong>, Stefanie Friedrich: <strong>Excel</strong> 2003, <strong>Programm</strong>ierung<br />

mit Visual Basic<br />

(2) www.fernuni-hagen.de/imperia/md/content/zmi 2010/b012.pdf<br />

Johannes Gogolok: <strong>VBA</strong>-<strong>Programm</strong>ierung mit <strong>Excel</strong>, Grundlagen<br />

52

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!