Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.
Dynamischer Adressblock
Wenn Sie einen Adressblock etwa für die Anzeige in einem Bericht oder für anderweitige Nutzung zusammenstellen wollen, stoßen Sie mitunter auf eine anspruchsvolle Aufgabe. Dummerweise sind die Kundentabellen, aus denen die Adressen bezogen werden sollen, immer unterschiedlich aufgebaut. Noch dazu gibt es manchmal nicht nur eine einzige Adresse, sondern Liefer- und Rechnungsadresse. Dabei treten wiederum Unterschiede auf, wo die primäre Adresse eingetragen wird – also die Adresse, die als Rechnungs- und Lieferadresse genutzt wird, wenn nur eine Lieferadresse oder nur eine Rechnungsadresse vorliegt. Dieser Beitrag zeigt eine Funktion, mit der Sie die Adressblöcke für Ihren Einsatzzweck komfortabel zusammenstellen können.
Beispieltabelle
Ein Beispiel für eine Kundentabelle mit Rechnungs- und Lieferdaten sieht etwa wie in Bild 1 aus. Wenn für einen Kunden eine Lieferanschrift und eine Rechnungsanschrift vorliegt ist der Umgang mit den Daten in dieser Tabelle recht unkompliziert: Sie ermitteln die Lieferadresse aus den oberen Feldern und die Rechnungsadresse aus den unteren Feldern der Tabelle.
Bild 1: Beispiel für eine Kundentabelle
Etwas komplizierter wird es, wenn Liefer- und Rechnungsadresse identisch sind. Dann gilt es zunächst festzustellen, ob diese in den Feldern vorliegt, die mit Liefer... beginnen, oder in denen, die mit Rechnung... beginnen.
Sie als menschlicher Beobachter erkennen dies normalerweise mit einem Blick, aber wenn wir später automatisiert bestimmen wollen, welcher der beiden Blöcke mit Adressinformationen die gesuchten Informationen liefert, brauchen wir ein auswertbares Kriterium. Wir können an dieser Stelle festlegen, dass zumindest für deutsche Adressen mindestens eine PLZ oder ein Ort vorliegen müssen. Bei den anderen Daten kann es vorkommen, dass das eine oder andere Feld fehlt. Eine Adresse kann zwar Firma und Name einer Person enthalten, aber es kann auch nur eine Firma oder nur eine Person geben. Und auch die Straße muss nicht zwangsläufig angegeben werden, denn es gibt auch Adressen, die nur über Firma, Postleitzahl und Ort definiert werden.
Also legen wir an dieser Stelle fest, dass die PLZ unser Kriterium sein soll, ob in den Liefer...-Feldern oder den Rechnung...-Feldern eine Adresse vorliegen soll.
In der Tabelle tblKunden finden Sie übrigens die beiden Felder LieferAnredeID und RechnungAnredeID, die mit einer weiteren Tabelle namens tblAnreden verknüpft sind.
Im Folgenden wollen wir durch geeignete Konfigurationen und eine entsprechende VBA-Funktion sicherstellen, dass alle Varianten von Adressen wie in Bild 2 abgebildet in entsprechende Adressblöcke umgewandelt werden können. Das heißt, dass wir aus dem vollständigen Datensatz ganz oben die Lieferadresse aus den Liefer...-Feldern zusammenstellen und die Rechnungsadresse aus den Rechnung...-Feldern. Für den zweiten Datensatz wollen wir die Lieferadresse aus den Liefer...-Feldern zusammenstellen – genau wie die Rechnungsadresse. Der dritte Datensatz enthält nur Daten in den Rechnung...-Feldern, also sollen sowohl die Lieferadresse als auch die Rechnungsadresse aus diesen Feldern erstellt werden.
Bild 2: Verschiedene Konstellationen von AdressenEinfache Benutzerführung
Der Benutzer/Entwickler, der mit dieser Lösung arbeitet, soll es möglichst einfach haben, den Adressblock zu definieren. Daher wollen wir einige Daten in einer Konfigurationstabelle festlegen, die der Benutzer nach Wunsch bearbeiten kann.
Diese Tabelle sieht im Entwurf wie in Bild 3 aus. Das erste Feld enthält die Bezeichnung der jeweiligen Konfiguration. Das zweite und dritte Feld dienen der Eingabe eines Schemas für die Platzhalter, die in der Lieferadresse und der Rechnungsadresse verwendet werden sollen (mehr dazu weiter unten).
Bild 3: KonfigurationstabelleDas Feld Standard legt fest, ob die Quelltabelle standardmäßig die Lieferdaten enthält oder die Rechnungsdaten und dass, sofern die jeweils andere Adresse fehlt, die als Standard festgelegte Adresse angelegt wird. Dieses Feld legen wir als Nachschlagefeld aus, allerdings ohne fremde Tabelle als Datensatzherkunft. Stattdessen legen wir für die Eigenschaft Herkunftstyp den Wert Wertliste fest und geben für die Eigenschaft Datensatzherkunft die folgende Liste an:
"Lieferadresse";"Rechnungsadresse"
Dadurch zeigt das Feld diese beiden Einträge als mögliche Werte an. Das Feld Identifizierer nimmt den Namen des Feldes auf, das entscheidet, ob die Daten der Liefer- oder Rechnungsadresse vorliegen oder nicht – wie oben beschrieben wollen wir hier das PLZ-Feld für die Liefer- oder die Rechnungsadresse verwenden. Wenn die Daten für die Lieferadresse immer eingetragen werden und die der Rechnungsadresse nur, wenn diese von der Lieferadresse abweicht, tragen wir etwa das Feld RechnungPLZ in das Feld Identifizierer ein, sonst das Feld LieferPLZ.
Das Feld TabelleAbfrage nimmt den Namen der Tabelle oder Abfrage auf, die als Datenquelle für die Adressblöcke verwendet werden soll. Primaerschluesselfeld legt fest, welches Feld das Primärschlüsselfeld der in TabelleAbfrage festgelegten Tabelle oder Abfrage ist. Die folgenden beiden Felder sind vor allem interessant, wenn der Versand nicht nur in das gleiche, sondern auch in andere Länder erfolgt. Wenn Sie etwa eine Sendung innerhalb Deutschlands verschicken, geben Sie nur Firma, Name, Straße, PLZ und Ort im Adressblock an. Wenn die Sendung hingegen in das Ausland geht, fügen Sie noch eine Zeile mit dem Zielland hinzu. Damit Sie definieren können, wann das Zielland angegeben werden soll und wann nicht, tragen Sie unter NichtAuszugebendeLaender eine Liste der Länder ein, für die das Land nicht in die Zieladresse übernommen werden soll. Unter FelderMitLaendern geben Sie dann ein, welche Felder die Länder enthalten, in unserem Beispiel also etwa LieferLand und RechnungLand. Bei mehreren Einträgen trennen Sie diese durch Semikola.
Formular zur Verwaltung der Konfigurationen
Diese Daten verwalten wir in einem Formular namens frmKonfiguration. Es ist an die Tabelle tblKonfigurationen gebunden und sieht in der Formularansicht wie in Bild 4 aus. Besonderheiten gibt es bei diesem Formular nicht – die Steuerelemente werden nach dem Hineinziehen in den Detailbereich lediglich noch in der Größe und Position angepasst.
Bild 4: Formular zum Verwalten der KonfigurationenAnlegen einer Konfiguration
Noch nicht beschrieben haben wir den Inhalt der beiden Felder KonfigurationLieferung und KonfigurationRechnung. Hier gibt es verschiedene Möglichkeiten, die Felder der unter TabelleAbfrage als Datenquelle verwendeten Tabelle oder Abfrage einzutragen. Dazu schauen wir uns zunächst die Abfrage qryKunden an, welche die Daten der Tabelle tblKunden und tblAnreden in eine für unsere Zwecke optimal nutzbare Form bringt. Die Abfrage sieht im Entwurf wie in Bild 5 aus. Um diese zu erstellen, fügen Sie zunächst die Tabelle tblKunden und dann zwei Mal die Tabelle tblAnreden zum Entwurf der Abfrage hinzu. Die erste Verknüpfung zwischen dem Feld LieferAnredeID der Tabelle tblKunden und dem gleichnamigen Feld der Tabelle tblAnreden wird noch automatisch erstellt, die Verknüpfung zwischen dem Feld RechnungAnredeID der Tabelle tblKunden und dem Feld AnredeID der zweiten Instanz der Tabelle tblAnreden im Entwurf müssen Sie per Drag and Drop zwischen den beiden Feldern selbst hinzufügen.
Bild 5: Abfrage, welche die Daten der beteiligten Tabellen zusammenführtWichtig ist, dass Sie die Verknüpfungseigenschaften der beiden Verknüpfungen bearbeiten. Wenn Sie dies nicht tun und enthält beispielsweise das Feld RechnungAnredeID eines Datensatzes der Tabelle tblKunden keinen Wert und somit auch keine Verknüpfung zur Tabelle tblAnreden, dann wird dieser Datensatz der Tabelle tblKunden nicht als Ergebnis der Abfrage qryKunden zurückgeliefert. Damit dies dennoch geschieht, stellen Sie in den Verknüpfungseigenschaften der Beziehung die folgende Option ein:
Beinhaltet ALLE Datensätze aus 'tblKunden' und nur die Datensätze aus 'tblAnreden', bei denen
die Inhalte der verknüpften Felder beider Tabellen gleich sind.
Dann werden auch Daten aus tblKunden angezeigt, zu denen es nicht für beide Felder LieferAnredeID und RechnungAnredeID einen verknüpften Datensatz in der Tabelle tblAnreden gibt.
Die beiden verknüpften Tabellen ziehen wir übrigens hinzu, um jeweils das Feld Anrede statt der Felder LieferAnredeID und RechnungAnredeID für die Zusammenstellung der Adressblöcke bereitzustellen.
Damit diese dann später auch unterschieden werden können, obwohl sie den gleichen Feldnamen besitzen, stellen wir diesen noch jeweils den Alias LieferAnrede beziehungsweise RechnungAnrede voran, also etwa so:
LieferAnrede: Anrede
Nun erstellen wir die Vorlage für die beiden Konfigurationen für die Liefer- und die Rechnungsadresse. Dazu geben Sie den Platzhalter für einen Feldnamen aus der Datenquelle grundsätzlich in eckigen Klammern an.
Wenn Sie also sicher sind, dass alle Felder der als Datenquelle verwendeten Tabelle ausgefüllt sind, können Sie eine Vorlage wie die folgende verwenden:
[LieferFirma]
[LieferAnrede] [LieferVorname] [LieferNachname]
[LieferZusatz]
[LieferStrasse]
[LieferPLZ] [LieferOrt]
[LieferLand]
Für die Rechnungsadresse sieht dies analog so aus:
[RechnungFirma]
[RechnungAnrede] [RechnungVorname] [RechnungNachname]
[RechnungZusatz]
[RechnungStrasse]
[RechnungPLZ] [RechnungOrt]
[RechnungLand]
Nun kommt es allerdings vor, dass Informationen fehlen. Das ist kein Problem, wenn die komplette Zeile fehlt – diese wird dann von unserer Funktion einfach weggelassen. Fehlt also etwa die Zeile mit dem Platzhalter LieferZusatz, weil das gleichnamige Feld für den aktuellen Datensatz keinen Wert enthält, dann wird die Zeile einfach weggelassen.
Aber was, wenn beispielsweise das Feld Firma fehlt? In diesem Fall würde ja die Zeile mit der Firma wegfallen – auch das wäre kein Problem. Aber in diesem Fall möchten wir zum Beispiel die Anrede in die erste Zeile holen, also etwa so:
Herrn
André Minhorst
Borkhofer Str. 17
47137 Duisburg
Mit Firma soll der Adressblock so aussehen:
André Minhorst Verlag
Herrn André Minhorst
Borkhofer Str. 17
47137 Duisburg
Dafür haben wir uns eine spezielle Notation für eine If...Then...Else-Bedingung ausgedacht. Sie können in einer eckigen Klammer nicht nur den Namen eines Feldes angeben, sondern bis zu drei durch das Pipe-Zeichen (|) getrennte Felder. Der erste Eintrag gibt dabei das Feld an, dessen Inhalt auf den Wert Null beziehungsweise auf eine leere Zeichenfolge geprüft wird.
Der zweite Eintrag nimmt das Feld auf, das im Adressblock ausgegeben werden soll, wenn das im ersten Eintrag angegebene Feld nicht leer ist. Der dritte Eintrag nimmt das Feld auf, das im Adressblock erscheinen soll, wenn das im ersten Eintrag angegebene Feld leer bleibt. Der folgende Platzhalter sorgt also dafür, dass die Funktion prüft, ob das Feld LieferFirma einen Wert enthält. Falls ja, wird der Inhalt dieses Feldes ausgegeben, falls nicht, der Wert des Feldes Anrede:
[LieferFirma|Lieferfirma|LieferAnrede]
Wenn wir im gleichen Zuge dafür sorgen wollen, dass, wenn das Feld LieferFirma einen Wert enthält, die Anrede zusammen mit dem Vornamen und dem Nachnamen in die folgende Zeile gesetzt wird, verwenden wir die folgende Konstellation von Platzhaltern:
[LieferFirma|LieferAnrede] [LieferVorname] [LieferNachname]
Anwendung der Funktion
Für die Anwendung der Funktion namens Adressblock finden Sie im Modul mdlTools der Beispieldatenbank einige Beispiele. Die Funktion erwartet drei Parameter und liefert direkt den Adressblock als String zurück. Schauen wir uns den folgenden Aufruf an:
Debug.Print Adressblock(Lieferadresse, 1, 1)
Dieser liefert die Lieferadresse für die Konfiguration mit dem Wert 1 im Feld KonfigurationID und für den Kunden mit dem Wert 1 im Feld KundeID:
André Minhorst Verlag
Herr André Minhorst
Labor
Borkhofer Str. 17
47137 Duisburg
Wenn Sie die Rechnungsadresse für den gleichen Datensatz mit der gleichen Konfiguration ausgeben möchten, verwenden Sie einfach Rechnungsadresse als ersten Parameter:
Debug.Print Adressblock(Rechnungsadresse, 1, 1)
Das Ergebnis sieht dann so aus:
Frau
Anja Minhorst
Schnüranstr. 25
47138 Duisburg
Auf die gleiche Weise können Sie durch Variation des zweiten und dritten Parameters andere Konfigurationen und natürlich auch andere Einträge der Kundentabelle zur Ausgabe der Adressblöcke verwenden.
Bei den beiden vorangegangenen Beispielen war als Land jeweils Deutschland angegeben. Wie weiter oben festgelegt, soll der Wert Deutschland für die beiden Felder LieferLand und RechnungLand ignoriert werden, was hier geschieht.
Wenn Sie beispielsweise den vierten Eintrag der Beispieltabelle tblKunden, der das Land Schweiz verwendet, als Adressblock ausgeben wollen, sieht der Aufruf so aus:
Debug.Print Adressblock(Lieferadresse, 1, 4)
Dies ist der resultierende Adressblock:
Heinz Müller AG
Herr Heinz Müller
Testweg 2
2222 Luzern
Schweiz
Programmierung der Funktion
Damit können wir uns nun an die Programmierung der Funktion machen, die aus der Tabelle tblKunden mithilfe der Konfiguration aus tblKonfigurationen einen Adressblock erstellt. Zunächst definieren wir eine Enumeration, welche die beiden Werte Lieferadresse (0) und Rechnungsadresse (1) festlegt:
Public Enum eAdressart
Lieferadresse = 0
Rechnungsadresse = 1
End Enum
Die Funktion Adressblock legt die Enumeration für den Parameter lngAdressart als Datentyp fest, sodass Sie per IntelliSense direkt bei der Definition des Aufrufs der Funktion auf die beiden bereitstehenden Werte zugreifen können (s. Bild 6). Die beiden übrigen Parameter lngKonfigurationID und lngKundeID haben jeweils den Datentyp Long.
Bild 6: IntelliSense beim FunktionsaufrufDie Funktion sieht wie in Listing 1 aus und erstellt zunächst ein Recordset auf Basis der Tabelle tblKonfigurationen für den mit dem Parameter lngKonfigurationID übergebenen Primärschlüsselwert. Das Gleiche erledigt sie für die Tabelle tblKunden, deren Datensatz mit dem Wert des Parameters lngKundeID als Primärschlüsselwert in der Variablen rstKunde landet. Eine erste Hilfsfunktion namens VorlageErmitteln ermittelt die Vorlage für die angegebene Adressart aus lngAdressart, die Konfiguration aus rst und den Kunden aus rstKunde. Diese Funktion liefert den Inhalt eines der beiden Felder KonfigurationRechnung oder KonfigurationLieferung aus der Tabelle tblKonfigurationen zurück, die für die aktuelle Konstellation benötigt wird.
Public Function Adressblock(lngAdressart As eAdressart, lngKonfigurationID As Long, lngID As Long)
Dim db As DAO.Database, rst As DAO.Recordset, rstKunde As DAO.Recordset
Dim strVorlage As String, strZeilen() As String, strFeld As String, i As Integer
Dim intStart As Integer, intEnde As Integer, strElement As String, strZeile As String
Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.