Wenn ein potenzieller Kunde Sie um Unterstützung beim Programmieren oder Anpassen einer bestehenden Datenbank bittet, ist es am einfachsten, wenn diese Ihnen die Datenbank zum Analysieren zur Verfügung stellt. Das scheitert aber oft daran, dass der Kunde die Datenbank nicht herausgeben darf, weil die enthaltenen Daten nicht weitergegeben werden dürfen. Oft handelt es sich dabei um Adressdaten. Dieser Beitrag zeigt, wie Sie dem Kunden das Werkzeug bereitstellen, die enthaltenen Daten zu anonymisieren.
Warum anonymisieren
Aber warum sollte man sich überhaupt die Mühe machen, die Daten zu anonymisieren Es wäre doch viel einfacher, einfach die Datenbank zu kopieren und die enthaltenen Daten vor der Weitergabe zu löschen. Klar, das geht viel schneller: Allerdings enthält die Datenbank dann auch keine Daten und der Entwickler – in diesem Fall Sie – oder der Kunde müssen manuell einige Testdatensätze eingeben. Und manchmal sollen ja gerade Performance-Probleme behoben werden. In diesem Fall ist es natürlich komplett abwegig, eine leere Datenbank an den Entwickler zu übergeben.
Beides sind gute Anlässe, ein Tool zu programmieren, das den Kunden dabei unterstützt, die Datenbank in eine Form zu bringen, die keine nachvollziehbaren personenbezogenen Daten mehr enthält.
Konkreter Anlass
Im konkreten Fall geht es viel weniger um die oben beschriebene Konstellation, als um die änderung der Personendaten zwecks Veröffentlichung der programmierten Lösung samt Beispieldaten zum Ausprobieren der Anwendung.
Der erste Vorsitzende eines befreundeten Sportvereins ist nämlich mit einer Excel-Datei mit Mitgliedsdaten an mich herangetreten und hat mich gebeten, einmal eine vernünftige Mitgliederverwaltung zu programmieren, mit der die Daten nicht mehr in einer einzigen Excel-Tabelle verwaltet werden müssen, sondern die es auch noch ermöglicht, zusätzliche Auswertungen zu produzieren.
Wenn ich Ihnen als Leser von Access im Unternehmen meine Umsetzung dieser Lösung darlegen möchte, muss ich also die Personendaten in dieser Excel-Tabelle vorher anonymisieren. Die Lösung mit der Umwandlung der Mitgliedsdatei in eine richtige Anwendung finden Sie übrigens unter dem Titel Vereinsverwaltung: Von Excel zum Datenmodell (www.access-im-unternehmen.de/1106) in diesem Heft.
Konzept für das Tool
Wie aber gestalten wir nun das Tool, mit dem wir die Personendaten anonymisieren wollen Normalerweise würde ich es als Add-In programmieren. Allerdings müsste der Kunde dann erst das Add-In installieren, was diesen möglicherweise überfordern könnte. Also gehen wir diesmal einen anderen Weg und programmieren eine eigene Access-Lösung, mit welcher der Kunde dann die betroffene Access-Anwendung auswählen soll. Im Formular dieser Lösung sollen dann die Tabellen der Ausgangsanwendung zur Auswahl angeboten werden. Für die Felder der gewählten Tabelle soll der Benutzer dann angeben, mit welchen Daten diese gefüllt werden sollen – also mit Vornamen, Nachnamen, Straßen, PLZ und Ort, Land und so weiter. Dann soll er per Mausklick den Anonymisierungsvorgang starten können, welcher dann eine Kopie der Datenbank erstellt und die enthaltenen Daten ändert.
Das Tool erstellen
Als Tool legen wir also eine ganz normale Access-Datenbank an. Diese sollte beim öffnen möglichst gleich die enthaltene Funktion offenbaren, damit der Benutzer sich gleich zurechtfindet. In diesem Fall wäre dies das öffnen des Formulars, welches die Funktionen zum Auswählen der zu kopierenden und zu manipulierenden Datenbank enthält.
Das Formular soll keine Datensätze anzeigen, also stellen wir die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen, Trennlinien und Bildlaufleisten auf Nein ein.
Fügen Sie im oberen Bereich zwei Textfelder namens txtQuelldatei und txtZieldatei ein sowie zwei Schaltflächen namens cmdDateiauswahl und cmdZieldateiFestlegen. Diese ordnen Sie wie in Bild 1 an.
Bild 1: Steuer-elemente zum Auswählen von Quell- und Zieldatei
Für die Beim Klicken-Ereigniseigenschaft hinterlegen wir jeweils eine entsprechende Ereignisprozedur. Ein Klick auf die Schaltfläche cmdDateiauswahl löst die Prozedur cmdDateiauswahl_Click aus Listing 1 aus. Diese verwendet die Funktion Openfilename, die Sie im Modul mdlDateidialoge finden. Sie übergibt der Funktion den aktuellen Datenbankpfad als Parameter und stellt die Access-Dateiendungen .mdb und .accdb als Filter ein.
Private Sub cmdDateiauswahl_Click() Dim strQuelldatei As String strQuelldatei = Openfilename(CurrentProject.Path, "Quelldatei auswählen", "Access-DB (*.mdb;*.accdb)|Alle Dateien (*.*)") Me!txtQuelldatei = strQuelldatei Me!txtZieldatei = VerzeichnisAusPfad(strQuelldatei) & "\" & ZieldateiAusPfad(strQuelldatei) End Sub Private Sub cmdZieldateiFestlegen_Click() Dim strZieldatei As String Dim strQuelldatei As String Dim strZielverzeichnis As String strQuelldatei = Me!txtQuelldatei If Len(Dir(strQuelldatei, vbDirectory)) > 0 Then strZieldatei = ZieldateiAusPfad(strQuelldatei) strZielverzeichnis = VerzeichnisAusPfad(strQuelldatei) End If strZieldatei = GetSaveFile(strZielverzeichnis, strZieldatei, "Access-DB (*.mdb;*.accdb)|Alle Dateien (*.*)", _ "Zieldatei auswählen") Me!txtZieldatei = strZieldatei End Sub Private Function VerzeichnisAusPfad(strPfad As String) As String Dim strVerzeichnis As String strVerzeichnis = Left(strPfad, InStrRev(strPfad, "\") - 1) VerzeichnisAusPfad = strVerzeichnis End Function Private Function ZieldateiAusPfad(strPfad As String) As String Dim strZieldatei As String Dim intPunkt As String strZieldatei = Mid(strPfad, InStrRev(strPfad, "\") + 1) intPunkt = InStrRev(strZieldatei, ".") strZieldatei = Left(strZieldatei, intPunkt - 1) & "_Anonymisiert" & Mid(strZieldatei, intPunkt) ZieldateiAusPfad = strZieldatei End Function
Listing 1: Prozeduren zum Auswählen von Quell- und Zieldatei
Das Ergebnis dieses Dialogs speichert sie in der Variablen, deren Inhalt direkt an das Textfeld txtQuelldatei weitergegeben wird. Außerdem ruft die Prozedur zwei weitere Hilfsfunktionen namens VerzeichnisAusPfad und ZieldateiAusPfad auf, welche sich ebenfalls im Klassenmodul des Formulars befinden und im Listing abgebildet sind.
VerzeichnisAusPfad erwartet einen kompletten Pfad, also beispielsweise die Angabe aus Bild 2 im oberen Textfeld. Es ermittelt die Position des hintersten Backslash und liefert die Zeichenkette bis zu dieser Position minus eins, damit der Backslash wegfällt.
Bild 2: Auswählen von Quell- und Zieldatei
Die Funktion ZieldateiAusPfad arbeitet etwas spezifischer und liefert nicht nur einfach den Dateinamen des hineingegebenen Pfades, sondern ergänzt diesen so, dass der Dateiname gut als die anonymisierte Version zu erkennen ist. Die Funktion ermittelt ebenfalls zunächst in einer Anweisung den Teil des mit strPfad übergebenen Pfades, der sich hinter dem letzten Backslash in strPfad befindet. Das Verzeichnis wird also vorn abgeschnitten. Dann ermittelt sie die Position des Punktes, also des Zeichens, das sich zwischen dem eigentlichen Dateinamen und der Dateiendung befindet. Der in der Variablen strZieldatei zwischengespeicherte Ausdruck besteht dann aus dem Teil vor dem Punkt, dem Ausdruck _anonymisiert. und der Dateiendung. Dieses automatische Füllen des Feldes txtZieldatei ist eine Möglichkeit, dem Benutzer weitere Schritte abzunehmen, denn er braucht in den meisten Fällen nicht noch die Zieldatei auszuwählen.
Möchte er dies dennoch tun, hat er natürlich die Möglichkeit dazu. Er braucht dann nur auf die Schaltfläche cmdZieldateiFestlegen zu klicken, welche die Prozedur cmdZieldateiFestlegen_Click auslöst. Diese liest den Wert des Feldes txtQuelldatei in die Variable strQuelldatei ein und prüft, ob dieser Ausdruck ein gültiges Verzeichnis enthält.
In diesem Fall ermittelt die Prozedur über die Funktion ZieldateiAusPfad einen Vorschlag für den Namen der Zieldatei und speichert diesen in der Variablen strZieldatei. Das Zielverzeichnis wird über die Funktion VerzeichnisAusPfad ermittelt und landet in der Variablen strZielverzeichnis.
Danach ruft die Prozedur über die Funktion GetSaveFile einen Dialog auf, über den der Benutzer die Zieldatei festlegen soll. Hier wird auch klar, warum wir zuvor Zielverzeichnis und Zieldatei in zwei verschiedene Variablen geschrieben haben: Beim Aufruf dieser Funktion wird das Zielverzeichnis als beim öffnen anzuzeigendes Verzeichnis gewählt und der Name der Zieldatei wird unten im Dialog voreingestellt (s. Bild 3). Schließlich landet die hier ausgewählte Datei im Textfeld txtZieldatei.
Bild 3: Auswählen der Zieldatei
Datei kopieren
Wir haben ja avisiert, dass wir nicht in der vom Benutzer ausgewählten Datei herumspielen – es kann immerhin sein, dass der Benutzer zuvor keine Kopie anlegt und direkt eine Originaldatei zum anonymisieren auswählt. Also legen wir auf jeden Fall zuvor eine Kopie der Datenbank an, wozu wir die zuvor ermittelten Daten zur Quell- und Zieldatei nutzen.
Wir legen direkt einmal eine Schaltfläche namens cmdAnonymisieren im Formular an, auch wenn wir noch keine Steuer-elemente zum Einstellen der Anonymisierungsdetails hinzugefügt habe und diese Funktionalität noch fehlt. Allerdings ist das Kopieren der Datei der Grundstein, daher beginnen wir damit (s. Bild 4). Diese Schaltfläche löst nun die folgende Prozedur aus, welche wiederum eine Funktion zum Kopieren der Quelldatenbank in die Zieldatenbank aufruft. Sollte diese Funktion namens DateiKopieren den Wert True zurückliefern, soll der Inhalt der If…Then-Bedingung ausgeführt werden:
Bild 4: Schaltfläche zum Start des Vorgangs
Private Sub cmdAnonymisieren_Click() If DateiKopieren(Me!txtQuelldatei, Me!txtZieldatei) Then ''''...anonymisieren End If End Sub
Funktion zum Kopieren der Datenbank
Die dadurch aufgerufene Funktion DateiKopieren finden sie in Listing 2. Die Funktion erwartet den Pfad der Quell- und der Zieldatenbank als Parameter. Das Kopieren gelingt nicht, wenn die Quelldatei geöffnet ist. Ob dies der Fall ist, ermitteln wir, indem wir nach einer Datei suchen, deren Dateiname auf .ldb oder .laccdb endet. Dies ist die Dateiendung der Datei, die beim öffnen einer Access-Datei angelegt wird. Ist eine solche Datei vorhanden, dann ist die Quelldatei offensichtlich geöffnet und kann nicht kopiert werden. Der Versuch, dies mit der FileCopy-Funktion zu erledigen, würde sonst zum Auslösen des Fehlers mit der Nummer 70 führen (Zugriff verweigert). In diesem Fall gibt die Funktion eine entsprechende Meldung aus. Auch für die Zieldatei erfolgt eine entsprechende überprüfung. Ist die Quelldatenbank hingegen nicht geöffnet und die Zieldatenbank entweder nicht geöffnet oder nicht vorhanden, kopiert die Prozedur diese mit der FileCopy-Methode, der Sie den Pfad zur Quell- und zur Zieldatei übergibt.
Public Function DateiKopieren(strQuelle As String, strZiel As String) Dim strQuelleTemp As String Dim strZielTemp As String strQuelleTemp = Replace(strQuelle, ".mdb", ".ldb") strQuelleTemp = Replace(strQuelleTemp, ".accdb", ".laccdb") If Len(Dir(strQuelleTemp)) > 0 Then MsgBox "Die Quelldatei muss geschlossen sein." Exit Function End If strZielTemp = Replace(strZiel, ".mdb", ".ldb") strZielTemp = Replace(strZielTemp, ".accdb", ".laccdb") If Len(Dir(strZielTemp)) > 0 Then MsgBox "Die Zieldatei muss geschlossen sein." Exit Function End If FileCopy strQuelle, strZiel If Len(Dir(strZiel)) > 0 Then DateiKopieren = True End If End Function
Listing 2: Die Funktion zum Kopieren der Zieldatei in die Quelldatei
Ist die Zieldatei anschließend im Dateisystem vorhanden, stellt die Funktion den Rückgabewert auf True ein.
Tabellen und Felder speichern
Wir wollen es dem Benutzer ermöglichen, alle zu ändernden Tabellen und Felder auf einen Streich zu definieren. Dazu muss er diese zunächst einlesen und wir müssen mit einem geeigneten Formular dafür sorgen, dass diese auch vom Benutzer bearbeitet werden können.
Wir wollen also Informationen über die Tabellen und die darin enthaltenen Felder speichern. Dazu benötigen wir zwei Tabellen namens tblTabellen und tblFelder. Die erste sieht im Entwurf wie in Bild 5 aus.
Bild 5: Entwurf der Tabelle tblTabellen
Sie enthält ein Primärschlüsselfeld, ein Feld mit dem Namen der Tabelle sowie ein Ja/Nein-Feld namens Anonymisieren, mit der Benutzer festlegen kann, ob diese Tabelle komplett anonymisiert werden soll. Die zweite Tabelle namens tblFelder enthält einige Felder mehr. Das liegt daran, dass hier die Details zum Anonymisieren der Inhalte gespeichert werden. Den Entwurf der Tabelle können Sie Bild 6 entnehmen. Neben den bereits aus der Tabelle tblTabellen bekannten Feldern nutzen wir hier die folgenden Felder:
Bild 6: Entwurf der Tabelle tblFelder
- Felddatentyp: Speichert den Zahlenwert, der den Felddatentyp des Feldes repräsentiert
- TabelleID: Fremdschlüsselfeld, mit dem der Datensatz der Tabelle tblTabellen festgelegt wird, zu dem das Feld gehört
- ErsetzenMitID: Fremdschlüsselfeld zu einer Tabelle namens tblErsetzenMit. Hier werden verschiedene Möglichkeiten zum Ersetzen abgebildet, zum Beispiel Vorname, Nachname, Straße et cetera. Damit wird beispielsweise festgelegt, aus welchen Hilfstabellen die zu ersetzenden Daten kommen.
- Info1, Info2, Info3: Diese Felder enthalten Hinweistexte für weitere Informationen, die in den Feldern Wert1, Wert2 und Wert3 gespeichert werden. Damit können Sie zum Beispiel für Felder, die mit Datumswerten gefüllt werden sollen, den Datumsbereich festlegen.
- Wert1, Wert2, Wert3: Diese Felder nehmen die Werte auf, die zum Füllen der Felder als Referenz benutzt werden sollen.
Wie Sie der Abbildung entnehmen können, legen wir für die Tabelle außerdem einen zusammengesetzten, eindeutigen Index an, der dafür sorgt, dass jeder Feldname nur einmal je Tabelle eingegeben werden darf. Dazu fügen wir diesem die beiden Felder Feldname und TabelleID hinzu und legen für die Eigenschaft Eindeutig den Wert Ja fest.
Beziehung zwischen den Tabellen tblTabellen und tblFelder
Die Tabelle tblTabellen und tblFelder sollen in einer 1:n-Beziehung stehen. Dazu haben wir per Nachschlagefeld bereits die notwendige Verknüpfung hinzugefügt. Die Verknüpfung können Sie in Bild 7 einsehen. Hier definieren wir noch referenzielle Integrität und aktivieren die Löschweitergabe an verwandte Datensätze. Dadurch werden beim Löschen eines der Datensätze der Tabelle tblTabellen auch alle mit diesem Datensatz verknüpften Datensätze der Tabelle tblFelder gelöscht.