Zusammenfassung
Legen Sie mit wenigen Codezeilen Beispieldaten für Ihre Datenbanken in der Entwicklungsphase an.
Techniken
Zufallsfunktionen, Rnd, Int, zufällige Auswahl von Datensätzen
Voraussetzungen
Access 97 oder höher
Beispieldateien
Testdaten97.mdb, Testdaten00.mdb
Beispieldaten generieren
André Minhorst, Duisburg
Eine der leidigsten Aufgaben bei der Datenbankentwicklung ist das Eintippen von Testdaten. Es ist ja ganz schön, zwischendurch mal eine etwas weniger anspruchsvolle Tätigkeit auszuüben, aber diese Zeit könnte man sicher sinnvoller nutzen, indem man einen Kaffee trinkt oder ein wenig im Internet surft. Ein wenig Vorarbeit ist natürlich notwendig, aber dann sind die Beispieldaten im Nu generiert.
Beispieldaten
Mancher Entwickler ist sich seiner selbst so sicher, dass er Anwendungen locker ohne Testdaten entwickelt. Wenn die Anwendung in Betrieb geht, ist der Nachholbedarf dann allerdings groß:
Fehler treten auf, die Daten passen nicht in die Steuerelemente und die Berichte zeigen nur die Hälfte der gewünschten Informationen an.
Mit ein wenig Aufwand lässt sich eine Menge Ärger vermeiden: Wenn Testdaten vorhanden sind, lassen sich viele Funktionen zuverlässig prüfen und die Steuerelemente in Formularen und Berichten der gewünschten Größe anpassen.
Die optimalen Beispieldaten kommen natürlich vom Auftraggeber selbst: Wenn eine zu entwickelnde Anwendung dem Verwalten bestehender Daten dienen soll, liegt nichts näher, diese nach dem Entwurf des Datenmodells direkt in die passenden Tabellen zu integrieren. Diesen Schritt müssen Sie früher oder später vermutlich ohnehin gehen, also warum nicht sofort? Die Beispieldaten kommen somit "frei Haus".
Es gibt allerdings auch Fälle, in denen die Beispieldaten nicht auf der Straße liegen: Wenn Sie etwa ein Produkt entwickeln möchten, dessen Abnehmer noch nicht feststehen oder für das es einfach noch keine bestehenden Daten gibt, müssen Sie die Tabellen selbst füllen.
Grundlage für das Erzeugen von Beispieldaten
Es gibt einige Assistenten für Access, die Tabellen relativ "blind" mit Beispieldaten füllen, die dem jeweiligen Datentyp entsprechen. Das klappt für einige Fälle, aber sobald es an verknüpfte Tabellen geht, hört der Spaß meist auf.
Außerdem macht es doch wesentlich mehr Laune, beispielsweise eine Adressenliste zu testen, die richtige Namen enthält und keine per Zufall generierten Zeichenketten wie kUDvkxKskKNN. "Richtige" Beispieldaten machen auch einen wesentlich besseren Eindruck, wenn es um die Vorführung oder um eine Demoversion der jeweiligen Anwendung geht.
Woher nehmen, wenn nicht stehlen?
Um etwa eine Adresstabelle mit einigen hundert oder tausend Datensätzen zu füllen, benötigen Sie natürlich einige Basisdaten - aber nicht unbedingt so viele, wie Sie Datensätze erzeugen möchten. Mit 20 bis 30 Vornamen, Nachnamen, Orten und Straßen lässt sich schon eine Menge eindeutige Kombinationen erzeugen. Die müssen Sie natürlich irgendwo her nehmen - also greifen Sie sich einfach das nächste Telefonbuch und "hacken" ein paar Daten in eine Basistabelle. Denn merke: Nichts ist monotoner, als Beispieldaten einzugeben - außer, sich die Beispieldaten auch noch ausdenken zu müssen ...
Art der Daten
Welche Daten benötigt man überhaupt, um eine Datenbank mit Beispieldaten zu füllen? In der Regel sollten Daten für die folgenden Felder ausreichen:
Vorname
Nachname
Anrede
Firma
Straße und Hausnummer
PLZ
Ort
Land
Telefon (Telefax, Mobil)
E-Mail
Internet
Datumsangaben
Zahlenwerte
Verknüpfungsfelder
Sonstige Felder wie Projektnamen, Fahrzeugnamen ...
Daten generieren
Die Daten für die oben genannten Felder gewinnen Sie auf unterschiedliche Arten. Für die ersten acht Felder halten Tabellen mit bestehenden Daten als Quelle her.
Die Übrigen können mit einfachen Funktionen erzeugt werden, die Sie ebenfalls wie die Funktion zum zufälligen Auswählen der bestehenden Daten im Folgenden kennen lernen.
Datengenerierung per VBA
Zum Anlegen von Datensätzen mit Beispieldaten müssen Sie nun irgendwie dafür sorgen, dass die Daten - woher auch immer - in der Zieltabelle landen. Dazu verwendet man am Besten eine passende SQL-Anweisung, die per VBA mit den entsprechenden Daten bestückt wird. Für die Kontakttabelle aus Abb. 1 könnte die Anweisung wie folgt aussehen:
db.Execute "INSERT INTO tblPersonen
(Anrede, Vorname, Nachname, Firma,
Strasse, PLZ, Ort, Bundesland, Telefon,
Telefax, EMail) VALUES('" & strAnrede &
"', '" & strVorname & "', '" &
strNachname & "', '" & strFirma & "', '"
& strStrasse & " " & intHausnummer & "',
'" & strPLZ & "', '" & strOrt & "', '" &
strBundesland & "', '" & strVorwahl & "/"
& strTelefon & "', '" & strVorwahl & "/"
& strTelefax & "', '" & strEMail & "')"
Bleibt nur noch die kleine Aufgabe, die Variablen für die einzufügenden Daten mit den entsprechenden Werten zu füllen.
Die dazu notwendige Funktionalität soll der Übersicht halber auf eine öffentliche Routine und eine Klasse aufgeteilt werden, deren Methoden per Zufall die einzelnen Daten ermitteln.
Quellcode 1: Routine zum Anlegen von Beispieldaten in einer Personen-Tabelle
Public Sub TabelleFuellen(lngAnzahlDatensaetze As Long)
Dim db As DAO.Database
Dim i As Integer
Dim objBeispieldaten As clsBeispieldaten
Dim strAnrede As String
Dim strVorname As String
Dim strNachname As String
... weitere Deklarationen, siehe Beispieldatenbank
'Klasse für die Ermittlung der Zufallsdaten instanzieren
Set objBeispieldaten = New clsBeispieldaten
Set db = CurrentDb
'Gewünschte Anzahl Datensätze durchlaufen
For i = 1 To lngAnzahlDatensaetze
'Beispieldaten ermitteln
With objBeispieldaten
.GetVorname strVorname, strGeschlecht, strAnrede
.GetNachname strNachname
.GetNachname strNameFirma
.GetFirma strNameFirma, strFirma
.GetStrasse strStrasse
.GetHausnummer 1, 100, intHausnummer
.GetOrt strPLZ, strOrt, strBundesland, strVorwahl
.GetTelefon 6, 8, strTelefon
.GetTelefon 6, 8, strTelefax
.GetEMail strVorname, strNachname, strEMail
End With
'Datensatz schreiben
db.Execute "INSERT INTO tblPersonen(Anrede, Vorname, Nachname, Firma, Strasse, PLZ, " _ & "Ort, Bundesland, Telefon, Telefax, EMail) VALUES('" & strAnrede & "', '" _ & strVorname & "', '" & strNachname & "', '" & strFirma & "', '" & strStrasse & " " _ & intHausnummer & "', '" & strPLZ & "', '" & strOrt & "', '" & strBundesland _ & "', '" & strVorwahl & "/" & strTelefon & "', '" & strVorwahl & "/" & strTelefax _ & "', '" & strEMail & "')"
Next i
Set db = Nothing
End Sub

Abb. 1: Diese Tabelle soll mit Beispieldaten gefüllt werden.
Die Routine aus Quellcode 1 deklariert und instanziert zunächst die Klasse mit den Methoden zum Ermitteln der Beispieldaten und die Variablen für die per Zufall ermittelten Daten. Dann durchläuft die Routine eine Schleife und dabei die einzelnen Methoden zur Ermittlung der Daten. Diese Daten schreibt sie schließlich in einen neuen Datensatz der Personen-Tabelle.
Die Klasse clsBeispieldaten
Die Klasse clsBeispieldaten enthält die Methoden zum Ermitteln von Daten nach dem Zufallsprinzip. Dabei werden verschiedene Techniken verwendet, die nachfolgend vorgestellt werden.
Die Funktionen zur Generierung der Daten teilen sich in folgende Typen auf:
Generieren aus bestehenden Tabellen
Generieren von Telefonnummern
Generieren von E-Mail und Internetadressen aus Namen
Erzeugen von Datumsangaben
Erzeugen von Zahlenwerten in bestimmten Bereichen
Ermitteln von Werten für Verknüpfungsfelder aus fremden Tabellen
Zufallszahlen mit der Rnd-Funktion
In fast allen nachfolgend vorgestellten Funktionen spielt die Rnd-Funktion eine Rolle. Diese Funktion ermittelt einen Zufallswert größer oder gleich 0 und kleiner 1. Um Werte aus einem bestimmten Bereich zu erhalten - beispielsweise zwischen 1 und 10 - muss man die Funktion entsprechend "einhüllen". Der folgende Ausdruck liefert die passenden Werte:
Int(10 * Rnd() + 1)
Für andere Intervalle legen Sie die Werte für die zwei Variablen Obergrenze und Untergrenze fest und verwenden den folgenden Ausdruck:
Int((Obergrenze - Untergrenze + 1) * Rnd + Untergrenze)
Die nachfolgend verwendeten Ausdrücke verwenden dabei jeweils die berechneten Werte für den Ausdruck Obergrenze - Untergrenze + 1.
Daten aus bestehenden Tabellen generieren
Die Beispieldatenbank enthält folgende Tabellen mit Daten, die als Grundlage für Testdaten dienen können:
tblVornamen (Vornamen und Geschlecht)
tblNachnamen (Nachnamen)
tblStrassen (Straßennamen)
tblOrte (Ort, PLZ, Vorwahl, Bundesland)
Nachnamen ermitteln
Daten aus Tabellen mit nur einem Feld wie tblNachnamen und tblStrassen werden mit einer Methode wie aus Quellcode 2 ermittelt.
Dazu soll zufällig einer der Datensätze der Tabelle ermittelt werden. Dies geht am einfachsten, wenn Sie diese Aufgabe an eine Abfrage weitergeben. Diese Abfrage ist wie in Abb. 2 aufgebaut.
Wichtig ist hier, dass die Abfrage aufsteigend nach dem Feld Zufall sortiert ist. Dieses Feld enthält eine in Abhängigkeit vom Autowert des Datensatzes gebildete Zufallszahl. Da diese immer einen anderen Wert hat, ändert sich auch die Reihenfolge. Damit die Abfrage nur einen Datensatz zurückgibt, stellen Sie noch die Eigenschaft Spitzenwerte der Abfrage auf 1 ein.

Abb. 2: Abfrage zur zufälligen Ermittlung eines Datensatzes
Die Methode GetNachname aus Quellcode 2 hat nur den zu ermittelnden Nachnamen als Parameter. Dieser muss in der aufrufenden Routine zuvor deklariert werden und kann nach dem Aufruf der Methode ausgewertet werden.
Diese Variante der Übergabe von Rückgabewerten ist in diesem Zusammenhang eher ungewöhnlich - normalerweise könnte man diesen auch als Funktionswert zurückgeben. Warum das Ergebnis dennoch als Parameter zurückgegeben wird, erfahren Sie weiter unten.
Genau wie den Nachnamen ermitteln Sie auch eine Straße - nur dass hier die Methode GetStrasse zum Einsatz kommt.
Ort, PLZ, Vorwahl und Bundesland ermitteln
Etwas aufwändiger ist das Ermitteln zusammenhängender Daten wie Postleitzahl, Ort, Bundesland und Vorwahl oder Vorname, Anrede und Geschlecht.
Zwar könnte man auch alle Informationen einzeln ermitteln, da es sich ja immerhin nur um Beispieldaten handelt. Ein wenig Freude am Detail soll jedoch auch dabei sein.
Daher sind zusammenpassende Daten bereits in den beiden Tabellen tblOrte und tblVornamen enthalten (s. Abb. 3).
Um diese Daten mit einer Methode ähnlich der zum Finden von Nachnamen per Zufall zu ermitteln, verwenden Sie wiederum eine Abfrage, die zufällig einen Datensatz der Tabelle tblOrte auswählt (s. Abb. 4).

Abb. 3: Weitere Tabellen mit Beispieldaten
Quellcode 2: Code zum Ermitteln eines Nachnamens nach dem Zufallsprinzip
Public Sub GetNachname(strNachname As String)
Set rst = db.OpenRecordset("qryNachnameZufall", _ dbOpenDynaset)
strNachname = rst!Nachname
rst.Close
Set rst = Nothing
End Sub

Abb. 4: Abfrage zum Ermitteln von PLZ, Ort, Vorwahl und Bundesland
Wenn Sie nicht gerade zuerst die ID eines Datensatzes ermitteln, diese zwischenspeichern und dann nacheinander die gewünschten Informationen auf Basis der gespeicherten ID ermitteln möchten, können Sie dies auch in einem Rutsch beziehungsweise innerhalb einer Methode erledigen. Um mehrere Rückgabewerte gleichzeitig von einer Routine zu erhalten, verwendet man entweder ein Array oder einen benutzerdefinierten Typ - oder man setzt einfach mehrere Parameter als Rückgabeparameter der Methode ein.
Im vorliegenden Fall kommt letztere Technik zum Einsatz und der Grund, warum auch weiter oben für Nachnamen und Straßen diese Technik verwendet wurde, liegt allein darin, dass alle Methoden die ermittelten Werte auf dem gleichen Wege zurückliefern sollen.
Die Methode GetOrt sieht dementsprechend wie in Quellcode 3 aus. Um die Methode möglichst flexibel zu halten, sind alle Parameter optional - man könnte also gegebenenfalls auch alle Werte getrennt ermitteln.
Quellcode 3:
Public Sub GetOrt(Optional strPLZ As String, Optional strOrt _ As String, Optional strBundesland As String, _ Optional strVorwahl As String)
Set rst = db.OpenRecordset("qryOrteZufall", dbOpenDynaset)
strOrt = rst!Ort
strPLZ = rst!PLZ
strBundesland = rst!Bundesland
strVorwahl = rst!Vorwahl
rst.Close
Set rst = Nothing
End Sub
Quellcode 4: Telefonnummern per Zufall
Public Sub GetTelefon(intMinLaenge As Integer, _ intMaxLaenge As Integer, strTelefon As String)
Dim intDiffLaenge As Integer
Dim i As Integer
Dim strTelefonTemp As String
intDiffLaenge = Int(Rnd() * (intMaxLaenge - intMinLaenge))
For i = 1 To intMinLaenge + intDiffLaenge
strTelefonTemp = strTelefonTemp & Int(Rnd() * 10)
Next i
strTelefon = strTelefonTemp
End Sub
Quellcode 5: Generieren von E-Mail-Adressen aus Vor- und Nachname
Public Sub GetEMail(strVorname As String, _ strNachname As String, strEMail As String)
strEMail = StrConv(strVorname, vbLowerCase) & "@" _ & StrConv(strNachname, vbLowerCase) & ".de"
End Sub
Vorname, Anrede und Geschlecht ermitteln
Das Ermitteln von Vorname, Geschlecht und Anrede erfolgt genau wie bei PLZ und Co.
Ermitteln von Telefonnummern
Telefonnummern sind zu anspruchslos, um extra in einer Tabelle gespeichert und daraus per Zufall ausgelesen zu werden. Statt dessen werden Telefonnummern komplett per Zufallsfunktion generiert (s. Quellcode 4).
Mit zwei Parametern lässt sich das Aussehen der Telefonnummern festlegen: intMinLaenge und intMaxLaenge legen fest, welche Länge die zu ermittelnden Telefonnummern haben dürfen. Wenn eine feste Länge gewünscht ist, stellen Sie einfach beide Werte auf den gleichen Wert ein.
Für Telefonnummern mit verschiedenen Längen ermittelt die Methode ebenfalls per Zufall, welche Länge aus dem angegebenen Bereich verwendet werden soll.
Anschließend ermittelt sie die gewünschte Anzahl Zahlen für die Telefonnummern.
Diese Routine kann natürlich für alle Telefonnummerntypen verwendet werden - also für Telefon, Telefax, Mobil und privat oder geschäftlich.
E-Mail-Adressen zusammensetzen
Sehr unspektakulär ist die Methode zum Erzeugen einer E-Mail: Diese verwendet einfach die mit den Parametern strVorname und strNachname übergebenen Informationen und setzt daraus eine E-Mail-Adresse zusammen - aus Torsten und Müller wird dabei torsten@müller.de.
Die Liebe zum Detail wird hier insofern aufgegeben, als dass Umlaute und sonstige Sonderzeichen wie scharfes s (ß) oder Ähnliche nicht gesondert konvertiert werden. Die StrConv-Funktion sorgt dafür, dass alle Buchstaben innerhalb der E-Mail-Adresse klein geschrieben werden (s. Quellcode 5).
Ermitteln weiterer Daten
Die übrigen für das angegebene Beispiel benötigten Daten wie der Firmenname oder die Hausnummer werden auf ähnliche, einfache Weise ermittelt.
Quellcode 6: Generieren von Datumsangaben
Public Sub GetDatum(datStart As Date, datEnde As Date, _ datDatum As Date)
Dim intDatumsintervall As Integer
intDatumsintervall = DateDiff("d", datStart, datEnde) + 1
datDatum = DateAdd("d", Int(Rnd() * intDatumsintervall), _ datStart)
End Sub
Es gibt allerdings noch einige Datentypen, die für andere als die hier als Beispiel verwendete Personentabelle nützlich sein können - etwa Datumsangaben, Zahlen oder Werte für Verknüpfungsfelder.
Datumsangaben
Die Methode zum zufallsgesteuerten Erzeugen von Datumsangaben erwartet ein Intervall in Form von Start- und Enddatum als Grundlage für die Ermittlung von Datumsangaben.
Aus diesen beiden Werten wird zunächst das Intervall in Tagen berechnet. Auf Basis dieses Intervalls ermittelt die nachfolgende Kombination aus Int- und Rnd-Funktion einen Zufallswert, der irgendwo zwischen 0 und der Intervallgröße liegt, und addiert die entsprechende Anzahl Tage zur unteren Intervallgrenze (s. Quellcode 6).
Datumsintervalle berechnen
Manchmal sollen Tabellen mehrere, voneinander abhängige Daten enthalten - zum Beispiel enthält eine Bestellungen-Tabelle ein Bestelldatum und ein Lieferdatum. Um diese beiden Felder zu füllen, ermitteln Sie ein erstes Datum mit der oben beschriebenen Methode und verwenden dann einen mit der Rnd-Funktion ermittelten Zahlenwert, um ein für diesen Zeitraum übliches Intervall zu berechnen. Diesen Zahlenwert schlagen Sie einfach mit der DateAdd-Funktion auf das erste Datum - das Bestelldatum - auf und erhalten somit das Lieferdatum.
Werte für Verknüpfungsfelder
Wenn Sie Beispieldaten für verknüpfte Tabellen erzeugen müssen, ist das auch kein Problem. Erstellen Sie einfach zunächst die Daten in der Mastertabelle der Beziehung. Bei Projekten und Kunden ist das beispielsweise die Kundentabelle.
Wenn die Kundendaten vorliegen, können Sie auch die mit den Kunden verknüpften Projekte anlegen. Dazu müssen Sie das Fremdschlüsselfeld, das beispielsweise KundeID heißen könnte, mit passenden Daten füllen. Die zur Ermittlung dieser Daten verwendete Technik ist die gleiche wie die zum Ermitteln der zufälligen Datensätze aus den Tabellen mit Vornamen, Nachnamen oder Orten.
Falls Sie keine eigene gespeicherte Abfrage dazu anlegen möchten, können Sie diese auch direkt im VBA-Code angeben.
Zusammenfassung und Ausblick
Das automatisierte Erstellen von Beispieldaten ist sehr hilfreich. Es spart Zeit und wenn man sich ein wenig Mühe gibt, erhält man realitätsnahe Daten, die zum Testen der Anwendung auf die zukünftigen Anforderungen ausreichen. Durch die automatisierte Erstellung der Daten lassen sich per Mausklick tausende von Datensätzen erstellen und die Anwendung unter realistischen Bedingungen testen. Damit können Sie leicht prüfen, ob ein Bericht auch noch auf der vierten Seite wie gewünscht aussieht.
Ein wenig Fantasie ist allerdings gefragt: Zwar finden Sie in der Klasse clsBeispieldaten Methoden für die Ermittlung vieler verschiedener Daten, aber natürlich noch längst nicht für alle. Wenn Sie beispielsweise eine Projekttabelle erzeugen und mit Beispieldaten füllen möchten, denken Sie sich halt ein paar verschiedene Projekttypen aus und greifen dann per Zufall auf diese zu.
Und wenn Sie auch dieses letzte bisschen manuelle Beispieldatenerstellung vermeiden möchten - Ihre vorhandenen Datenbanken liefern sicher ausreichend Stoff als Grundlage für Beispieldaten.
|