Flexible Bestellverwaltung

Größe: px
Ab Seite anzeigen:

Download "Flexible Bestellverwaltung"

Transkript

1 Nr. 3 Juni 2013 Flexible Bestellverwaltung Verarbeiten Sie bestellte Positionen flexibel in Lieferungen und stellen Sie die Rechnungen nach Kundenwunsch zusammen (ab S. 2 und S. 24) Datenbanken anzeigen Verwenden Sie ein TreeView-Formular, um alle Datenbanken Ihrer Festplatte anzuzeigen und auszuwählen (ab S. 48) m:n-daten als Liste Jetzt ohne VBA und redundante Daten: Verknüpfte Daten als Liste in einem Textfeld anzeigen (ab S. 16) Fremdgehen per VBA Steuern Sie Funktionen und Formulare aus anderen Datenbanken fern (ab S. 36) Mat-Nr. H

2 Service Inhaltsverzeichnis / Impressum Tabellen und Datenmodellierung Formulare und Steuerelemente VBA und Programmiertechnik Interaktiv Lösungen Service Flexible Bestellverwaltung: Datenmodell 2 Standardwerte aus Lookup-Tabellen 8 m:n-daten in einer Zeile anzeigen 16 Flexible Bestellungen: Formulare 24 Funktionen aus anderen Datenbanken 36 VBA-Textexport unter Access 2007 und jünger 44 Alle Datenbanken einlesen und anzeigen 48 Abonnements verwalten, Teil 3 66 Impressum U2 Editorial 1 Impressum ISBN ISSN: Mat.-Nr Haufe-Lexware GmbH & Co. KG, Munzinger Str. 9, Freiburg Kommanditgesellschaft, Sitz Freiburg Registergericht Freiburg, HRA 4408 Komplementäre: Haufe-Lexware Verwaltungs GmbH, Sitz Freiburg, Registergericht Freiburg, HRB 5557; Martin Laqua Geschäftsführung: Isabel Blank, Markus Dränert, Jörg Frey, Birte Hackenjos, Randolf Jessl, Jens Köhler, Matthias Mühe, Markus Reithwiesner, Joachim Rotzinger, Dr. Carsten Thies Beiratsvorsitzende: Andrea Haufe Steuernummer: 06392/11008 Umsatzsteuer-Identifikationsnummer: DE Redaktion: Dipl.-Inform. (FH) Michael Forster, (Chefredakteur, V.i.S.d.P.), Dipl.-Ing. André Minhorst (Chefredaktion, extern), Frieda Flechler (Redaktionsassistentin), Rita Klingenstein (sprachl. Lektorat), Sascha Trowitzsch (Fachlektorat) Autoren: André Minhorst, Sascha Trowitzsch Anschrift der Redaktion: Postfach , Freiburg, Tel. 0761/898-0, Fax: 0761/ , computer@haufe.de, Internet: Druck: J.P. Himmer GmbH & Co KG, Postfach , Augsburg Auslieferung und Vertretung für die Schweiz: H.R. Balmer AG, Neugasse 12, CH-6301 Zug, Tel. 041/ , Fax: 041/ Das Update-Heft und alle darin enthaltenen Beiträge und Abbildungen sind urheberrechtlich geschützt. Jede Verwertung, die nicht ausdrücklich vom Urheberrechtsgesetz zugelassen ist, bedarf der vorherigen Zustimmung des Verlags. Das gilt insbesondere für Vervielfältigungen, Bearbeitungen, Übersetzungen, Mikroverfilmung und für die Einspeicherung in elektronische Systeme. Wir weisen darauf hin, dass die verwendeten Bezeichnungen und Markennamen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen. Die im Werk gemachten Angaben erfolgen nach bestem Wissen, jedoch ohne Gewähr. Für mögliche Schäden, die im Zusammenhang mit den Angaben im Werk stehen könnten, wird keine Gewährleistung übernommen.

3 Editorial Flexibel bestellen, liefern und abrechnen Die meisten Beispiele für Bestellverwaltungen sind recht einfach gehalten, um die Programmierung eines Bestellvorgangs leicht erklären zu können. Das gilt für das Internet ebenso wie für dieses Magazin. Dem schaffen wir in dieser Ausgabe Abhilfe: Ab jetzt dürfen Sie Ihrer Bestellverwaltung etwas mehr Flexibilität verleihen. Mit der Idealvorstellung, dass alle bestellten Artikel auch geliefert und in einer Rechnung erfasst werden können, machen wir jetzt Schluss! Das Datenmodell der Bestellverwaltung (Flexible Bestellungen: Datenmodell, ab S. 2) ermöglicht unter anderem das Aufteilen von Bestellpositionen einer Bestellung auf mehrere Lieferungen. Sie können auch Positionen aus verschiedenen Bestellungen in einer Lieferung zusammenfassen. Und bei den Rechnungen erhalten Sie ebenfalls völlige Freiheit: Diese stellen Sie nämlich aus beliebigen Bestellpositionen etwa einer oder mehrere einzelnen Bestellungen eines Kunden zusammen. So können Sie einem Kunden beispielsweise einmal monatlich eine Rechnung über alle gelieferten Artikel senden. Dies verlangt natürlich auch nach entsprechend umgestalteten Formularen. Wie Sie diese gestalten, beschreibt der Beitrag Flexible Bestellungen: Formulare ab S. 24. Nebenher leisten wir mal wieder Pionierarbeit. Haben Sie schon einmal versucht, die Daten aus einer m:n-beziehung wie beispielsweise bei Fahrzeugen und ihren Ausstattungsmerkmalen innerhalb eines Abfragefeldes als einfache, durch Onlinezugang Alle Beiträge im PDF-Format und alle Beispieldatenbanken unter /download Benutzername: flexibles Kennwort: datenmodell Kommata getrennte Liste auszugeben? Richtig: Das klappt eigentlich nur per VBA. Wir haben uns aber eine Lösung einfallen lassen, die das Ganze völlig dynamisch und ohne VBA-Einsatz erledigt. Lesen Sie mehr dazu unter m:n-daten in einer Zeile anzeigen (ab S. 16). Der Beitrag Alle Datenbanken einlesen und anzeigen (ab S. 48) liefert eine sehr interessante Lösung. Damit können Sie, ähnlich wie im Windows Explorer, in einem Baum Verzeichnisse des Dateisystems anzeigen. Der Clou dabei ist: Die Lösung liest nur die Verzeichnisse ein, die auch Datenbankdateien enthalten und zeigt diese an! Im Verzeichnisbaum können Sie per Kontextmenü Datenbanken öffnen, löschen oder in das Verzeichnis der Datenbankdatei wechseln. Unsere Beitragsreihe zum Thema Abonnements verwalten geht in diesem Heft ab S. 66 mit dem dritten Teil weiter. In dieser Ausgabe geht es um das Vorbereiten von Textdateien mit einer Empfängerliste zur weiteren Verarbeitung sowie um das Versenden einer Abonnement-Ausgabe per . Unter dem Titel Funktionen aus anderen Datenbanken betrachten wir ab S. 36, wie man VBA- Funktionen aus anderen Datenbanken aufruft. Dies kann beispielsweise interessant sein, wenn Sie etwa die Funktionen, die ein Access-Add-In bietet, direkt per VBA aufrufen möchten statt über den entsprechenden Menü-Eintrag. Viel Erfolg bei der Umsetzung der neuen Beiträge! Ihr Michael Forster 1

4 Tabellen und Datenmodellierung Flexible Bestellverwaltung: Datenmodell Flexible Bestellverwaltung: Datenmodell André Minhorst, Duisburg Die üblichen Beispiele zum Thema Bestellverwaltung gehen vereinfachend davon aus, dass immer alle Artikel vorhanden sind und dementsprechend auch in Rechnung gestellt werden können. In der Realität sieht dies anders aus: Natürlich ist nicht immer gewährleistet, dass alle angebotenen Artikel auch verfügbar sind. In diesem Fall lassen sich Lieferungen und Rechnungen nur schwer organisieren. Also kümmern wir uns nochmals um die entsprechenden Tabellen, Formulare und natürlich auch um die Berichte. Die Nordwind-Datenbank und Konsorten machen es vor: Bestellungen werden in einer Tabelle namens tblbestellungen verwaltet, die den Kunden referenziert und weitere Daten wie etwa das Bestell- und das Lieferdaten enthält. Die Bestellungen und die in einer Tabelle wie tblartikel gespeicherten Artikel werden über eine Verknüpfungstabelle namens tblbestellpositionen zusammengeführt. Auf diese Weise wird die Bestellung erfasst, was kein Problem ist hier wirken sich Fehlbestände noch nicht aus. Interessant wird es beim Erstellen von Lieferscheinen oder Rechnungen. Wenn eine Bestellung einen Artikel A und einen Artikel B enthält, aber nur A lieferbar ist, darf natürlich nur Artikel A auf dem Lieferschein erscheinen. Artikel B wird dann später hinterhergeschickt. Alternativ wartet man, bis beide Artikel verfügbar sind, und liefert diese in einer Sendung. Zusammenfassung Lernen Sie das Datenmodell für eine flexiblere Bestell-, Liefer- und Rechnungsverwaltung kennen. Techniken Datenmodellierung Voraussetzungen Access 2000 und höher Beispieldateien FlexibleBestellungen.mdb Shortlink /882 Um die Außenstände im Rahmen zu halten, soll der Kunde natürlich schnell seine Rechnung erhalten. Bevor Artikel B nicht beim Kunden angekommen ist, kann man diesen aber wohl kaum in Rechnung stellen also schickt man zunächst eine Rechnung über Artikel A oder versendet alternativ die Rechnung mit allen Positionen nach Versendung aller bestellten Artikel. Hier gehen wir vorsichtig davon aus, dass eine Bestellposition später einer Rechnungsposition entspricht. Auch dies ist nicht unbedingt gegeben: Wenn ein Kunde 100 Stück eines bestimmten Artikels bestellt und nur 50 Stück lieferbar sind, muss man gegebenenfalls selbst eine einzige Position auf zwei Lieferschein- und Rechnungspositionen aufteilen können. Dies kann man noch weiter ausarbeiten. In manchen Branchen schicken Kunden nicht nur eine Bestellung in einem bestimmten Zeitraum, sondern ordern schnell noch mal einen oder mehrere Artikel nach. Hier sollte man die Möglichkeit vorsehen, nicht für jede Bestellung eine eigene Rechnung zu schicken, sondern mehrere Bestellungen zusammenzufassen. Und um dem Ganzen die Krone aufzusetzen: Wenn ein Kunde zwei Bestellungen aufgibt, bei denen beide nicht sofort komplett bearbeitet werden können, weil nicht alle Artikel vorliegen, sollte man auch mehrere Artikel aus verschiedenen Bestellungen in einer einzelnen Rechnung zusammenfassen können. 2

5 Flexible Bestellverwaltung: Datenmodell Tabellen und Datenmodellierung Abb. 1: Datenmodell, wenn für jede Bestellung eine Rechnung verschickt wird Und schließlich ließe sich die Abrechnung auch noch nach Zeiträumen definieren: So könnten Sie beispielsweise, unabhängig davon, wie viele Bestellungen der Kunde getätigt hat, eine Rechnung etwa pro Woche oder pro Monat schicken, die alle bis dahin gelieferten Artikel berücksichtigt. Sie sehen: Es gibt mehr Möglichkeiten als die übliche 1:1-Abbildung von Bestellung und Rechnung. Schauen wir uns also an, wie sich dies auf das Datenmodell auswirkt und wie sich die Daten in Formularen und Berichten bearbeiten und ausgeben lassen. Standard: Bestellung = Rechnung Im einfachsten Fall sieht das Datenmodell wie in Abb. 1 aus. Jede Bestellung bezieht sich auf einen Kunden und enthält einen oder mehrere Artikel, für die in der Tabelle tblbestelldetails ein individueller Preis festgelegt werden kann. Außerdem landen dort die Anzahl und gegebenenfalls noch ein Rabatt. Aber dort ist keine einzige Tabelle zu sehen, die Informationen zur Rechnung liefert? Doch: Die Rechnungsinformationen werden direkt aus den zum Speichern der Bestelldaten verwendeten Tabellen entnommen. In diesem Fall wäre jede zusätzliche Tabelle, in der die Bestelldaten erneut als Rechnungsdaten aufgeführt werden, unnötig. Die Flexibilität geht allerdings gegen Null. Es ist hier noch nicht einmal möglich, eine einzelne Bestellposition nachvollziehbar zu stornieren. Also erweitern wir das Datenmodell so, dass wir alle eingangs erwähnten Möglichkeiten abdecken können. Anschließend kümmern wir uns um die Möglichkeiten der Dateneingabe und der Berichtserstellung. Erweiterung: Kostenstelle Der Kunde verarbeitet oder versendet die gelieferten Artikel möglicherweise weiter und muss diese dazu verschiedenen Kostenstellen zuordnen können. Daher sollte die Tabelle tblbestelldetails um ein Feld namens Kostenstelle ergänzt werden. Da dieses je Kunde anders aussehen kann, verwenden wir hier vorerst ein reines Textfeld. Sollte man die Bezeichnung der Kostenstellen in eine eigene Tabelle ausgliedern und dann per Fremdschlüsselfeld darauf verweisen? Wenn wir flexibel bleiben wollen, lautet die Antwort ja. Außerdem ist eine weitere Änderung an der bestehenden Tabelle tblbestelldetails nötig. Es Abb. 2: Die Tabelle tblbestelldetails in der Entwurfsansicht 3

6 Tabellen und Datenmodellierung Flexible Bestellverwaltung: Datenmodell kann ja durchaus geschehen, dass der Kunde in einer Bestellung den gleichen Artikel für mehrere Kostenstellen ordert. Aktuell enthält die Tabelle tblbestelldetails jedoch einen zusammengesetzten Primärschlüssel über die Felder BestellungID und ArtikelID (s. Abb. 2). Dieser Schlüssel muss dann auf die KostenstelleID ausgeweitet werden. Nebenher erhalten wir natürlich einen weitaus höheren Komfort, wenn eine von vielen Kostenstellen eines Kunden ausgewählt werden kann und nicht jedesmal manuell eingetippt werden muss. Die Tabelle zum Speichern der Kostenstellen sieht wie in Abb. 3 aus. Neben dem Primärschlüsselfeld und der Bezeichnung der jeweiligen Kostenstelle enthält die Tabelle auch noch ein Feld namens KundeID. Abb. 3: Tabelle zum Speichern der Kostenstellen Dieses erlaubt die Zuordnung der Kostenstellen zu den Kunden, damit beim Anlegen einer neuen Bestellung direkt alle zum Kunden gehörenden Kostenstellen verfügbar sind. Damit eine Kostenstelle nicht doppelt angelegt werden kann, fügen Sie noch einen zusammengesetzten eindeutigen Primärschlüssel für die beiden Felder KundeID und Kostenstelle zur Tabelle hinzu. Abb. 4: Die neue Tabelle tblpositionen Außerdem erhält die Tabelle einen nur aus einem Feld bestehenden Primärschlüssel namens BestellpositionID. Das Fremdschlüsselfeld zur Auswahl einer Kostenstelle heißt KostenstelleID und wird als Nachschlagefeld ausgelegt. Es soll die Daten der Tabelle tblkostenstellen zur Auswahl anbieten. Positionen statt Bestelldetails Die Tabelle tblbestelldetails benennen wir im Rahmen der Umgestaltung des Datenmodells gleich in tblbestellpositionen um. 4 Damit in jeder Bestellung jeder Artikel nur in einer Position je Kostenstelle eingegeben werden kann, fügen Sie der Tabelle einen eindeutigen Index über die drei Felder BestellungID, ArtikelID und KostenstelleID hinzu (s. Abb. 4). Die Auswahl der Kostenstelle muss später in den Formularen natürlich derart eingeschränkt wer-

7 Flexible Bestellverwaltung: Datenmodell Tabellen und Datenmodellierung den, dass nur die Kostenstellen des Kunden der Bestellung angezeigt werden. Standardkostenstelle Wenn Sie die Positionen einer Bestellung für einen Kunden anlegen, möchten Sie je nach Anzahl der Positionen nicht jedesmal die Kostenstelle auswählen. Also fügen wir der Tabelle tblkostenstellen ein Feld Abb. 5: Die Tabelle tblkostenstellen im Datenmodell namens IstStandard hinzu, mit dem Sie die aktuelle Kostenstelle für den Kunden festlegen können Abb. 5 zeigt die beteiligten Tabellen zum Festlegen von Kostenstelle LieferungID: Primärschlüsselfeld der Tabelle und Standardkostenstelle im Überblick. Lieferdatum: Datum der Lieferung Diese soll im Bestellformular schnell geändert werden können, damit die fortan angelegten Bestellpositionen im Kontext der aktuellen Kostenstelle angelegt werden. Mehr zu dieser Art von Standardwerten erfahren Sie im Beitrag Standardwerte aus Lookup-Tabellen (/883). Lieferungen verwalten Der entscheidende Schritt zur flexiblen Rechnungserstellung ist die Verwaltung der gelieferten Artikel. Dies soll im Wesentlichen Informationen darüber erfassen, welcher Kunde wann welche Lieferung erhalten hat. Anschließend können Sie dann leicht auf die gelieferten Positionen und ihr Lieferdatum zugreifen, um darauf basierend wie auch immer aufgeteilte Rechnungen zu erstellen egal, ob Sie eine Rechnung pro Lieferung oder über einen bestimmten Zeitraum stellen möchten. Um diese Daten zu erfassen, legen Sie zwei weitere Tabellen in der Datenbank an. Die erste enthält die Stammdaten zu den einzelnen Lieferungen und heißt tbllieferungen. In einem ersten Entwurf soll die Tabelle nur die folgenden Felder enthalten gegebenenfalls kommen noch weitere hinzu: LieferungDurch: Fremdschlüsselfeld zur Tabelle tblversandfirmen Sendungsverfolgung: Feld zum Speichern eventueller Sendungsverfolgungsnummern Die eigentlich gelieferten Waren werden dann in der Tabelle tbllieferpositionen erfasst. Diese enthält die folgenden Felder: LieferpositionID: Primärschlüsselfeld der Tabelle LieferungID: Fremdschlüsselfeld zur in der Tabelle tbllieferungen gespeicherten Lieferung BestellpositionID: Fremdschlüsselfeld zur Tabelle tblbestellpositionen, um die gelieferte Position zu referenzieren Menge: Tatsächlich gelieferte Menge. Hiermit soll sichergestellt werden, dass eventuell weniger gelieferte Mengen auch erfasst werden, sodass fehlende Lieferungen entsprechend berechnet werden können. Bleibt noch eine wichtige Frage: Woher erfährt man, für welchen Kunden die in der Tabelle tbllieferungen erfasste Lieferung gedacht ist? Eigentlich könnte man den Kunden mithilfe einer Abfrage ermitteln, die von der Tabelle tblliefe- 5

8 Tabellen und Datenmodellierung Flexible Bestellverwaltung: Datenmodell Abb. 6: Datenmodell mit Liefer-Tabellen rungen über die Tabelle tbllieferposition, tblbestellpositionen und tblbestellungen schließlich zur Tabelle tblkunden führt. Allerdings sollte man sich die Frage stellen, ob man diesen Weg wirklich gehen möchte, wenn man die Lieferungen an einen Kunden etwa im Unterformular eines Kundenformulars auflisten möchte. Alternativ könnte man den Kunden nochmals in der Tabelle tbllieferungen speichern. Abb. 6 zeigt, wo das neue Feld KundeID landen würde, welches Feld dadurch referenziert wird (das Feld KundeID der Tabelle tblkunden) und über welches Feld man sonst den Kunden zur Lieferung ermitteln müsste (das Feld KundeID der Tabelle tblbestellungen). Genau genommen enthält das Fremdschlüsselfeld KundeID in der Tabelle tbllieferungen natürlich redundante Informationen. Damit daraus Inkonsistenzen entstehen, müsste der Benutzer jedoch den Wert des Feldes KundeID der Tabelle tblbestellungen oder der Tabelle tbllieferungen manuell ändern. Über die Benutzeroberfläche, sprich die Formulare der Anwendung, sollte dies nicht möglich sein die Datensätze der Tabellen tblbestellungen und tbllieferungen werden normalerweise nur in Unterformularen anderer Formulare angezeigt. Selbst in Ausnahmefällen sollte der Kunde einer Bestellung oder Lieferung nicht änderbar sein. 6 Also legen wir das Feld KundeID wie vorgeschlagen in der Tabelle tbllieferungen an. Rechnungstabellen Für die Verwaltungen der Rechnungen und Rechnungspositionen sehen wir zwei weitere Tabellen vor. Die erste heißt tblrechnungen und enthält der Einfachheit halber zunächst die folgenden Felder: RechnungID: Primärschlüsselfeld der Tabelle KundeID: Fremdschlüsselfeld zum Festlegen des Kunden Rechnungsdatum: Datum der Rechnung Da es hier zunächst um die reine Erstellung der Rechnungen ohne irgendwelchen Schnickschnack geht, sollen keine weiteren Felder aufgenommen werden. Die Tabelle tblrechnungspositionen besteht aus den folgende Feldern und speichert die einzelnen Rechnungspositionen: RechnungspositionID: Primärschlüsselfeld der Tabelle RechnungID: Fremdschlüsselfeld, um die Rechnungsposition einer Rechnung zuordnen zu können

9 Flexible Bestellverwaltung: Datenmodell Tabellen und Datenmodellierung Abb. 7: Datenmodell mit Rechnungs- Tabellen LieferpositionID: Fremdschlüsselfeld zum Festlegen der Lieferposition, auf die sich die Rechnungsposition bezieht Die Tabellen im Zusammenhang Das hört sich etwas mau an. Die Rechnungstabellen sollen mit sechs Feldern auskommen? Wie soll man daraus etwa einen Rechnungsbericht aufbauen? Dies wird etwas klarer, wenn wir einen Blick auf die Zusammenfassung des Datenmodells aus Abb. 7 werfen. Wenn Sie beispielsweise die Daten für einen Rechnungsbericht zusammenstellen möchten, benötigen Sie natürlich das Rechnungsdatum. Aber was ist beispielsweise mit der Adresse des Kunden? An diese in der Tabelle tblkunden enthaltenen Daten gelangen Sie über die Verknüpfung mit dieser Tabelle. Und woher kommen die Daten für die Rechnungspositionen? Dazu hangeln wir uns über das Fremdschlüsselfeld LieferpositionID zunächst zur Tabelle tbllieferpositionen, der wir die Menge der aktuellen Position entnehmen. Einzelpreis und Rabatt sowie den Mehrwertsteuersatz entnehmen wir der Tabelle tblbestellpositionen. Sonst fehlt eigentlich nichts sollten die kundenspezifischen Kostenstellen aufgenommen werden, können diese ebenfalls aus der Tabelle tblbestellpositionen entnommen werden. Zusammenfassung und Ausblick Durch die aufeinander aufbauenden Tabellen tblbestellpositionen, tbllieferpositionen und tblrechnungspositionen können Sie die bestellten Artikel flexibel in einer oder mehreren Lieferungen an den Kunden schicken. Dadurch dass Sie in einer Rechnung beliebige gelieferte Positionen berücksichtigen können, erhalten Sie eine recht flexible Rechnungserstellung. In einem weiteren Teil erläutern wir, wie Sie Bestellungen, Lieferungen und Rechnungen in entsprechenden Formularen erstellen und verwalten. 7

10 Tabellen und Datenmodellierung Standardwerte aus Lookup-Tabellen Standardwerte aus Lookup-Tabellen André Minhorst, Duisburg Es gibt eine Reihe von Beispielen für den Einsatz von Lookup-Tabellen die einfachste ist wohl die Tabelle zum Speichern von Anreden. In einigen Fällen soll eines der enthaltenen Elemente standardmäßig verwendet werden. Dann gilt es, dieses Standardelement entsprechend zu deklarieren. Wie so oft gibt es unter Access verschiedene Möglichkeiten, dies zu realisieren und es gibt verschiedene Schwierigkeitsgrade. Dieser Beitrag zeigt einige Varianten auf. Einfache Standardwerte Wenn ein Formular auf einer Tabelle etwa namens tblkunden basiert, welche die Auswahl der Anrede per Nachschlagefeld ermöglicht, kann der Benutzer eine der Anreden auswählen zum Beispiel Herr, Frau oder Firma. Das heißt, dass der Benutzer immer eine Auswahl treffen muss. Diese Arbeit können Sie dem Benutzer erleichtern, indem Sie einen der Werte des Kombinationsfeldes als Standardwert festlegen. Dazu gibt es verschiedene Varianten: Sie legen einen der Werte des Primärschlüsselfeldes der Tabelle tblanreden als Standardwert der Tabelle tblkunden fest (s. Abb. 1). Der festgelegte Wert wird dann im neuen Datensatz bereits angezeigt (s. Abb. 2). Abb. 1: Festlegen eines Standardwertes im Tabellenentwurf Sie legen einen der Werte des Primärschlüsselfeldes der Tabelle tblanreden als Standardwert des Kombinationsfeldes im Formular Zusammenfassung Erfahren Sie, wie Sie nicht nur einfache Standardwerte, sondern auch dynamische Standardwerte oder Standardwerte für verknüpfte Tabellen definieren. Techniken Datenmodellierung, Formulare, VBA Voraussetzungen Access 2000 Beispieldateien Standardwerte_1.mdb, Standardwerte_2.mdb Shortlink /883 8 Abb. 2: Standardwert in der Datenblattansicht fest. Wie dies gelingt, zeigt Abb. 3. Wenn Sie ein gebundenes Feld auf Basis eines Feldes der Datenherkunft aus der Feldliste in das Formular ziehen, wird die Standardwert-Eigenschaft mit dem gleichen Wert wie in der Tabelle eingerichtet. Sie lassen den Benutzer festlegen, welcher der Werte der Tabelle tblanreden als Standard-

11 Standardwerte aus Lookup-Tabellen Tabellen und Datenmodellierung In einem Formular, welches ein Nachschlagefeld namens AnredeID auf Basis der Tabelle tblanreden einsetzt, können Sie den in der Tabelle tbloptionen festgelegten Standardwert wie in Abb. 6 einstellen und zwar mit einer einfachen DLookup-Abfrage: =DomWert("Standardanrede";"tb loptionen") Abb. 3: Festlegen eines Standardwertes im Formularentwurf Abb. 4: Optionentabelle mit aktuell nur einer Option Wenn Sie den Standardwert in der Tabelle tbloptionen bei geöffnetem Formular frmkunden ändern, wird beim Anlegen des folgenden Datensatzes bereits der gewählte Standardwert verwendet. Im Tabellenentwurf können Sie einen solchen Ausdruck übrigens nicht verwenden. Dort sind nur ganz wenige Standardfunktionen wie etwa Datum() oder statische Werte erlaubt. Meistgenutzter Wert als Standard Abb. 5: Festlegen der Standardanrede in der Optionentabelle wert verwendet werden soll. Eine solche Information würde man dann beispielsweise in einer Optionen-Tabelle verwalten. Standardanrede in Optionentabelle Wenn Sie es auf die Spitze treiben möchten, können Sie auch jeweils abfragen, welcher Wert des Nachschlagefeldes bisher am meisten verwendet wurde. Dazu brauchen Sie die Optionentabelle nicht mehr, sondern passen nur den Ausdruck für die Eigenschaft Standardwert an und zwar auf diesen Ausdruck (im Beispielformular frmkunden für das Kombinationsfeld cboanredeidmeistgenutzt eingestellt): Eine einfache Optionentabelle mit nur der einen benötigten Option könnte im Entwurf wie in Abb. 4 aussehen. Das Feld Standardanrede verwendet wiederum die Tabelle tblanreden als Datensatzherkunft für ihr Nachschlagefeld. Dadurch können Sie wie in Abb. 5 ganz einfach den gewünschten Standardwert auswählen. Abb. 6: Dynamischer Standardwert 9

12 Tabellen und Datenmodellierung Standardwerte aus Lookup-Tabellen =DomWert("AnredeID";"qryMeisteAnre de") Die dort verwendete Abfrage qry- MeisteAnrede sieht im Entwurf wie in Abb. 7 aus. Sie sortiert die Werte des Feldes AnredeID nach der Anzahl ihres Vorkommens in der Tabelle tblkunden. Damit das Ergebnis nur den ersten Wert und somit die meistverwendete Anrede liefert, erhält die Eigenschaft Spitzenwerte der Abfrage den Wert 1. Das Ergebnis der Abfrage sieht wie in Abb. 8 aus. Abb. 7: Abfrage zur Ermittlung der meistgenutzten Anrede im Entwurf... In diesem Fall ermittelt das Formular bei jedem Wechseln zum neuen Datensatz, welche Anrede eingesetzt werden soll. Letzte Auswahl verwenden Wenn Sie für neue Datensätze jeweils den zuvor gespeicherten Wert im Nachschlagefeld als Standardwert nutzen wollen, benötigen Sie eine kleine VBA-Routine, die nach dem Speichern des vorherigen Datensatzes den Standardwert neu setzt. Im Fall des Fremdschlüsselfeldes AnredeID Abb. 8:... und in der Datenblattansicht verwenden Sie den folgenden Ausdruck hier in der Ereignisprozedur, die durch das Ereignis Nach Aktualisierung des Kombinationsfeldes cboanredeidvorher im Beispielformular frmkunden ausgelöst wird: Private Sub cboanredeidvorher_click() Me!cboAnredeIDVorher.DefaultValue = _ Str(CDbl(Me!cboAnredeIDVorher)) Die Wirkung zeigt sich sofort. Im Beispielformular frmkunden brauchen Sie nur einen neuen Wert für das unterste Kombinationfeld auszuwählen und nach Vervollständigung der übrigen Felder zu einem neuen Datensatz zu wechseln. Dieser zeigt dann gleich den zuletzt festgelegten Eintrag als Standardwert an (s. Abb. 9). Abhängige Lookup-Datensätze Abb. 9: Der Standardwert kann gleich nach der Auswahl eines Wertes auf den gewählten Wert eingestellt werden. Mit abhängigen Lookup-Datensätzen sind solche Datensätze einer Lookup-Tabelle gemeint, die nicht allgemein ausgewählt werden sollen, sondern nur in Abhängigkeit vom aktuellen Daten- 10

13 Standardwerte aus Lookup-Tabellen Tabellen und Datenmodellierung Abb. 10: Standardwert für abhängige Verknüpfungen, erste Variante satz der verknüpften Tabelle. Dies lässt sich am besten anhand eines Beispiels erläutern in diesem Falle an den Kostenstellen eines Kunden. In einer Bestellverwaltung sollen für jeden Kunden verschiedene Kostenstellen verwaltet werden, die, sofern der Kunde die Bestellungen mit seinen Kunden oder einem bestimmten Projekt weiterverrechnen will, den einzelnen Positionen einer Bestellung zugeordnet werden können. Sprich: Es gibt je Kunde eine Tabelle mit Kostenstellen, die dem Kunden zugeordnet sind etwa über eine Verknüpfung des Fremdschlüsselfeldes KundeID der Kostenstellentabelle mit dem Feld KundeID der Kundentabelle. In der Tabelle der Bestellpositionen soll für jede Position eine Kostenstelle angegeben werden. Nun soll auch hier ein Standardwert für die Kostenstelle je Kunde festgelegt werden, die beim Anlegen einer neuen Position verwendet wird. Dort gibt es eine Tabelle namens tblkostenstellen, in welcher die Bezeichnung der Kostenstelle sowie die ID des Kunden gespeichert werden soll, zu dem die Kostenstelle gehört. Jeder Kunde hat andere Bezeichnungen für seine Kostenstellen, daher ist dies sinnvoll. Abb. 11 zeigt die Tabelle tblkostenstellen mit ein paar Beispieldatenbank. Die Tabelle tblpositionen enthält ein Feld namens KostenstelleID, mit dem eine der Kostenstellen ausgewählt werden soll. Im Formular wird die Auswahl der verfügbaren Kostenstellen dann auf die Kostenstellen zum aktuellen Kunden eingeschränkt. Nun soll das Feld KostenstelleID noch mit einem durch den Benutzer (oder auf eine der oben ge- Lookup-Standardwert, Variante I Dafür gibt es mindestens zwei Möglichkeiten. Die erste sieht im Datenmodell wie in Abb. 10 aus (siehe Beispieldatenbank Standardwerte_1. mdb). Abb. 11: Die Tabelle tblkostenstellen mit dem Fremdschlüsselfeld KundeID 11

14 Tabellen und Datenmodellierung Standardwerte aus Lookup-Tabellen Abb. 12: Standardwert für die Kostenstelle neuer Datensätze abhängig vom aktuellen Kunden nannten Methoden) festzulegenden Standardwert belegt werden. Dazu haben wir in der ersten Variante ein Feld namens StandardkostenstelleID zur Tabelle tblkunden hinzugefügt. Diese Tabelle ist ebenfalls als Nachschlagefeld zur Auswahl der Datensätze der Tabelle tblkostenstellen Abb. 13: Unterformular mit vom Hauptformular abhängigem Standardwert ausgelegt, und auch im Formular zur Einstellung der Werte der enthaltenen Datensätze sollen nur die Kostenstellen =DomWert("StandardkostenstelleID";"tblKunden"; angezeigt werden, die zum aktuellen Kunden "KundeID =" & [Parent]![KundeID]) gehören. Nach der Auswahl der Standardkostenstelle eines Kunden soll beim Neuanlegen von Bestellpositionen immer diese Kostenstelle als Standardwert für das Feld KostenstelleID vorgegeben werden. Das Ergebnis finden Sie in Abb. 13. Dort zeigt das Feld KostenstelleID den in der Tabelle tblkunden enthaltenen Standardwert an. Lookup-Standardwerte, Variante II Als Beispiel verwenden wir ein Formular wie in Abb. 12. Das Unterformular zeigt alle Datensätze der Tabelle tblpositionen für den aktuell im Hauptformular ausgewählten Kunden-Datensatz. Die Eigenschaft Standardwert des Kombinationsfeldes zur Auswahl der Kostenstelle einer Bestellposition stellen Sie dabei auf einen Wert wie den Folgenden ein: In der zweiten Variante (siehe Standardwerte_2. mdb) wird der Standardwert der Kostenstelle für einen Kunden nicht in der Kundentabelle, sondern in der Tabelle der Kostenstellen festgelegt. Das Datenmodell sieht dann wie in Abb. 14 aus. Für das Feld KostenstelleID der Tabelle tblpositionen sollen dann nach wie vor nur solche Datensätze der Tabelle tblkostenstellen ausgewählt werden, deren Feld KundeID mit dem entspre- 12

15 Standardwerte aus Lookup-Tabellen Tabellen und Datenmodellierung Abb. 14: Datenmodell für die Variante mit dem Standardwert in der Kostenstellen-Tabelle chenden Wert des Feldes KundeID der Tabelle tblbestellungen übereinstimmt. Dies ist unter Access per VBA beim Anlegen beziehungsweise Ändern der Daten zu gewährleisten, unter dem SQL Server etwa könnte dies durch entsprechende Trigger erledigt werden. Uns interessiert aber, wie wir in diesem Fall an den Standardwert für die KostenstelleID eines Kunden herankommen. Wir verwenden wieder ein ähnlich aufgebautes Formular wie im vorherigen Beispiel. Diesmal wird der Ausdruck für den Standardwert wie folgt ermittelt: Verwalten der Standardwerte, Variante I Die Verwaltung der Standardwerte fällt je nach Variante anders aus. Im ersten Fall mit der Auswahl der Standard-Kostenstelle als Feld der Tabelle tblkunden legen Sie einfach ein Formular an, das die Tabelle tbl- Kunden als Datenherkunft verwendet, und fügen neben den übrigen gewünschten Feldern das Feld StandardkostenstelleID zum Detailbereich hinzu (s. Abb. 15). Dieses Kombinationsfeld soll jedoch nicht alle Datensätze der Tabelle tblkostenstellen zur Auswahl anbieten, sondern nur die für den aktuellen Kunden. Dies lässt sich leider nicht ohne VBA-Einsatz erledigen. Wenn Sie nämlich etwa den folgenden Ausdruck verwenden, um nach KundeID zu filtern, funktioniert dies nur für die Anzeige des ersten Kundendatensatzes nach dem Öffnen des Formulars: SELECT KostenstelleID, Kostenstelle, KundeID FROM tblkostenstellen WHERE KundeID=[Forms]![frmKunden]![KundeID]); Wechseln Sie dann zu einem Datensatz, wird der Filter nicht aktualisiert das Kombinationsfeld zeigt immer noch die zum ersten Kunden gehörenden Kostenstellen an. Sie haben nun zumindest die folgenden beiden Möglichkeiten: =DomWert("KostenstelleID";"tblKostenstellen"; "KundeID =" & [Parent]![KundeID] & " AND IstStandard = TRUE") Dieser Ausdruck ermittelt die KostenstelleID des Datensatzes der Tabelle tblkostenstelle, dessen Feld KundeID mit dem aktuell im Hauptformular ausgewählten Kunden übereinstimmt und dessen Wert im Feld IstStandard den Wert True enthält. Abb. 15: Formular zur Auswahl der Standardkostenstelle 13

16 Tabellen und Datenmodellierung Standardwerte aus Lookup-Tabellen Sie behalten die aktuelle Datenherkunft mit eingebautem Filter bei und aktualisieren den Inhalt des Unterformulars bei jedem Datensatzwechsel. Sie stellen die Datensatzherkunft des Kombinationsfeldes gleich beim Wechsel des Datensatzes per VBA ein. Die erste Variante erfordert den Einsatz der folgenden Ereignisprozedur, die durch das Ereignis Beim Anzeigen ausgelöst wird: Private Sub Form_Current() Me!StandardkostenstelleID.Requery Bei der zweiten Variante verwenden Sie als Datenherkunft zunächst die folgende einfache Abfrage: SELECT KostenstelleID, Kostenstelle FROM tblkostenstellen Für das Ereignis Beim Anzeigen hinterlegen Sie dann die folgende Prozedur, welche die Datensatzherkunft komplett neu einstellt und zwar auf die nach dem entsprechenden Wert im Feld KundeID gefilterte Tabelle tblkostenstellen: Private Sub Form_Current() Me!StandardkostenstelleID.RowSource = _ "SELECT KostenstelleID, Kostenstelle µ FROM tblkostenstellen WHERE µ KundeID = " & Me!KundeID Die im Kombinationsfeld StandardkostenstelleID ausgewählte Kostenstelle wird dann direkt im entsprechenden Feld der Tabelle tblkunden gespeichert. Verwalten der Standardwerte, Variante II Im zweiten Fall arbeiten wir mit dem Feld Ist- Standard in der Tabelle tblkostenstellen. Wir können also nicht einfach ein gebundenes Feld zum Formular frmkunden hinzufügen und dessen Werte auswählen. Aber mit etwas mehr Aufwand lässt sich zumindest auf Seiten der Benutzeroberfläche der gleiche Effekt wie bei der ersten Variante erreichen. Das Formular ist identisch aufgebaut, nur ist das Kombinationsfeld cbostandardkostenstelleid diesmal nicht an ein Feld der Datenherkunft des Formulars frmkunden gebunden. Wir legen auch seine Datenherkunft nicht im Vorhinein fest. Stattdessen stellen Sie nur die beiden Eigenschaften Spaltenanzahl und Spaltenbreiten auf die Werte 2 und 0cm ein. Das Füllen der Datensatzherkunft und die Auswahl des anzuzeigenden Datensatzes übernimmt nun die durch das Ereignis Beim Anzeigen ausgelöste Ereignisprozedur, die Sie in Listing 1 finden. Die Datensatzherkunft wird genau wie im vorherigen Beispiel eingestellt. Da das Kombinationsfeld jedoch nicht gebunden ist, muss die Ereignisprozedur einen Wert dafür auswählen. Dies erledigt die zweite Zeile, die per DLookup- Funktion den Datensatz der Tabelle tblkostenstellen ermittelt, welcher dem aktuellen Kunden zugeordnet ist und der gleichzeitig über das Feld IstAktiv markiert ist. Damit zeigt das Formular die jeweils zum Kunden gehörende Standardkostenstelle an. Allerdings Listing 1: Füllen des Kombinationsfeldes mit den Kostenstellen-Daten Private Sub Form_Current() Me!cboStandardkostenstelleID.RowSource = _ "SELECT KostenstelleID, Kostenstelle FROM tblkostenstellen WHERE KundeID = " & Me!KundeID Me!cboStandardkostenstelleID.Value = DLookup("KostenstelleID", "tblkostenstellen", _ "KundeID = " & Me!KundeID & " AND IstStandard = TRUE") 14

17 Standardwerte aus Lookup-Tabellen Tabellen und Datenmodellierung Listing 2: Speichern des Wertes im ungebundenen Kombinationsfeld Private Sub cbostandardkostenstelleid_afterupdate() Dim db As DAO.Database Set db = CurrentDb db.execute "UPDATE tblkostenstellen SET IstStandard = False WHERE KundeID = " _ & Me!KundeID, dbfailonerror db.execute "UPDATE tblkostenstellen SET IstStandard = True WHERE KostenstelleID = " _ & Me!cboStandardkostenstelleID, dbfailonerror Set db = Nothing werden Änderungen an diesem Feld nicht gespeichert kein Wunder, denn es ist ja auch nicht an ein Feld der Datenherkunft gebunden. Auch das ist kein Problem: Wir erstellen eine weitere Ereignisprozedur, die durch das Ereignis Nach Aktualisierung des Kombinationsfeldes cbostandardkostenstelleid ausgelöst wird. Diese Prozedur sieht wie in Listing 2 aus und führt im Wesentlichen zwei Aktualisierungsabfragen aus. Die erste stellt den Wert des Feldes IstStandard für alle Datensätze der Tabelle tblkostenstellen für den aktuellen Kunden auf False ein. Die zweite wiederum setzt den Wert für das gleiche Feld des soeben ausgewählten Datensatzes auf True. Damit wird der Wert genau wie in einem gebundenen Feld gespeichert. Vor- und Nachteile der beiden Varianten Die erste Variante erlaubt eine leichtere Handhabung des Standardwertes, da dieser ganz einfach aus der Tabelle tblkunden ausgelesen und dort auch angepasst werden kann. Diesbezüglich ist die zweite Variante etwas aufwendiger. Bei beiden Varianten kann es vorkommen, dass gar kein Eintrag der Tabelle tblkostenstellen als Standardwert für die Kostenstelle eines Kunden ausgewählt ist. Aber nur die zweite erlaubt es, gleichzeitig mehrere Kostenstellen auszuwählen. Dies lässt sich auf Access-Ebene auch nicht durch Einschränkungen über die Tabellendefinition verhindern also müssen Sie dies programmatorisch regeln, wie es bereits in der Ereignisprozedur cbo- StandardkostenstelleID_AfterUpdate geschehen ist. Der Nachteil der ersten Variante liegt im Datenmodell: Die beiden Tabellen tblkunden und tblkos tenstellen referenzieren sich dort gegenseitig. Sie müssen in einer solchen Konstellation darauf achten, die Löschweitergabe korrekt zu definieren. Wenn Sie für beide Beziehungen zwischen den Tabellen referenzielle Integrität und Löschweitergabe definieren und dann einen Eintrag der einen Tabelle löschen, ist dies nicht möglich es wird eine Sperrung bewirkt. Mit einseitiger Löschweitergabe ist dies kein Problem, hier ist jedoch gar keine Löschweitergabe angezeigt. Zusammenfassung und Ausblick Die Vergabe von Standardwerten für Felder ist oft hilfreich. Bei einfachen Werten wie dem aktuellen Datum oder der Uhrzeit gelingt dies unter Access reibungslos. Wenn Sie einem Feld einen Standardwert etwa auf Basis eines Feldes aus einer anderen Tabelle unterjubeln wollen, wird es bereits schwieriger dies gelingt nicht ohne Formularprogrammierung per VBA. Und wenn Sie auch noch Standardwerte für die aus anderen Tabellen ausgewählten Daten vergeben möchten, leidet die Übersicht nochmals. Dennoch wird früher oder später ein Kunde oder Benutzer mit einem solchen Wunsch an Sie herantreten. Dieser Beitrag liefert das notwendige Know-how, um Standardwerte für verschiedene Konstellationen bereitzustellen. 15

18 Formulare und Steuerelemente m:n-daten in einer Zeile anzeigen Die beiden Tabellen tblartikel und tblkategorien sind in der Südsturm-Beispieldatenbank eigentm:n-daten in einer Zeile anzeigen André Minhorst, Duisburg Für Daten mit einer m:n-beziehung gibt es einige Beispiele: Fahrzeuge und ihre Ausstattungsmerkmale, Artikel und Kategorien, Mitarbeiter und Positionen et cetera. Üblicherweise stellt man diese mit mehreren Steuerelementen dar etwa die Fahrzeuge im Hauptformular und die Ausstattung im Unterformular. Oder die Mitarbeiter landen im Hauptformular und zwei Listenfelder zeigen die zugeordneten und die nicht zugeordneten Abteilungen an. Was aber, wenn die Daten gar nicht bearbeitet, sondern nur angezeigt werden sollen und dies möglichst noch in einer einzigen Zeile? Dann hilft die Lösung aus diesem Beitrag weiter. Verknüpfte Daten nebeneinander Ziel des Beitrags ist es, eine Darstellung wie in Abb. 1 zu erhalten. Die ersten paar Spalten sollen die herkömmlichen Felder der m-tabelle der Verknüpfung liefern. Die folgenden Spalten sollen im Spaltenkopf den Inhalt und die Nummer anzeigen, also etwa Kategorie 1, Kategorie 2 et cetera. Darunter erscheinen schließlich die verknüpften Daten. Beispiel Artikel und Kategorien Zusammenfassung Erfahren Sie, wie Sie die Daten der n-seite einer m:n- Beziehung wahlweise per VBA oder mit einer Abfrage in Listenform anzeigen. Techniken Abfragen, VBA, Kreuztabellenabfragen Voraussetzungen Abb. 1: Darstellung von per m:n-beziehung verknüpften Daten in einer Zeile lich über das Fremdschlüsselfeld KategorieID der Tabelle tblartikel verknüpft. Auf diese Weise lässt sich aber nur je eine Kategorie je Artikel festlegen. Was aber, wenn Sie die Kategorien etwas verfeinern möchten und ein Artikel mehreren Kategorien zugeteilt werden soll? In diesem Fall benötigen wir eine m:n-verknüpfungstabelle, die alle denkbaren Kombinationen aus Artikeln und Kategorien speichern kann. Im Beziehungen-Fenster sieht dies wie in Abb. 2 aus; dort können Sie auch erkennen, dass wir das Feld KategorieID aus der Tabelle tblartikel entfernt haben. Access 2000 Beispieldateien mnliste.mdb Shortlink /884 Die Verknüpfungstabelle tblkategoriezuordnungen enthält drei Felder das Primärschlüsselfeld sowie zwei Fremdschlüsselfelder, welche beliebige Kombinationen aus den Datensätzen der Tabellen tblartikel und tblkategorien erlauben. Allerdings schränkt ein zusammengesetzter Index 16

19 m:n-daten in einer Zeile anzeigen Formulare und Steuerelemente über diese beiden Felder die Werte dahingehend ein, dass jede Kombination aus Artikel und Kategorie nur einmal vorkommen darf. Dazu legen Sie neben dem Primärindex einen weiteren Index an, der die betroffenen Felder enthält und dessen Eigenschaft Eindeutig auf Ja eingestellt wurde (s. Abb. 3). Abb. 2: m:n-beziehung zwischen Artikeln und Kategorien Sie können nun wie in Abb. 4 einige Beispieldatensätze für die Zuordnung von Artikeln zu Kategorien hinzufügen. Liste per VBA erzeugen Nun könnten Sie jedem Artikel per VBA eine entsprechende Liste der Kategorien hinzufügen diese müsste jedoch regelmäßig aktualisiert werden. Die Liste soll in der Tabelle tblartikel in einem weiteren Feld namens Kategorien gespeichert werden. Die VBA-Prozedur zum Füllen dieses Feldes sieht wie in Listing 1 aus. Die Prozedur legen Sie in einem beliebigen Standardmodul an und starten diese nach dem Platzieren der Einfügemarke innerhalb der Prozedur mit der Taste F5. Wenn Sie die Prozedur beispielsweise immer dann verwenden wollen, bevor die Artikeldaten in einem Formular angezeigt werden, rufen Sie es in der Ereignisprozedur auf, die durch das Ereignis Beim Laden des Formulars ausgelöst wird. Abb. 3: Jede Kombination aus Artikel und Kategorie ist nur einmal möglich. Die Prozedur erstellt zunächst ein Recordset auf Basis der Tabelle tblartikel. Per Do While durchläuft die Prozedur alle Datensätze der Tabelle tbl- Artikel in einer äußeren Schleife. Innerhalb dieser Schleife erzeugt die Prozedur eine weitere Datensatzgruppe, die diesmal alle Datensätze der verknüpften Tabellen tblkategoriezuordnungen und tblkategorien enthält, bei Die Prozedur selbst ist die einfachste Variante, um zum gewünschten Ergebnis zu kommen. Allerdings birgt das Ergebnis auch den Nachteil redundanter Daten in sich. Sobald einer der Artikel einer weiteren Kategorie zugeordnet wird oder eine Zuordnung entfällt, stimmen die Daten im Feld Kategorien nicht mehr. Abb. 4: Beispieldatensätze für die m:n-beziehung 17

20 Formulare und Steuerelemente m:n-daten in einer Zeile anzeigen Listing 1: Zusammenstellen der Kategorienliste per VBA Public Sub KategorielisteSchreiben() Dim db As DAO.Database Dim rstartikel As DAO.Recordset Dim rstkategorien As DAO.Recordset Dim strkategorien As String Set db = CurrentDb Set rstartikel = db.openrecordset("select * FROM tblartikel", dbopendynaset) Do While Not rstartikel.eof strkategorien = "" Set rstkategorien = db.openrecordset("select t2.kategoriename FROM µ tblkategoriezuordnungen AS t1 INNER JOIN tblkategorien AS t2 ON t1.kategorieid = µ t2.kategorieid WHERE t1.artikelid = " & rstartikel!artikelid, dbopendynaset) Do While Not rstkategorien.eof strkategorien = strkategorien & ";" & rstkategorien!kategoriename rstkategorien.movenext Loop If Len(strKategorien) > 0 Then strkategorien = Mid(strKategorien, 2) End If With rstartikel.edit!kategorien = strkategorien.update End With rstartikel.movenext Loop Set db = Nothing denen das Feld ArtikelID mit der ID des aktuell in der äußeren Schleife bearbeiteten Artikel- Datensatzes übereinstimmt. Auch die Datensätze dieses Recordsets werden innerhalb einer Do While-Schleife durchlaufen. Dabei stellt die Prozedur in der Stringvariablen strkategorien eine per Semikola getrennte Liste der Kategorienamen zusammen. Dabei wird mit jedem Durchlauf ein Ausdruck wie ;<Kategoriename> zur Zeichenkette in strkategorien hinzugefügt. Sollte diese zumindest eine Kategorie enthalten, muss natürlich noch das führende Semikolon entfernt werden, was eine entsprechende Anweisung mit der Mid-Funktion erledigt. Schließlich trägt die Prozedur die Kategorienliste in das Feld Kategorien des aktuellen Datensatzes des Recordsets rstartikel ein. Das Ergebnis können Sie in Abb. 5 begutachten. Alle Datensätze der Tabelle tblartikel enthalten im Feld Kategorien einen oder mehrere durch Semikola getrennte Kategorienamen. Kategorieliste per Abfrage Die fehlende Dynamik der Zusammenstellung der Kategorieliste per VBA stellt uns noch nicht ganz zufrieden. Gibt es denn keine Möglichkeit, eine solche Liste immer aktuell zu halten, ohne jedes Mal eine Prozedur aufrufen zu müssen? Klar: Wenn Sie etwa mit dem SQL Server arbeiten, können Sie einen Trigger einsetzen, der Änderungen in der Tabelle tblkategoriezuordnungen direkt in das Feld Kategorien der Tabelle tblartikel überträgt. Allerdings verwendet ja längst nicht jede Access- Datenbank ein SQL Server-Backend. Also suchen 18

21 m:n-daten in einer Zeile anzeigen Formulare und Steuerelemente Wir benötigen also eine Darstellung, deren erste beiden Felder etwa ArtikelID und Artikelname anzeigen. Die übrigen Spalten soll die Kreuztabelle mit den Überschriften Kategorie 1, Kategorie 2 und so weiter füllen. Erster Schritt: Basisabfrage erstellen Abb. 5: Tabelle mit der Kategorienliste im Feld Kategorien wir nach einer alternativen Lösung, zum Beispiel einer Abfrage. Im ersten Schritt wollen wir eine Abfrage erhalten, die für eine bestimmte Anzahl von Kategorien je Artikel vorbereitet ist sagen wir für zehn Stück. Die Abfrage sollte also in zehn Feldern mit den Namen Kategorie 1, Kategorie 2 und so weiter die dem Artikel zugewiesenen Kategorien anzeigen. Wenn ein Artikel keine zehn Kategorien aufweist, bleiben die hinteren Kategorie-Felder einfach leer. Im zweiten Schritt wandeln wir die resultierende Abfrage so um, dass Sie genau die gleiche Darstellung wie in der obigen Lösung mit der per VBA zusammengestellten Kategorienliste erhalten! Die Lösung: Eine Kreuztabellenabfrage Der Weg zur Lösung dieser Aufgabe bestand größtenteils darin, eine Möglichkeit zu finden, um die zugewiesenen Kategorien den entsprechenden Feldnamen, also Kategorie 1, Kategorie 2 und so weiter zuzuweisen. Wir brauchen also eine Abfrage, die je nach Anforderung beliebig viele Kategoriefelder zum Abfrageentwurf hinzufügt. Die Lösung fiel leicht, da es überhaupt nur eine solche Möglichkeit gibt nämlich die Kreuztabellenabfrage. Sie erlaubt es, die Werte eines Feldes der Datenherkunft als Spaltenüberschriften zu verwenden neben einer oder mehreren echten Spaltenüberschriften. Dummerweise enthält aber keine der Tabellen tblartikel, tblkategoriezuordnungen oder tblkategorien ein Feld namens Kategorie 1. Wir benötigen aber eine Datenherkunft, welche sowohl einen Verweis auf den Artikeldatensatz und auf die jeweilige Kategorie liefert und gleichzeitig noch ein Feld mit den Werten Kategorie 1, Kategorie 2 et cetera füllt. Hier kommt eigentlich nur eine Abfrage auf Basis der Verknüpfungstabelle tblkategoriezuordnungen infrage, die in der Datenblattansicht wie in Abb. 6 aussieht. Wie aber erhalten wir ein Feld namens Kategorienummer, dessen Werte genau für jede Kombination aus Artikel und Kategorie von 1 bis n durchnummeriert sind? Das Rätsel lüftet ein Blick auf den Entwurf dieser Abfrage (s. Abb. 7). Diese fügt dem Entwurfsraster neben den drei Feldern der Tabelle tblkategoriezuordnungen noch ein weiteres Feld namens Kategorienummer hinzu, dessen Ausdruck wie folgt aussieht: Kategorienummer: "Kategorie " & DomAnzahl( "KategorieZuordnungID";"tblKategoriezuordnungen"; "KategorieZuordnungID<=" & [KategorieZuordnungID] & " AND ArtikelID = " & [ArtikelID]) Was bewirkt dieser Ausdruck nun? Er ermittelt die Anzahl aller Einträge der Tabelle tblkategoriezuordnungen, deren Feld ArtikelID den gleichen Wert enthält wie der aktuelle Datensatz und dessen Primärschlüsselfeld einen Wert enthält, der kleiner oder gleich dem Primärschlüsselfeld des aktuellen Datensatzes ist. Wenn der Artikel Chai beispielsweise drei Kategorien zugeordnet ist, dann durchläuft Access beim Ermitteln des Abfrageergebnisses die drei Daten- 19

22 Formulare und Steuerelemente m:n-daten in einer Zeile anzeigen Abb. 6: Basisabfrage für die Kreuztabelle sätze in der angegebene Sortierreihenfolge hier nach dem Primärschlüsselwert. Der erste Wert im Feld KategoriezuordnungID lautet 1. Es gibt in der Tabelle tblkategoriezuordnungen genau einen Wert, der kleiner oder gleich 1 ist und die gleiche ArtikelID aufweist also ist die Anzahl 1. Beim zweiten Datensatz mit dem Wert 2 im Feld KategoriezuordnungID findet die DomAnzahl- Funktion genau zwei passende Datensätze den mit dem Wert 1 und den mit dem Wert 2 im Primärschlüsselfeld. Dieser Nummerierung stellt die Abfrage noch den Ausdruck Kategorie voran, sodass Texte wie Kategorie 1, Kategorie 2 und so weiter entstehen. Die Nummerierung beginnt dabei für jeden Artikel von vorn. Kreuztabelle erzeugen Nun liegt die gewünschte Datenherkunft vor. Nun wollen wir eine Kreuztabelle erstellen, deren Ergebnis beispielsweise wie in Abb. 8 aussieht. Dort finden Sie jeweils die Werte der Felder ArtikelID und Artikelname plus die jeweils zugeordneten Kategorien. Welche Informationen benötigen wir außer den durch die Abfrage qrykategoriezuordnungen- MitKategorienummer gelieferten Daten? Diese liefert beispielsweise nur die Fremdschlüsselfelder zu den Tabellen tblartikel und dem Feld Abb. 7: Entwurfsansicht der Abfrage qrykategoriezuordnungenmitkategorienummer 20

23 m:n-daten in einer Zeile anzeigen Formulare und Steuerelemente Abb. 8: Das gewünschte Aussehen der Kreuztabellenabfrage Artikelname sowie der Tabelle tblkategorien und dem Feld Kategoriename. Da aber sowohl der Artikelname als auch der Kategoriename in der Kreuztabelle angezeigt werden sollen, fügen wir noch die beiden Tabellen tblartikel und tbl- Kategorien zum Entwurf hinzu. Anschließend wandeln Sie die Abfrage mit dem Kontextmenü-Eintrag Abfragetyp Kreuztabellenabfrage in eine Kreuztabelle um. Die Kreuztabelle erwartet nun drei verschiedene Datenarten, die Sie durch Auswahl eines der Einträge in der Zeile Kreuztabelle festlegen: Zeilenüberschriften: Dies sind die Felder der Tabelle, die wie in einer normalen Tabelle dargestellt werden. In diesem Fall sollen ArtikelID und Artikelname diese Aufgabe übernehmen. Spaltenüberschriften: Die ersten Spaltenüberschriften liefern die Namen der als Zeilenüberschriften festgelegten Felder der Datenherkunft. Die folgenden werden dynamisch aus einem Feld der Datenherkunft gewählt. Wir möchten die Einträge Kategorie 1, Kategorie 2 und so weiter als Spaltenüberschriften verwenden, also wählen wir das Feld Kategorienummer der soeben erstellten Abfrage qry- Ka te go rie zuordnungenmitkategorie nummer aus. Fehlen noch die Daten, die unterhalb der dynamisch gelieferten Spaltenüberschriften erscheinen. Hier sollen die Kategorienamen erscheinen. Wie aber kann eine der in der Zeile Funktion zur Verfügung stehenden Aggregatfunktionen genau den Kategorienamen für die entsprechende Spalte liefern und gelingt dies überhaupt? Wer auf Ausdruck tippt, liegt falsch. Es gelingt ganz einfach mit der Funktion ErsterWert. Es gibt ohnehin nur einen Wert, also liefert ErsterWert den richtigen Kategorienamen (s. Abb. 9). Abb. 9: Entwurf der Kreuztabelle 21

24 Formulare und Steuerelemente m:n-daten in einer Zeile anzeigen Fertig auf diese Weise haben wir eine Kreuztabelle erstellt, die alle zugewiesenen Kategorien ausgibt. Und als zusätzliches Bonbon zeigt die Abfrage sogar noch nicht einmal unnötige dynamische Spaltenüberschriften an wenn Sie den Artikeln maximal drei Kategorien zugeordnet haben, dann erscheinen auch nur die drei Spalten Kategorie 1, Kategorie 2 und Kategorie 3. Abfrage perfektionieren Nun hatten wir aber den Wunsch, die Kategorien nicht in einzelnen Spalten, sondern in einer durch Semikola separierten Liste darzustellen. Wir möchten also beispielsweise aus den Inhalten der drei Spalten Kategorie 1, Kategorie 2 und Kategorie 3 einen Ausdruck wie <Kategorie1> ;<Kategorie2>;<Kategorie3> machen oder, wenn nur eine oder zwei Kategorien zugeordnet wurden, einen Ausdruck wie <Kategorie1> oder <Kategorie1>;<Kategorie2>. Auch wenn es in der Praxis selten geschieht: Natürlich können Sie eine Abfrage auf Basis einer Kreuztabellenabfrage erstellen. In diesem Fall ziehen Sie einfach die soeben erstellte Kreuztabelle in den Entwurf einer neuen Abfrage (s. Abb. 10). Diese liefert Kategorie x-spalten entsprechend der maximalen Anzahl der aktuell vorhandenen Kategorien je Artikel. Im Ausdruck Kategorien fügen wir die vier Felder [Kategorie 1], [Kategorie 2], [Kategorie 3] und [Kategorie 4] mit entsprechenden Semikola zwischen den Feldern zum gewünschten Ausdruck zusammen. Dummerweise liefert dies nicht das gewünschte Ergebnis dieses sieht nämlich etwa so aus: Getränke;Gewürze;Naturprodukte; Getränke;;; Getränke;Milchprodukte;Naturprodukte;Gewürze Gewürze;Milchprodukte;; Gewürze;;; Gewürze;Meeresfrüchte;Naturprodukte; Je nach der Anzahl der tatsächlich vorhandenen Kategorien bleiben also hinten eines oder mehrere Semikola übrig. Dieses Problem ist einfach zu lösen. Neben dem Und-Operator gibt es nämlich auch noch den Plus-Operator zum Verknüpfen zweier Zeichenketten. Dies unterscheidet sich dahingehend, dass zwei mit Plus verknüpfte Ausdrücke den Wert Null liefern, wenn nur einer der Ausdrücke Null ist. Wenn das Feld Kategorie 2 also leer ist, würde ";" + [Kategorie 2] den Wert Null liefern. Folgender Ausdruck lässt also keine Semikola übrig: Kategorien: [Kategorie 1] & ";"+[Kategorie 2] & ";"+[Kategorie 3] & ";"+[Kategorie 4] Nun haben wir aber immer noch ein kleines Problem: Die Abfrage ist nämlich genau auf vier Ka- Abb. 10: Abfrage auf Basis der Kreuztabellenabfrage 22

25 m:n-daten in einer Zeile anzeigen Formulare und Steuerelemente tegorien ausgelegt. Weniger Kategorien werden zwar auch angezeigt, aber nicht mehr. Sollte also nun eine fünfte Kategorie zu einem Artikel hinzugefügt werden, erscheint diese nicht in der Liste der Kategorien des Abfrageergebnisses. Die schlechte Nachricht ist: Wir müssen uns auf eine Obergrenze festlegen. Die gute lautet: Diese kann durchaus höher sein als die aktuelle maximale Anzahl Kategorien eines Artikels. In der folgenden Erweiterung gehen wir davon aus, dass zehn Kategorien je Artikel ausreichen. Dazu gehen wir noch einmal zum Entwurf der Kreuztabellenabfrage zurück. Klicken Sie in den grauen Bereich im oberen Teil des Abfrageentwurfs, um die Abfrageeigenschaften anzuzeigen. Hier legen Sie für die Eigenschaft Fixierte Spaltenüberschriften den folgenden Ausdruck fest (siehe auch Abb. 11): "Kategorie 1";"Kategorie 2";"Kategorie 3";"Kategorie 4";"Kategorie 5";"Kategorie 6";"Kategorie 7";"Kategorie 8";"Kategorie 9";"Kategorie 10" Abb. 11: Festlegen der Anzahl der maximal angezeigten Kategorien Die Kreuztabellenabfrage zeigt nun immer alle zehn Spalten an auch, wenn keiner der Artikel zehn Kategorien zugewiesen ist. Das ist aber kein Problem wir wollen ja schließlich eine Liste der Kategorien. Der Entwurf der Abfrage qryartikelmitkategorienliste stellt nun in der Feldliste der Datenherkunft qryartikelmitallenkategorien zehn Kategoriefelder zur Verfügung (s. Abb. 12). Diese refenzieren wir sämtlich im Ausdruck für das Feld Kategorien: Kategorien: [Kategorie 1] & ";"+[Kategorie 2] & ";"+[Kategorie 3] & ";"+[Kategorie 4] & ";"+[Kategorie 5] & ";"+[Kategorie 6] & ";"+[Kategorie 7] & ";"+[Kategorie 8] & ";"+[Kategorie 9] & ";"+[Kategorie 10] Zusammenfassung und Ausblick Fertig wir haben eine Abfrage erzeugt, welche die per m:n-beziehung zu einem Artikel zugewiesenen Kategorien in einer Liste anzeigt. Sie haben außerdem erfahren, wie Sie die gleiche Lösung per VBA erreichen mit dem Nachteil, dass hier in regelmäßigen Abständen eine Aktualisierung der Kategorielisten erforderlich ist. Abb. 12: Datenherkunft mit allen Kategorie x-feldern 23

26 Formulare und Steuerelemente Flexible Bestellungen: Formulare Flexible Bestellungen: Formulare André Minhorst, Duisburg Die flexible Handhabung von Bestellungen, Lieferungen und Rechnungen basiert auf einem ausgefeilten Datenmodell. Genauso wichtig ist die Bereitstellung einer Benutzeroberfläche, die alle Möglichkeiten des Datenmodells ausschöpft. In diesem Beitrag lernen Sie die Formulare kennen, die das Aufnehmen von Bestellungen nach Kunde und Kostenstelle, die Erfassung von Lieferungen und die flexible Erstellung von Rechnungen erlauben. Im Beitrag Flexible Bestellungen: Datenmodell (/882)haben wir das Datenmodell einer einfachen Bestellverwaltung, nämlich der Südsturm-Datenbank, so erweitert, dass Sie damit neben den eigentlichen Bestelldaten einige weitere Daten erfassen können: Alle Kostenstellen eines Kunden Kostenstelle für jede Bestellposition Lieferungen Lieferpositionen Rechnungen Rechnungspositionen Diese Daten werden so in Tabellen abgelegt, dass Lieferungen und Rechnungen recht flexibel verarbeitet werden können. Wenn Sie das Datenmodell Zusammenfassung Erfahren Sie, wie Sie flexible Liefer- und Rechnungspositionen mit Formularen verwalten. Techniken Formulare Voraussetzungen Access 2000 und höher Beispieldateien FlexibleBestellungen.mdb Shortlink /885 aufgestellt haben, steht das Fundament es liegt jedoch noch einige Arbeit vor Ihnen. Wir gehen einmal davon aus, dass wir ein herkömmliches Formular zur Erfassung der Bestellungen verwenden. Dieses wollen wir an dieser Stelle nicht näher beschreiben, sondern uns gleich auf die übrigen Formulare stürzen, mit denen Sie die Lieferungen und die Rechnungsstellung organisieren. Der Optimalfall Im besten Fall liegen immer alle bestellbaren Artikel in ausreichender Anzahl vor. Wenn Sie eine Anwendung programmieren, die diesen Fall abdecken soll, sind Sie quasi bereits fertig Sie können die Lieferscheine und die Rechnungen direkt aus den Bestelldaten füllen und verarbeiten. Nun kommen einige von Ihnen und sagen: Diesen Optimalfall kann es nicht geben! Niemand kann voraussehen, ob nicht irgendein Wahnsinniger auf einmal Tausende von Exemplaren eines bestimmten, schlecht lagerbaren Artikels bestellt! Doch, das geht! Haben Sie mal mit Downloadartikeln wie ebooks oder Software gehandelt? Sie sehen: Nichts ist unmöglich. Wir wollen uns aber nicht auf diesen (nicht mehr allzu seltenen) Fall reduzieren, sondern etwas schaffen, mit dem auch die übrigen Menschen etwas anfangen können. Wenn das Regal leer ist In diesem Fall kommt früher oder später eine Bestellung, die nicht sofort komplett beliefert werden kann, weil Artikel nicht mehr in ausreichender Zahl vorrätig sind. Dies kann man auch 24

27 Flexible Bestellungen: Formulare Formulare und Steuerelemente durch eine sorgfältige Pflege der verfügbaren Artikel nicht gewährleisten. Mittlerweile hängen so viele Abnehmer wie Onlineshop, Telefonverkauf, ebay et cetera an einer Warenwirtschaft, dass es sich kaum verhindern lässt, dass ein Artikel einmal mehr verkauft wird als er vorhanden ist. Doch das soll kein Problem sein: Zwar ist es für einen Kunden ärgerlich, wenn er den gewünschten Artikel nicht in der angegebenen Zeit erhält, aber besser etwas später als gar nicht. Also sehen wir in der Anwendung die Möglichkeit vor, dass eine Bestellung nicht vollständig geliefert werden kann. Gleichzeitig sollten wir den Fall abfangen, dass ein Kunde zwei oder mehr Bestellungen aufgibt, die in einer einzigen Lieferung durchgeführt werden können. Beim Zusammenstellen der Lieferungen betrachten wir also nicht die Bestellung eines Kunden, sondern alle bestellten und offenen Bestellungen dieses Kunden. Dabei kann es natürlich auch sein, dass ein Kunde an einem Tag eine Bestellung durchführt, die bis auf eine Position auch versendet wird. Am nächsten Tag bestellt er erneut etwas. Praktischerweise soll der fehlende Artikel vom Vortag direkt mit dieser Sendung verschickt werden. Von der Bestellposition zur Lieferposition Um dies zu erledigen, brauchen wir ein Formular, das alle offenen Bestellpositionen eines Kunden anzeigt und diese zur Übernahme in einer Lieferung anbietet. Dazu benötigen wir zumindest eine Liste aller offenen Bestellpositionen. Wie verarbeiten wir diese dann weiter? Es wären beispielsweise folgende Optionen denkbar: Die Positionen werden in einem Unterformular in der Datenblattansicht aufgelistet und mit einem zusätzlichen Steuerelement versehen, mit dem die zu liefernden Positionen markiert werden können. Wir verwenden zwei Listenfelder, wobei die Einträge der Tabelle tblbestellpositionen in einer Liste angezeigt werden und die zu liefernden Positionen in die andere Liste gezogen werden. Man könnte auch zwei Unterformulare (oben für die bestellten Artikel, unten für die zu liefernden Artikel) verwenden, wobei die Einträge des oberen per Doppelklick zum unteren Unterformular hinzugefügt werden. Weiter hinten schauen wir uns an, wie die dritte Lösung umgesetzt wird. Sie erlaubt es gleichzeitig, die Anzahl der bestellten und der zu liefernden Artikel anzuzeigen und per bedingter Formatierung Fehlmengen farbig hervorzuheben. Rechnungen erstellen Schließlich sollen noch die Rechnungen erstellt werden. Dies erfolgt auf Basis der gelieferten Artikel. Diese werden ja komplett in der Tabelle tbl- Lieferpositionen gespeichert, die über die Tabelle tbllieferungen weitere Informationen über den Lieferzeitpunkt referenziert. Ein Formular soll nun alle noch nicht bezahlten Lieferpositionen eines Kunden anzeigen und deren Auswahl für die Zusammenstellung der Rechnungspositionen erlauben. Auch dieses Formular sehen wir uns weiter unten im Detail an. Formular zum Zusammenstellen von Lieferungen Das Formular frmlieferungen zeigt die einzelnen Lieferungsdatensätze an und enthält zwei Unterformulare. Das erste Unterformular heißt frmbestellpositionenoffen und soll alle Einträge der Tabelle tblpositionen anzeigen, die noch nicht oder noch nicht vollständig geliefert wurden. Das bedeutet, dass wir alle Datensätze der Tabelle tbllieferpositionen heranziehen müssen, deren Feld PositionID die jeweilige Bestellposition referenziert, und deren Mengen vergleichen. Ist die Menge der gelieferten Artikel geringer als die bestellte, soll das Formular den Eintrag der Tabelle tblpositionen anzeigen. Das zweite Unterformular heißt frmlieferpositionen und zeigt alle zur aktuellen Lieferung gehörenden Datensätze an. Der Aufbau des Formulars soll zunächst wie in Abb. 1 aussehen, um die betroffenen Daten überhaupt darzustellen. 25

28 Formulare und Steuerelemente Flexible Bestellungen: Formulare als vollständig ausgeliefert gekennzeichnet sind. Dazu eine kurze Erläuterung des Datenmodells: Dort gibt es neben der üblichen Tabelle zur Erfassung der Bestellpositionen, tblpositionen, eine ähnliche Tabelle zur Eingabe der Lieferpositionen einer Lieferung (tbllieferpositionen). Abb. 1: Erster Entwurf des Formulars frmlieferungen mit den zu liefernden und den in der aktuellen Lieferung enthaltenen Datensätzen Diese referenziert direkt Bestellpositionen in der Tabelle tblpositionen und gibt an, wie viele der dort aufgeführten Mengen die Lieferung enthält. Es kann also mehrere Lieferpositionen zu einer Bestellposition geben. Erst wenn die Summe der in jeder Lieferposition angegebenen Menge von Artikeln gleich der Menge der bestellten Artikel ist, soll die Bestellposition nicht mehr im oberen Unterformular angezeigt werden. Später legen wir Steuerelemente an, mit denen die Bestellpositionen leicht in die Lieferpositionen übertragen werden können. Das Hauptformular frmlieferungen Das Hauptformular frmlieferungen ist an die Tabelle tbllieferungen gebunden und zeigt alle Felder dieser Tabelle im oberen Abschnitt des Detailbereichs an. Das Formular dient zum Anlegen neuer Lieferungen, kann aber auch zum Ansehen und Bearbeiten vorhandener Lieferungen dienen. Das Unterformular sfmbestellpositionenoffen Das oberste Unterformular des Hauptformulars frmlieferungen soll alle offenen Bestellpositionen für den im Hauptformular ausgewählten Kunden anzeigen. Die Hauptaufgabe besteht nun darin, eine geeignete Datenherkunft für das Formular zu ermitteln. Diese soll alle Datensätze der Tabelle tblpositionen liefern, die noch nicht durch entsprechende Datensätze in der Tabelle tbllieferpositionen Die benötigte Abfrage muss also die Summe der Menge der Artikel aller Lieferpositionen zusammenfassen, die sich auf eine Bestellposition beziehen, und prüfen, ob deren Menge noch kleiner als die bestellte Menge ist. Dazu verwenden wir eine Abfrage mit einer Gruppierung. Diese sieht im Entwurf wie in Abb. 2 aus und enthält die drei Tabellen tblbestellungen, tblpositionen und tbllieferpositionen. Aus der Tabelle tblbestellungen bezieht die Abfrage das Bestelldatum sowie das Feld KundeID. Über dieses wollen wir später alle Datensätze zu einem bestimmten Kunden ermitteln. Die Tabelle tbl- Positionen liefert die Felder PositionID, Artikel- ID und Menge. Aus tbllieferpositionen stammt schließlich das Feld Menge. Nun kann es sein, dass die Tabelle tbllieferpositionen keinen, einen oder mehrere Datensätze zu den in der Tabelle tblpositionen enthaltenen Bestellpositionen enthält. Wenn keine Lieferposition vorliegt, geschieht ohne weitere Vorkehrungen Folgendes: Die Abfra- 26

29 Flexible Bestellungen: Formulare Formulare und Steuerelemente Abb. 2: Formular zur Ermittlung der Summen der gelieferten Artikel zu einer Bestellposition ge liefert keinen Datensatz zurück, da sie nur solche Daten anzeigt, für die in allen als Datenherkunft dienenden Tabellen Daten enthalten sind. Damit fielen aber gerade solche Bestellpositionen weg, die noch nicht geliefert wurden was nicht gerade das Ziel dieser Abfrage ist. Damit es keine Rolle spielt, ob es bereits Lieferungen zu einer Bestellposition gibt oder nicht, passen wir also wie in der Abbildung die Verknüpfungseigenschaften für die Beziehung zwischen den Tabellen tblpositionen und tblbestellpositionen an. Auf diese Weise bleibt das Feld GelieferteMenge der Abfrage schlicht leer, wenn kein passender Datensatz in der Tabelle tbllieferpositionen vorliegt. Der zweite Fall ist, dass es genau eine Lieferung für eine Bestellposition gibt. Das ist der Optimalfall: Bei der Lieferung wurde die gewünschte Menge Artikel berücksichtigt, das Feld Menge enthält in beiden Tabellen den gleichen Wert. Dummerweise erfolgen Lieferungen auch einzelner Bestellpositionen in mehreren Rutschen, sodass wir die Menge aller zu einer Bestellposition gehörenden Lieferpositionen summieren müssen. Und damit kommen wir zum Sinn einer Gruppierung in der Abfrage. Richten Sie diese ein, beispielsweise mit dem Eintrag Summen des Kontextmenüs des Abfrage-Entwurfsrasters, und legen Sie für das Feld GelieferteMenge in der Zeile Funktion den Wert Summe und in allen anderen Feldern den Wert Gruppierung fest. Abb. 3: Beispieldaten für die Tabelle tbllieferpositionen Angenommen, die Tabelle tbllieferpositionen ent hält einige manuell hinzugefügte Datensätze wie in Abb. 3 (analog haben wir zuvor einen passenden Datensatz in der Tabelle tbllieferungen angelegt). Dort wird mit dem Feld BestellpositionID die Bestellposition referenziert, auf die sich die unter Menge angegebene Anzahl gelieferter Artikel bezieht. In der Abfrage qrysfmbestellpositionenoffen- Base sollten dann die Anzahlen der bestellten und der gelieferten Artikel gegenübergestellt werden. Und genau so funktioniert es, wie Abb. 4 zeigt. Dort erscheint genau für die drei Artikel, deren Lieferung wir manuell in die Tabelle tbllieferpositionen eingetragen haben, je ein Datensatz. Abfrage der Abfrage Das entspricht allerdings noch nicht vollständig dem gewünschten Ergebnis: Wir wollten ja nur diejenigen Bestellpositionen erhalten, deren Lieferung noch nicht vollständig ausgeführt wurde. Also fügen wir zum Feld BestellteMenge noch ein Kriterium hinzu, das in der bereits mit GROUP 27

30 Formulare und Steuerelemente Flexible Bestellungen: Formulare Abb. 4: Anzeige der bestellten und der gelieferten Menge Artikel in der Datenherkunft eines Unterformulars BY versehenen Abfrage als HAVING-Bedingung integriert wird: >Nz(Summe([tblLieferpositionen].[Menge]);0) Damit erhalten wir das gewünschte Ergebnis die oberen beiden Datensätze der Abbildung verschwinden. Das Unterformular sfmlieferpositionen soll alle bereits zur im Hauptformular angezeigten Lieferung gelieferten Artikel auflisten. Die Datenherkunft des Formulars soll die LieferpositionID, das Bestelldatum, den Artikel und die gelieferte Menge als anzuzeigende Werte zurückgeben. Außerdem benötigen wir im Unterformular noch das Feld LieferungID, um nur die Lieferpositionen zur aktuellen Lieferung des Hauptformulars herauszufiltern. Die Abfrage enthält die drei verknüpften Tabellen tblbestellungen (für das Bestelldatum), tblbestellpositionen und tbllieferpositionen (s. Abb. 5). In den Detailbereich des Unterformulars nehmen Sie die Felder wie in Abb. 6 auf und schließen das Unterformular. Unterformular zur Anzeige der aktuellen Lieferpositionen Haupt- und Unterformulare zusammenführen Folgt der interessanteste Schritt: Das Einfügen der Unterformulare in das Hauptformular. Öffnen Sie das Hauptformular frmlieferungen in der Entwurfsansicht und ziehen Sie die beiden Unterformulare sfmlieferpositionenoffen und sfmlieferpositionen untereinander in den Detailbereich des Formulars. Ein Wechsel in die Formularansicht zeigt, dass das Unterformular sfmlieferpositionenoffen noch Abb. 5: Datenherkunft des Unterformulars zur Anzeige der erledigten Lieferpositionen einer Lieferung 28

31 Flexible Bestellungen: Formulare Formulare und Steuerelemente Abb. 6: Unterformular zur Anzeige der erledigten Lieferpositionen nicht mit dem Hauptformular synchronisiert wird normalerweise füllt Access die beiden Eigenschaften Verknüpfen von und Verknüpfen nach des Unterformular-Steuerelements automatisch, wenn es eine Beziehung zwischen den Daten aus Haupt- und Unterformular erkennt. Ein Wechseln in die Formularansicht zeigt anhand der wenigen Beispieldatensätze in den Tabellen tbllieferungen und tbllieferpositionen, dass beide Formulare die gewünschten Daten anzeigen (s. Abb. 8). Im oberen Formular erscheinen alle bestellten, aber noch nicht vollständig gelieferten Positionen und das gefiltert nach den Bestellungen des aktuellen Kunden. Das untere Formular zeigt alle bereits vollständig gelieferten Positionen an. Teilweise gelieferte Positionen erscheinen in beiden Listen, wobei oben die gesamte Bestellmenge und die bereits gelieferte Menge angezeigt werden. Neue Lieferung anlegen Dies ist in diesem Fall nicht möglich es gibt keine gemeinsamen Felder. Das Unterformular soll alle anstehenden Lieferpositionen für den Kunden der Lieferung im Hauptformular anzeigen. Also stellen Sie die entsprechenden Eigenschaften wie in Abb. 7 jeweils auf das Feld KundeID ein. Beim Hinzufügen des Unterformulars sfmlieferpositionen hat es Access einfacher: Die Daten des Unterformulars sind über das Feld LieferungID mit dem gleichnamigen Feld des Hauptformulars verknüpft, also wird dieses automatisch für die Verknüpfungseigenschaften festgelegt. Wenn Sie einen neuen Datensatz der Tabelle tbl- Lieferungen im Hauptformular anzeigen, bleiben beide Unterformulare leer. Dies ändert sich erst, wenn Sie einen Wert für das Feld KundeID im Hauptformular auswählen. Das Unterformular sfmlieferpositionenoffen zeigt dann alle Lieferpositionen zur neuen Bestellung an. Nun benötigen wir nur noch eine einfache Methode, um die Positionen dieser Lieferung festzulegen. Eine Idee wäre, einfach die Anzahl der zu liefernden Artikel in das Feld Geliefert des oberen Unterformulars einzutragen. Dummerweise basiert dieses Unterformular jedoch auf einer gruppierten Abfrage, die keine Aktualisierung zulässt. Abb. 7: Herstellen der Synchronisierung zwischen Hauptund Unterformular 29

32 Formulare und Steuerelemente Flexible Bestellungen: Formulare Der Benutzer klickt einfach auf den Bestelldatensatz, um einen einzigen Artikel, und doppelt, um alle Artikel zur Lieferliste hinzuzufügen. Wir stellen für jede Zeile zwei Schaltflächen bereit, mit welcher der Benutzer einen oder alle Artikel der aktuellen Bestellpositionen zur Lieferung hinzufügen kann. Der erste Vorschlag bedeutet je nach Anzahl der Bestellpositionen eine Menge Mausbewegungen. Der zweite ist gut, allerdings wenig intuitiv. Der dritte ist optimal, aber schwer umzusetzen. Wie soll man Schaltflächen in der Datenblattansicht unterbringen? Per Schaltfläche liefern Abb. 8: Haupt- und Unterformular arbeiten wie gewünscht. Lieferung bearbeiten Nun fehlt nur noch eine entscheidende Funktion nämlich die zum Hinzufügen der bestellten Positionen zu den gelieferten Positionen. Dabei ist zu berücksichtigen, dass entweder alle oder eine bestimmte Anzahl der Artikel einer Bestellposition in eine Lieferung aufgenommen werden können. Da diese Funktion für jeden Artikel einzeln angeboten werden soll, gibt es folgende Möglichkeiten: Wir probieren es dennoch auch wenn absehbar ist, dass das Ergebnis eher zweckorientiert als hübsch aussehen wird. Statt Schaltflächen soll jeder Eintrag des oberen Formulars am Ende einmal ein Feld mit dem Wert + und einmal mit dem Wert ++ enthalten. Damit dies für jeden Datensatz gelingt, müssen wir diese Zeichenketten in die als Datenherkunft verwendete Abfrage integrieren. Dies erledigen Sie, indem Sie die Abfrage qrysfmbestellpositi- Der Benutzer markiert die zu bearbeitende Bestellposition und klickt dann auf eine Schaltfläche zum Hinzufügen zur Lieferliste. Abb. 9: Datenherkunft zur Anzeige von + und ++ anpassen 30

33 Flexible Bestellungen: Formulare Formulare und Steuerelemente onenoffnen wie in Abb. 9 anpassen. Fügen Sie einfach zwei Felder hinzu, welche die folgenden Ausdrücke enthalten: PlusEins: "+" PlusAlle: "++" Diese beiden Felder müssen Sie natürlich auch zum Detailbereich des Unterformulars sfmbestellpositionenoffen hinzufügen. Damit als Spaltenüberschrift ebenfalls die Zeichenketten + und ++ erscheinen, stellen Sie die Bezeichnungsfelder im Entwurf des Unterformulars wie in Abb. 10 ein. Abb. 10: Hinzufügen der Schaltflächen zum Unterformular Diese als Schaltflächenersatz angelegten Textfelder erscheinen, wenn Sie die Ausrichtung zentrieren, wie in Abb. 11. Nun soll die erste Schaltfläche (+) eines jeden Datensatzes dafür sorgen, dass ein Artikel der aktuellen Bestellposition zu einer bestehenden oder noch anzulegenden Lieferposition hinzugefügt wird. Die zweite (++) soll alle verbleibenden Artikel der aktuellen Bestellposition zur Lieferung hinzufügen. Dazu legen Sie für die Ereignisprozedur Beim Klicken der beiden Textfelder jeweils eine neue Ereignisprozedur an. Die Prozedur zum Hinzufügen eines einzigen Artikels zu einer Lieferposition sieht so aus: Private Sub PlusEins_Click() ArtikelAnLieferposition 1 Sie ruft eine weitere Prozedur namens ArtikelAn- Lieferposition auf, welche die Anzahl der zu übertragenden Artikel als Parameter erwartet in diesem Fall genau einer. Die zweite Prozedur besitzt ein paar Zeilen mehr. Das liegt daran, dass sie erst noch ermitteln muss, wie viele Artikel die aktuelle Bestellposition enthält und welche Menge schon geliefert ist. Daraus bildet sie die Differenz und übergibt das Ergebnis ebenfalls an die Prozedur ArtikelAnLieferposition: Abb. 11: Unterformular mit Schaltflächen zum Hinzufügen von Bestellpositionen zur Lieferung Private Sub PlusAlle_Click() Dim lngmenge As Long lngmenge = _ Me!BestellteMenge - Nz(Me!GelieferteMenge) ArtikelAnLieferposition lngmenge Fehlt noch die von beiden Ereignisprozeduren referenzierte Prozedur. Diese sieht wie in Listing 1 aus und erwartet die Menge der zur Lieferung hinzuzufügenden Artikel als Parameter. Die Prozedur prüft, ob der mit lngmenge übergebene Wert überhaupt größer 0 ist. Falls nicht, ist nichts zu tun und die Prozedur endet, da die Bedingung nicht erfüllt wurde. Ist lngmenge größer als 0, stellt die Prozedur zunächst einen SQL-Ausdruck für den Fall zusammen, dass bereits eine Lieferungsposition für diese Bestellposition angelegt wurde. Diese UPDATE- Abfrage fügt dem Feld Menge die in lngmenge enthaltene Anzahl Artikel hinzu, und zwar für Datensätze, deren Feld LieferungID zum aktuell im Hauptformular bearbeiten Datensatz aus der 31

34 Formulare und Steuerelemente Flexible Bestellungen: Formulare Listing 1: Eintragen neuer Daten in die Tabelle tbllieferpositionen Private Sub ArtikelAnLieferposition(lngMenge As Long) Dim db As DAO.Database Dim strsql As String If lngmenge > 0 Then Set db = CurrentDb strsql = "UPDATE tbllieferpositionen SET Menge = Menge + " & lngmenge _ & " WHERE LieferungID = " & Me.Parent!lieferungID & " AND BestellpositionID = " _ & Me!BestellpositionID db.execute strsql, dbfailonerror If db.recordsaffected = 0 Then strsql = "INSERT INTO tbllieferpositionen(lieferungid, BestellpositionID, Menge) µ VALUES(" & Me.Parent.lieferungID & ", " & Me!BestellpositionID & ", " & lngmenge & ")" db.execute strsql, dbfailonerror End If Set db = Nothing Me.Requery Me.Parent!sfmLieferpositionen.Form.Requery End If Tabelle tbllieferungen stammt und deren BestellpositionID mit dem gleichnamigen Feld der aktuellen Bestellposition übereinstimmt. Nach der Ausführung dieser Abfrage prüft die Prozedur, wie viele Datensätze davon betroffen waren. Lautet der Wert 0, liegt wohl noch kein Lieferdatensatz für diesen Bestelldatensatz vor. In diesem Fall legt die Prozedur mit einer INSERT INTO-Abfrage einen entsprechenden neuen Datensatz an und trägt für diesen auch gleich die mit lngmenge übergebene Menge Artikel ein. Schließlich aktualisiert die Abfrage mit der Requery-Methode noch das aktuelle Formular und schließlich auch das Unterformular zur Anzeige der Lieferpositionen. Fertig Lieferungen lassen sich nun ganz einfach mit wenigen Mausklicks zusammenstellen. Rechnungen verwalten Der letzte Punkt zum Thema Formular sind die Formulare zur Rechnungsverwaltung. Auch hier finden Sie wieder ein Hauptformular und zwei Unterformulare. Das Hauptformular heißt frm- Rechnungen und zeigt die Hauptdaten der Rechnung an. Die Daten stammen aus den Feldern RechnungID, KundeID und Rechnungsdatum der Tabelle tblrechnungen. Die drei Felder bringen wir im oberen Bereich des Formulars frm- Rechnungen unter. Darunter folgt ein Unterformular namens sfm- LieferpositionenOffen. Dieses soll alle Einträge der Tabelle tbllieferungen anzeigen, die zu dem für die neue Rechnung ausgewählten Kunden gehören und noch nicht bezahlt wurden. Schließlich soll das untere Unterformular namens sfmrechnungspositionen alle Rechnungspositionen für die im Hauptformular angezeigte Rechnung anzeigen. Bevor wir auf die Details eingehen, finden Sie in in Abb. 12 den Entwurf von Haupt- und Unterformularen im Überblick. Unterformular mit offenen Positionen Das Unterformular sfmlieferpositionenoffen soll alle Datensätze der Tabelle tbllieferpositionen anzeigen, die noch nicht in einer Rechnung erfasst wurden. In diesem Fall sollten nicht wie bei den Lieferpositionen eine Bestellposition auf mehrere Lieferpositionen aufgeteilt werden. Stattdessen entspricht 32

35 Flexible Bestellungen: Formulare Formulare und Steuerelemente jede Rechnungsposition genau einer Lieferposition. Die als Datenherkunft für das Unterformular verwendete Abfrage heißt qryfrmlieferpositionenoffen und sieht wie in Abb. 13 aus. Damit alle wichtigen Informationen zur Lieferposition vorliegen, liefert die Abfrage Daten aus den Tabellen tbllieferungen, tblbestellpositionen und tbllieferpositionen. Die Tabelle tbl- Rechnungspositionen hat nur eine Aufgabe: Die Abfrage soll keine Datensätze liefern, für die bereits eine Rechnungsposition existiert. Dies ist genau dann der Fall, wenn die Tabelle tblrechnungspositionen den entsprechenden Eintrag der Tabelle tbllieferpositionen über das Fremdschlüsselfeld LieferpositionID referenziert. Abb. 12: Formulare zum Verwalten der Rechnungen im Entwurf Damit die Abfrage alle Datensätze liefert auch solche, für die es keinen passenden Eintrag in der Tabelle tblrechnungspositionen gibt, stellen Abb. 13: Datenherkunft der für die Abrechnung bereitstehenden Bestellpositionen 33

36 Formulare und Steuerelemente Flexible Bestellungen: Formulare Sie die Verknüpfungseigenschaften für die Beziehung zwischen den Tabellen tbl- Rechnungspositionen und tbllieferpositionen entsprechend ein. Die Abfrage liefert nun alle Datensätze der Tabelle tbllieferpositionen, auch solche, für die kein Eintrag in der Tabelle tblrechnungspositionen vorliegt (s. Abb. 14). Somit müssen wir nun nur noch diejenigen Datensätze aus dem Ergebnis herausfiltern, die bereits in einer Rechnung enthalten sind. Kein Problem: Dazu fügen Sie dem Feld RechnungspositionID als Kriterium den Ausdruck Ist Null hinzu. Ähnlich wie beim Formular zur Verwaltung von Lieferungen soll das obere Unterformular auch wieder nur solche Lieferpositionen anzeigen, die zu dem aktuell im Hauptformular angezeigten Kunden gehören. Dazu stellen Sie wiederum die beiden Eigenschaften Verknüpfen von und Verknüpfen nach auf den Wert KundeID ein. Unterformular zur Anzeige der Rechnungspositionen Das Unterformular sfmrechnungspositionen soll alle bereits der Rechnung zugewiesenen Rechnungen ausgeben. Dazu verwendet es als Datenherkunft die Abfrage qrysfmrechnungen Abb. 14: Lieferpositionen, von denen bereits eine als Rechnungsposition markiert ist (s. Abb. 15). Die Abfrage liefert die Felder RechnungspositionID und RechnungID aus der Tabelle tblrechnungspositionen und die Felder ArtikelID, KostenstelleID, Einzelpreis, Rabatt und Mehrwertsteuer aus der Tabelle tblbestellpositionen. Fehlt noch die Menge. Die entnehmen wir natürlich nicht der Tabelle tblbestellpositionen, denn sie kann ja auf mehrere Einträge der Tabelle tbllieferpositionen aufgeteilt worden sein. Genau diese Tabelle liefert auch den fehlenden Wert für die Rechnungsdatensätze. Von der Lieferung zur Rechnung Es fehlt wiederum eine Möglichkeit, Lieferdatensätze schnell zur aktuellen Rechnung hinzuzufügen. Im Gegensatz zur vorherigen Aufgabenstellung sollen diesmal nur komplette Lieferdatensätze in Rechnungsdatensätze überführt werden. Also fügen wir der Abfrage qry- SfmLieferpositionenOffen ein Feld mit folgendem Inhalt hinzu: ZurRechnung: "Zur Rechnung" Abb. 15: Die Datenherkunft des Unterformulars sfmrechnungspositionen 34

37 Flexible Bestellungen: Formulare Formulare und Steuerelemente Listing 2: Eintragen neuer Daten in die Tabelle tblrechnungspositionen Private Sub ZurRechnung_Click() Dim db As DAO.Database Set db = CurrentDb db.execute "INSERT INTO tblrechnungspositionen(rechnungid, LieferpositionID) VALUES(" _ & Me.Parent!rechnungID & ", " & Me!LieferpositionID & ")", dbfailonerror Me.Requery Me.Parent!sfmRechnungspositionen.Form.Requery Set db = Nothing Im Formularentwurf des Unterformulars sfmlieferpositionenoffen legen Sie ein entsprechendes Textfeld für dieses Feld an. Versehen Sie es wieder mit einer Prozedur für die Ereigniseigenschaft Beim Klicken (s. Abb. 16). Diese benötigt nur eine INSERT INTO-Anweisung, um der Tabelle tblrechnungspositionen einen neuen Datensatz hinzuzufügen. Dieser enthält als RechnungID den Wert des gleichnamigen Feldes des übergeordneten Formulars und als LieferpositionID den Wert des aktuellen Datensatzes. Anschließend aktualisiert die Prozedur noch die beiden Unterformulare, damit der Lieferdatensatz scheinbar von einem zum anderen Unterformular verschoben wird (s. Listing 2). So könnte man etwa noch Schaltflächen hinzufügen, mit denen man gleichzeitig alle Bestellungen zu einer Lieferung oder Lieferungen zu einer Rechnung hinzufügen kann. Hier ging es jedoch zunächst um die grundlegenden Techniken, die im Datenmodell gelieferten Tabellen mit entsprechenden Formularen zu füllen. In einem weiteren Teil sehen wir uns noch an, wie die Berichte für die einzelnen Zwischenstände erstellt werden können also beispielsweise ein Lieferschein oder eine Rechnung. Zusätzlich sehen wir dort noch Möglichkeiten vor, gelieferte oder in Rechnung gestellte Positionen als solche zu markieren. Zusammenfassung und Ausblick Damit sind wir am Ende dieses grundlegenden Teils zur Beschreibung der Formulare zum Verwalten von Bestellungen, Lieferungen und Rechnungen angelangt. Es gibt noch eine Reihe von Möglichkeiten, diese Formulare optisch und funktionell zu optimieren. Abb. 16: Verwalten von Rechnungen 35

38 VBA und Programmiertechnik Funktionen aus anderen Datenbanken Funktionen aus anderen Datenbanken André Minhorst, Duisburg Manche Funktionen benötigen Sie nicht nur in einer, sondern in mehreren Datenbanken. Sie können die Funktion dann in die jeweiligen Datenbanken kopieren und dort nutzen. Dies bringt allerdings einigen Mehraufwand bei der Pflege der Funktion mit sich: Wenn Sie etwa einen Fehler beheben, müssen Sie dies gleich für mehrere Datenbanken erledigen. Beim zentralen Speichern der Funktion in einer einzigen Datenbankdatei brauchen Sie Änderungen nur an einer einzigen Stelle durchzuführen. Und es gibt noch weitere Vorteile und Anwendungszwecke mehr dazu im vorliegenden Beitrag. Der Grund dafür, die in diesem Beitrag vorgestellten Techniken zu verwenden, ist die Lösung aus einem anderen Beitrag namens Alle Datenbanken einlesen und anzeigen ( Dort stellen wir ein Add-In vor, mit dem Sie den Pfad zu einer bestimmten Access-Datenbank ermitteln können. Dabei liefert das Add-In nur die Verzeichnisse, in denen sich auch tatsächlich Access-Datenbankdateien befinden. Das Problem dieses Add-Ins und von Add-Ins im Allgemeinen ist: Es gibt keinen einfachen Weg, die enthaltenen Funktionen aufzurufen und die Ergebnisse direkt etwa per VBA in ein Textfeld zu schreiben. Gerade beim Ermitteln von Verzeichnissen und Datenbankdateien wäre dies aber sinnvoll anderenfalls müsste man immer den Pfad aus dem Add-In-Formular kopieren und an der gewünschten Stelle eintragen. Außerdem lassen Zusammenfassung Lernen Sie, wie Sie Funktionen, Formulare und weitere Features von Add-In-Datenbanken von einer Host-Anwendung aus nutzen können. Techniken Add-Ins, VBA Voraussetzungen Access 2000 Beispieldateien Start.mdb, Ziel.mda Shortlink /886 sich Add-Ins und ihre Funktionen nur über genau definierte Schnittstellen aufrufen beispielsweise über das Add-Ins-Menü oder als Objekt- oder Steuerelement-Assistent. Wenn Sie die Funktion aber etwa über die neben einem Textfeld platzierte Schaltfläche aufrufen und das Ergebnis in das Textfeld eintragen möchten, müssen Sie selbst eine Lösung per VBA erstellen. Dies ist, um beim Beispiel der Datenbankauswahl zu bleiben, auch kein Problem Sie brauchen einfach nur alle Objekte der Add-In-Datenbank in die Zieldatenbank zu kopieren und die dort enthaltene Funktion zum Starten des Add-Ins aufzurufen. Praktischer wäre es dennoch, wenn Sie eine solche Funktion an zentraler Stelle vorhalten und aufrufen könnten, statt diese in mehrere Datenbanken zu integrieren und dort auch separat pflegen zu müssen. Der Ansatz Der nachfolgend vorgestellte Ansatz basiert grundsätzlich darauf, eine Bibliotheksdatenbank mit allgemeinen Funktionen in die Zieldatenbank einzubinden und die Funktionen der Bibliotheksdatenbank in der Zieldatenbank verfügbar zu machen. Allerdings ist für diese Vorgehensweise ein fester Verweis auf die Bibliotheksdatenbank nötig. Verschieben Sie die Funktionsbibliothek, liefert die Zieldatenbank beim Aufruf einer der Funktionen einen Fehler. Bei der in diesem Beitrag verwendeten Technik wird die Bibliotheksdatenbank quasi per Late Bin- 36

39 Funktionen aus anderen Datenbanken VBA und Programmiertechnik ding referenziert, also erst kurz vor dem Zugriff auf die enthaltenen Funktionen. Das bedeutet, dass wir vor dem Binden noch prüfen können, ob die Funktionsbibliothek an Ort und Stelle ist. Falls nicht, liefern Sie dem Benutzer eine aussagekräftige Meldung und bitten ihn, die Bibliotheksdatenbank an die gewünschte Stelle zu kopieren. Entwickler oder Benutzer? Grundsätzlich sollten Sie jedoch überlegen, ob Sie die vorgestellten Techniken nur für den Zeitraum der Entwicklung nutzen oder ob auch der Benutzer die Bibliotheken erhalten soll. Sie als Entwickler haben (hoffentlich) einen genauen Überblick darüber, wo eine Datenbankanwendung auf Bibliotheken zugreift, und können gegebenenfalls schnell mal einen Pfad anpassen. Wenn Sie in den Anwendungen, die Sie an Benutzer weitergeben, ebenfalls mit Funktionsbibliotheken arbeiten möchten, könnte der Betrieb natürlich durch fehlende Bibliotheksdateien gestört werden. Wenn zur Weitergabe vorgesehene Datenbankdateien hingegen alle notwendigen Funktionen im eigenen VBA-Projekt enthalten, entfällt diese Gefahr. Dafür ist bei Aktualisierungen in den Bibliotheksfunktionen gleich das ganze Frontend auszutauschen. In diesem Beitrag erläutern wir, wie Sie das Einbinden externer Funktionen per Late Binding als Entwickler nutzen können. Funktionsbibliothek erstellen Die Funktionsbibliothek muss eine wichtige Voraussetzung erfüllen: Sie muss als Add-In gekennzeichnet werden. Das ist allerdings im Handumdrehen erledigt Sie passen dazu lediglich die Dateiendung an: aus.mdb wird.mda und aus.accdb wird.accda. Sprich: Sie ersetzen einfach nur das b durch das a. Und, was noch besser ist im Hinblick auf die eventuelle Weitergabe einer solchen Code-Bibliothek: Sie können auch eine als.mde oder.accde erstellte Datenbankdatei in eine.mda oder.accda-bibliothek umwandeln. Begriffsklärung Im Folgenden sollen die aufrufende Anwendung Host-Anwendung und die Anwendung mit den aufgerufenen Funktionen Add-In-Anwendung heißen. Einfache Funktion aufrufen Beginnen wir mit dem ersten Beispiel. Dabei soll die Host-Anwendung eine einfache Funktion in der Add-In-Anwendung aufrufen. Erstellen Sie also eine Add-In-Anwendung, die sich lediglich durch den Buchstaben a in der Dateiendung als solche zu erkennen gibt. Die sonst bei Add-Ins üblichen Maßnahmen brauchen Sie nicht zu treffen. Legen Sie dann ein Standardmodul beliebigen Namens in der Add-In-Datenbank an und fügen Sie dort die folgende Funktion hinzu: Public Function Meldungsfenster() MsgBox "Einfaches Meldungsfenster", _ End Function vbokonly, "Add-In" Der Test der Funktion zeigt das Meldungsfenster an. Nun schließen Sie die Add-In-Anwendung und erstellen beziehungsweise öffnen die Host- Anwendung. Damit wir direkt von der Benutzeroberfläche aus arbeiten, legen Sie ein neues Formular in der Host- Anwendung an und fügen diesem eine Schaltfläche namens cmdmeldungsfenster hinzu. Legen Sie für diese Schaltfläche die folgende Ereignisprozedur an, die durch das Beim Klicken- Ereignis ausgelöst wird: 37

40 VBA und Programmiertechnik Funktionen aus anderen Datenbanken Abb. 1: Aufruf eines Meldungsfensters aus einer anderen Datenbank Private Sub cmdmeldungsfenster_click() Application.Run CurrentProject.Path _ & "\Ziel.Meldungsfenster" Lassen Sie uns die einzige Anweisung dieser Prozedur auseinandernehmen: Der Aufruf der Funktion in der Add-In-Datenbank wird also durch die Run-Funktion des Application-Objekts erreicht. Diese erwartet als Parameter das Verzeichnis und den Namen der Add-In-Anwendung sowie den Namen der auszuführenden Funktion. CurrentProject.Path ermittelt in diesem Beispiel den Pfad der aktuellen Datenbank. Damit das Beispiel funktioniert, muss sich die Add-In- Datenbank also im gleichen Verzeichnis wie die Host-Datenbank befinden. Öffnen Sie das Formular nun in der Formularansicht und klicken Sie auf die Schaltfläche. Dies sollte das Meldungsfenster aus Abb. 1 hervorrufen. Speicherort der Add-In-Datenbank Sie können die Add-In-Datenbank natürlich auch an jedem anderen Ort speichern Sie müssen lediglich sicherstellen, dass diese an dem in der Run-Funktion angegebenen Ort liegt. Auch Folgendes wäre machbar, wenn sich die Add-In-Anwendung direkt im Verzeichnis c:\ befindet: Application.Run "c:\ziel.meldungsfenster" Hier ist deutlicher zu erkennen, dass Sie nur den Namen der Add-In-Anwendung angeben müssen und nicht die Dateiendung. Stattdessen tragen Sie hinter dem Punkt den Namen der aufzurufenden Funktion ein, hier Meldungsfenster. Damit geht einher, dass Sie nicht gleichzeitig etwa eine Add-In-Anwendung namens Ziel.mda und Ziel.accda einsetzen sollten. Das Dateisystem kann beide Dateien zwar unterscheiden, aber nicht die Run-Funkion. Wenn Sie die Beispieldatenbanken ausprobieren möchten, speichern Sie Start.mdb und Ziel.mda im gleichen Verzeichnis, da hier die CurrentProject.Path-Methode zum Ermitteln des Dateipfades der Add-In-Anwendung verwendet wird. Was geschieht? Bevor wir mit weiteren Beispielen fortfahren, schauen wir uns an, was sich mittlerweile im VBA-Editor getan hat. Diesen aktivieren Sie am schnellsten mit einer der Tastenkombinationen Strg + G oder Alt + F11. Der VBA-Editor zeigt im Objekt-Explorer nunmehr nicht nur das VBA-Projekt der aktuell geöffneten Host-Anwendung an, sondern zusätzlich das der Add-In-Anwendung (s. Abb. 2). Daran ist zu erkennen, dass Access das VBA-Projekt der verwendeten Add-In-Anwendung quasi eingebunden hat auch wenn der Verweise-Dialog keinen Verweis auf die Add-In-Anwendung aufweist. Hier sind nun folgende Dinge zu beachten: Sie können zwar den Code im VBA-Projekt der Add-In-Anwendung ändern und diesen auch ausprobieren. Allerdings werden Sie beim Schließen der Host-Anwendung und beim anschließenden separaten Öffnen des VBA-Projekts der Add-In-Anwendung feststellen, dass sämtliche Änderungen verlorengegangen sind. Also: Sie können natürlich schnell mal eine Änderung vornehmen, um diese auszuprobieren aber schließen Sie die Host-Anwendung dann niemals, ohne den geänderten Code zu kopieren und anschließend direkt in die Add- In-Anwendung einzupflegen! 38

41 Funktionen aus anderen Datenbanken VBA und Programmiertechnik Abb. 2: Anzeige der VBA-Projekte der Host- und der Add-In-Anwendung Das VBA-Projekt der Add-In-Anwendung bleibt bis zum Schließen der Host-Anwendung im Projekt-Explorer erhalten. Sie können also nicht etwa im VBA-Code einen Verweis auf das Projekt setzen und die Instanz durch Leeren des Verweises im Nirwana verschwinden lassen. Sub oder Funktion? Während Sie beim Aufruf eines Access-Add-Ins über die Benutzeroberfläche, also etwa über das Add-Ins-Menü, nur VBA-Functions verwenden können, erlaubt die Run-Funktion auch den Einsatz von Sub-Prozeduren. Die folgende Prozedur in der Add-In-Datenbank würde also den gleichen Effekt bewirken: Public Sub Meldungsfenster_Sub() MsgBox "Einfaches Meldungsfenster aus einer µ Sub", vbokonly, "Add-In" Der folgende Aufruf startet diese Prozedur (siehe Schaltfläche cmdmeldungsfenstersub im Beispielformular): Dies zeigt ebenfalls das erwartete Meldungsfenster an. Funktion mit Rückgabewert Im nächsten Beispiel erfahren Sie, wie Sie von der Funktion in der Add-In-Datenbank einen Funktionswert zurückgeben lassen. Legen Sie dazu im Standardmodul der Add-In-Datenbank die folgende Funktion an: Public Function Rueckgabewert() As String Rueckgabewert = "Wert von Add-In" End Function Diese Funktion liefert auf herkömmliche Weise eine Zeichenkette als Funktionswert an die aufrufende Anweisung. Im Beispielformular finden Sie den Aufruf dieser Funktion in der Prozedur cmdrueckgabewert_ Click. Der Unterschied zum vorherigen Beispiel ist, dass wir das Ergebnis der Run-Funktion in der Variablen strtest speichern und anschließend in einem Meldungsfenster ausgeben. Application.Run CurrentProject.Path µ & "\Ziel.Meldungsfenster_Sub" Wichtig ist dabei, dass Sie den Parameter der Run-Funktion in Klammern einfassen: 39

42 VBA und Programmiertechnik Funktionen aus anderen Datenbanken Abb. 3: Ein von einer Add-In-Funktion erhaltener Rückgabewert Zielfunktion als Parameter angegeben werden, sondern noch ein weiterer Parameter zum Einsatz kommt und dieser nimmt den Funktionsparameter auf. Im Beispiel soll der Inhalt des Textfeldes txtparameter des Formulars frmbeispiele an die Add-In- Funktion übergeben werden: Private Sub cmdparameter_click() Application.Run _ CurrentProject.Path _ & "\Ziel.WertUebergeben", _ Me!txtParameter Die Add-In-Funktion liefert den aktuellen Wert des Textfeldes als Inhalt eines Meldungsfensters (s. Abb. 4). Abb. 4: Dieses Meldungsfenster wird wiederum von der Add-In-Anwendung Rückgabeparameter erzeugt. Die Parameter herkömmlicher VBA- Private Sub cmdrueckgabewert_click() Prozeduren können Sie, sofern diese nicht explizit mit dem Schlüsselwort ByVal gekennzeichnet Dim strtest As String strtest = Application.Run(CurrentProject.Path µ sind, mit Werten füllen, die von der aufrufenden & "\Ziel.Rueckgabewert") Routine weiterverwendet werden können. Voraussetzung dafür ist, dass bereits beim Aufruf der MsgBox "Funktionswert von Add-In: '" _ & strtest & "'", vbokonly, "Host" Prozedur eine Variable als Parameter übergeben wurde. Auch dies gelingt ohne Probleme, wie Abb. 3 zeigt. Wert an Add-In übergeben Dies funktioniert auch vom Host zum Add-In. Die folgende Add-In-Funktion erwartet eine Zeichenkette als Parameter und gibt diese per Meldungsfenster aus: Public Function WertUebergeben(strWert As String) 40 MsgBox "An Add-In übergebener Wert: " _ End Function & strwert, vbokonly, "Add-In" Der folgende Aufruf unterscheidet sich von den vorherigen, da nicht nur Add-In-Anwendung und Dies gelingt auch bei Add-In-Funktionen. Die folgende Funktion enthält mit strhin einen String- Parameter. Die Funktion gibt den übergebenen Wert zunächst per Meldungsfenster aus und ändert den Wert des Parameters dann: Public Function HinUndZurueck(strHin As String) MsgBox "Empfangen wurde: " & strhin, _ vbokonly, "Add-In" strhin = "Zurueck" End Function Die Prozedur, die durch die Schaltfläche cmd- Rueckgabeparameter im Beispielformular ausgelöst wird, deklariert eine Variable namens strhinzurueck und übergibt diese als zweiten

43 Funktionen aus anderen Datenbanken VBA und Programmiertechnik Parameter der Run-Funktion. Anschließend gibt sie den Wert der als Parameter verwendeten und in der Funktion geänderten Variablen in einem Meldungsfenster aus: Private Sub cmdrueckgabeparameter_click() Dim strhinzurueck As String strhinzurueck = "Hin" Application.Run CurrentProject.Path _ & "\Ziel.HinUndZurueck", strhinzurueck MsgBox "Zurueckgegeben wurde: " _ & strhinzurueck, vbokonly, "Host" Parameter verschiedener Datentypen Sie können Parameter verschiedener Datentypen übergeben sogar Objektvariablen etwa mit einem Verweis auf das Database-Objekt. Die folgende Beispielfunktion in der Add-In-Anwendung erwartet drei Parameter und speichert diese in Variant-Variablen. Die folgenden MsgBox- Anweisungen geben Name und Datentyp der Variablen aus im Falle der dritten Variablen auch noch die Eigenschaft Name: Public Function Datentypen(var1 As Variant, var2 As Variant, obj As Variant) MsgBox "Datentyp var1: " & TypeName(var1) MsgBox "Datentyp var2: " & TypeName(var2) MsgBox "Datentyp var3: " & TypeName(obj) & vbcrlf & "Name: " & obj.name End Function Das Beispielformular der Host-Datenbank statten wir mit der folgenden Prozedur aus: Private Sub cmddatentypen_click() Dim strstring As String Dim intinteger As Integer Dim db As DAO.Database Set db = CurrentDb Application.Run CurrentProject.Path & µ "\Ziel.Datentypen", strstring, intinteger, db Die Prozedur übergibt je eine String-, Integerund Database-Variable. Die aufgerufene Funktion gibt die gewünschten Informationen aus. Daten aus der Add-In-Datenbank nutzen Vielleicht gibt es einen Anwendungsfall, bei dem die Add-In-Datenbank bestimmte Daten bereithalten soll. Sie können dann in der Add-In-Funktion ein Recordset auf Basis der Daten erzeugen und dieses an die aufrufende Funktion zurückgeben. Die Add-In-Funktion sieht wie folgt aus: Public Function RecordsetHolen() As DAO.Recordset Dim db As DAO.Database Dim rst As DAO.Recordset Set db = CodeDb Set rst = db.openrecordset("tbloptionen", _ dbopendynaset) Set RecordsetHolen = rst End Function Sie hat den Datentyp DAO.Recordset und öffnet schlicht und einfach ein Recordset auf Basis der Tabelle tbloptionen der Add-In-Datenbank. Woher aber weiß die Funktion, dass sie auf die Daten der Add-In-Datenbank zugreifen soll und nicht auf die der Host-Datenbank? Ganz einfach: Sie verwenden die Funktion CodeDB statt CurrentDB, um einen Verweis auf das entsprechende Database-Objekt zu erhalten. Im Formular frmbeispiele der Host-Datenbank bringen wir eine Schaltfläche namens cmdrecordset unter, die beim Klicken die folgende Prozedur auslöst: Private Sub cmdrecordset_click() Dim rst As DAO.Recordset Set rst = Application.Run(µ CurrentProject.Path & "\Ziel.RecordsetHolen") Do While Not rst.eof Loop Debug.Print rst.fields(0), _ rst.fields(1), rst.fields(2) rst.movenext RunCommand accmddebugwindow Die Prozedur ruft die Funktion RecordsetHolen in der Add-In-Datenbank auf und nimmt als 41

44 VBA und Programmiertechnik Funktionen aus anderen Datenbanken Rückgabewert den Verweis auf das Recordset- Objekt entgegen. Um zu zeigen, dass dieses nun verfügbar ist, werden die einzelnen Datensätze im Direktbereich ausgegeben, der mit RunCommand. DebugWindow eingeblendet wird. Formular öffnen Wenn Sie ein Formular in der Add-In-Anwendung öffnen möchten, fügen Sie der Anwendung folgende Funktion hinzu, wobei das Formular frm- Einfach in der Add-In-Anwendung enthalten sein muss: Public Function EinfachesFormularOeffnen() DoCmd.OpenForm "frmeinfach", _ End Function WindowMode:=acDialog In der Host-Anwendung rufen Sie diese Funktion einfach mit Run auf: Private Sub cmdformularoeffnen_click() Application.Run CurrentProject.Path _ & "\Ziel.EinfachesFormularOeffnen" Das Formular wird ohne Verzögerung geöffnet. Formular mit Öffnungsargument Wenn Sie ein Formular in der Add-In-Datenbank öffnen und diesem ein Öffnungsargument aus der Host-Anwendung übergeben möchten, erledigen Sie dies in zwei Schritten. Im ersten Schritt rufen Sie die Add-In-Funktion auf und übergeben den als Öffnungsargument vorgesehenen Wert hier beispielsweise ein String-Wert: Private Sub cmdformularopenargs_click() Application.Run CurrentProject.Path _ & "\Ziel.FormularMitOpenArgsOeffnen", _ "Öffnungsargument" Die Add-In-Funktion nimmt diesen Wert als Parameter entgegen und trägt ihn als Wert des Parameters OpenArgs beim Aufruf des Formulars in die OpenForm-Methode ein: Public Function FormularMitOpenArgsOeffnen(_ stropenargs As String) DoCmd.OpenForm "frmoeffnungsargument", _ End Function WindowMode:=acDialog, _ OpenArgs:=strOpenargs Im Formular der Add-In-Datenbank, hier frm- Oeffnungsargument, wird das über die Eigenschaft OpenArgs abrufbare Öffnungsargument beim Laden ausgewertet und beispielsweise in ein Textfeld eingetragen: Private Sub Form_Load() Me!txtOeffnungsargument = Nz(Me.OpenArgs) Das Ergebnis sehen Sie in Abb. 5. Formular mit Rückgabewert Wenn Sie eine Funktion zu einer Add-In-Anwendung hinzufügen, die ein Formular öffnet, damit der Benutzer dort bestimmte Eingaben tätigen kann und anschließend ein entsprechendes Ergebnis erhält, wollen Sie das Ergebnis auch zur aufrufenden Host-Anwendung zurückübertragen. Abb. 5: Ein per OpenArgs übergebener Wert im Textfeld des Add-In-Formulars 42 Das folgende Beispiel zeigt die dazu notwendigen Schritte. Den Start machen wir wieder in der Host- Anwendung. Dort löst die Schaltfläche cmdformular- Rueckgabewert die folgende Prozedur aus. Diese deklariert eine Variable namens strrueckgabewert und

45 Funktionen aus anderen Datenbanken VBA und Programmiertechnik Abb. 6: Eingabe des Rückgabewertes in ein Formular der Add- In-Datenbank... weist dieser das Ergebnis des Aufrufs der Funktion FormularMitRueckgabewert der Add-In-Datenbank zu. Zur Prüfung wird das Ergebnis per Meldungsfenster ausgegeben: Private Sub cmdformularrueckgabewert_click() Dim strrueckgabewert As String strrueckgabewert = _ Application.Run(CurrentProject.Path _ & "\Ziel.FormularMitRueckgabewert") MsgBox "Rueckgabewert: " & strrueckgabewert Die Funktion FormularMitRueckgabewert öffnet das Formular als modalen Dialog. Das bedeutet, dass der aufrufende Code erst weiterläuft, wenn der Benutzer das Formular geschlossen oder ausgeblendet hat. Ist dies geschehen, indem der Benutzer die OK- Schaltfläche gedrückt und das Formular ausgeblendet hat, liest die Prozedur den Wert des Textfeldes txtrueckgabewert ein und weist diesem den Rückgabewert der Funktion FormularMitRueckgabewert zu. Anschließend wird das Formular endgültig geschlossen: Public Function FormularMitRueckgabewert() As String DoCmd.OpenForm "frmrueckgabewert", _ WindowMode:=acDialog FormularMitRueckgabewert = _ Nz(Forms!frmRueckgabewert! _ txtrueckgabewert, "") DoCmd.Close acform, "frmrueckgabewert" End Function Abb. 7:... und Ausgabe des ermittelten Textfeld-Inhalts Das Formular frmrueckgabewert enthält eine Schaltfläche namens cmdok, die auf Mausklick das Formular ausblendet: Private Sub cmdok_click() Me.Visible = False Die Eingabe des Textes erfolgt schließlich wie in Abb. 6 im Formular frmrueckgabewert der Add- In-Datenbank, das Ergebnis gibt die Host-Anwendung dann wie in Abb. 7 aus. Zusammenfassung und Ausblick Dieser Beitrag zeigt alle Techniken, die für die Interaktion zwischen einer Host- und einer Add-In- Anwendung nötig sind. Damit können Sie umfangreiche Funktionen, die Sie in mehreren Anwendungen einsetzen, in eine eigene Anwendung exportieren und von der Host-Datenbank aus aufrufen. Vor der Weitergabe an Kunden/Benutzer fügen Sie die Funktion entweder wieder ein oder liefern das Add-In mit. 43

46 Interaktiv VBA-Textexport unter Access 2007 und jünger VBA-Textexport unter Access 2007 und jünger André Minhorst, Duisburg Normalerweise ist das Exportieren von Tabellen oder Abfragen als Text- oder CSV-Datei kein Problem Sie nutzen entweder den Assistenten dazu oder verwenden die Methode TransferText des DoCmd-Objekts. Dummerweise führt dies, auch wenn es in Anwendungen bis Access 2003 funktionierte, unter neueren Versionen von Access zu einem Fehler. Warum dies geschieht und wie Sie TransferText weiter nutzen können, erläutert dieser Beitrag. Wenn Sie einen Export der Daten einer Tabelle oder Abfrage in eine Textdatei per VBA automatisieren möchten, verwenden Sie normalerweise die TransferText-Methode des DoCmd-Objekts wie in folgendem Beispiel: DoCmd.TransferText acexportdelim,, "tblartikel", CurrentProject.Path & "\tblartikel.txt" Abb. 1: Fehlermeldung beim Versuch, eine Tabelle mit DoCmd.TransferText ohne Angabe einer Export-Spezifikation zu exportieren Dies löst unter Access 2007 und jünger den Fehler aus Abb. 1 aus. Anscheinend verwendet Access, wenn nichts anderes angegeben wird, entweder das Dezimaltrennzeichen oder das Texttrennzeichen als Feldtrennzeichen. Früher verwendete Access standardmäßig das Semikolon, aber Microsoft scheint hier etwas geändert zu haben. Welches Trennzeichen wird aber nun tatsächlich verwendet? Zusammenfassung Erfahren Sie, warum seit Access 2007 kein Textexport mehr per VBA gelingt und lernen Sie eine schnelle Möglichkeit zur Abhilfe kennen. Techniken VBA, Export Voraussetzungen Access 2000 Beispieldateien Textexport.mdb Shortlink /887 Um dies herauszufinden, habe ich probehalber das Trennzeichen in der Systemsteuerung von Windows verändert am Fehler ändert sich dadurch jedoch nichts. Fehlerfrei mit Export-Spezifikation Es gibt nur eine Lösung für das Problem: Sie müssen eine Export-Spezifikation angeben. Diese ist natürlich zuvor noch zu erstellen, was sich aber durch einmaliges Durchlaufen des Export- Assistenten erledigen lässt. Dazu rufen Sie den entsprechenden Assistenten auf (unter Access 2010 etwa mit dem Ribbon-Eintrag Externe Daten Exportieren Textdatei) und klicken dort auf OK (nicht die Option Exportieren von Daten mit Formatierung und Layout aktivieren!). Nun klicken Sie auf die Schaltfläche Erweitert und dann auf Speichern unter. Geben Sie den gewünschten Namen für die Spezifikation an und speichern Sie die Spezifikation (s. Abb. 2). Den Assistenten können Sie nun abbrechen, ohne den Export durchzuführen wir wollten nur eine 44

47 VBA-Textexport unter Access 2007 und jünger Interaktiv Abb. 2: Speichern einer Export- Spezifikation beliebige Spezifikation anlegen, um diese für den Export per VBA nutzen zu können. Natürlich können Sie hier noch weitere Eigenschaften festlegen, wenn Sie diese benötigen dies ist aber nicht Thema dieses Beitrags. Nach dem Anlegen der Spezifikation und dem erneuten Aufruf der TransferText-Methode diesmal unter Berücksichtigung der gespeicherten Spezifikation gelingt auch der Export ohne Fehler: DoCmd.TransferText acexportdelim, _ "Spec_tblArtikel", "tblartikel", _ CurrentProject.Path & "\tblartikel.txt" Problem: Viele Exporte Was aber, wenn eine Anwendung sehr viele Aufrufe der TransferText-Methode enthält? Sollten Sie diese in einer älteren Access-Version verwendet haben, klappte dies reibungslos. Unter Access 2007 und neuer löst jedoch jeder Text-Export ohne Spezifikation einen Fehler aus. Wenn Sie keine Lust haben, für jede zu exportierende Tabelle oder Abfrage von Hand eine Export- Spezifikation zu erstellen, gibt es gute Nachrichten: Diese Aufgabe lässt sich auch per Code erledigen. Die Spezifikationen werden nämlich in Systemtabellen gespeichert: Die Basisinformationen landen in der Tabelle MSysIMEXSpecs und die Informationen zu den einzelnen Feldern in mehreren Datensätzen der Tabelle MSysIMEXColumns. Im Gegensatz zu den übrigen Systemtabellen sind diese nicht geschützt und Sie können die Daten leicht per VBA hinzufügen. Es geht sogar noch weiter: Die Tabellen sind standardmäßig nicht angelegt und werden erst von Access erzeugt, wenn der Benutzer die erste Spezifikation speichert. Sie können also den kompletten Prozess der Spezifikationserstellung per VBA abwickeln. Dabei hilft die Prozedur SpezifikationAnlegen aus Listing 1. Die Prozedur erwartet den Namen der Tabelle oder Abfrage, für welche die Export- Spezifikation erzeugt werden soll. Sie erstellt die beiden benötigten Tabellen mit entsprechenden CREATE TABLE-Abfragen und fügt auch die Primärschüssel und Indizes hinzu. Mit dem Wert 2 für die Attributes-Eigenschaft werden die hinzugefügten Tabellen auch noch als Systemtabellen gekennzeichnet. Während dieses Vorgangs wird die Fehlerbehandlung von VBA deaktiviert, damit die Anweisungen keinen Fehler auslösen, wenn die Tabellen bereits vorhanden sind. 45

48 Interaktiv VBA-Textexport unter Access 2007 und jünger Listing 1: Spezifikation per VBA anlegen Public Sub SpezifikationAnlegen(strHerkunft As String) Dim db As DAO.Database Dim rst As DAO.Recordset Dim fld As DAO.Field Dim lngid As Long Dim strmsysimexspecs As String Dim strmsysimexcolumns As String Set db = CurrentDb On Error Resume Next strmsysimexspecs = "CREATE TABLE MSysIMEXSpecs([DateDelim] TEXT(2), [DateFourDigitYear] BIT, µ [DateLeadingZeros] BIT, [DateOrder] SMALLINT, [DecimalPoint] TEXT(2), [FieldSeparator] µ TEXT(2), [FileType] SMALLINT, [SpecID] COUNTER, [SpecName] TEXT(64), [SpecType] BYTE, µ [StartRow] INTEGER, [TextDelim] TEXT(2), [TimeDelim] TEXT(2));" db.execute strmsysimexspecs, dbfailonerror strmsysimexspecs = "CREATE UNIQUE INDEX [PrimaryKey] ON [MSysIMEXSpecs]([SpecName]) µ WITH PRIMARY DISALLOW NULL;" db.execute strmsysimexspecs, dbfailonerror db.tabledefs("msysimexspecs").attributes = 2 strmsysimexcolumns = "CREATE TABLE MSysIMEXColumns([Attributes] INTEGER, [DataType] SMALLINT, µ [FieldName] TEXT(64), [IndexType] BYTE, [SkipColumn] BIT, [SpecID] INTEGER, µ [Start] SMALLINT, [Width] SMALLINT);" db.execute strmsysimexcolumns, dbfailonerror strmsysimexcolumns = "CREATE INDEX [Index1] ON [MSysIMEXColumns]([SpecID], [Start]);" db.execute strmsysimexcolumns, dbfailonerror strmsysimexcolumns = "CREATE UNIQUE INDEX [PrimaryKey] ON [MSysIMEXColumns]([SpecID], µ [FieldName]) WITH PRIMARY DISALLOW NULL;" db.execute strmsysimexcolumns, dbfailonerror db.tabledefs("msysimexcolumns").attributes = 2 On Error GoTo 0 Set rst = db.openrecordset(strherkunft, dbopendynaset) db.execute "DELETE FROM MSysIMEXSpecs WHERE Specname = 'Spec_" & strherkunft & "'", _ dbfailonerror db.execute "INSERT INTO MSysIMEXSpecs(Specname, SpecType, DecimalPoint, TextDelim, µ FieldSeparator) VALUES('Spec_" & strherkunft & "', 1, ',', '""', ';')", dbfailonerror lngid = For Each fld In rst.fields db.execute "INSERT INTO MSysIMEXColumns(Fieldname, Datatype, SpecID) VALUES('" & fld.name _ & "', " & fld.type & ", " & lngid & ")", dbfailonerror Next fld Nach dem Erstellen der Systemtabellen löscht die Prozedur zunächst einen eventuell bereits vorhandenen Eintrag für die gewünschte Spezifikation. Die Spezifikationen werden dabei nach dem Schema Specs_<Tabellenname> betitelt. Dann fügt die Prozedur zunächst einen Eintrag zur Tabelle MSysIMEXSpecs hinzu dieser enthält die grundlegenden Einstellungen. Im Falle der Spezifikation, die zur Umgehung des oben beschriebenen Fehlers 3441 erzeugt werden soll, reichen einige wenige Eigenschaften aus der Name der Spezifikation, der Typ, das Dezimaltrennzeichen sowie das Texttrennzeichen und das Feldtrennzeichen. Danach durchläuft die Prozedur alle Felder der angegebenen Datenherkunft und legt für jedes 46

49 VBA-Textexport unter Access 2007 und jünger Interaktiv Abb. 3: Tabellen mit per VBA hinzugefügten Export-Spezifikationen Feld einen Eintrag in der Tabelle MSysIMEXColumns an. Auch hier geben wir uns mit wenigen Feldern zufrieden: Der Feldname, der Datentyp sowie der Wert des Fremdschlüsselfeldes zur Zuordnung zum entsprechenden Datensatz der Tabelle MSys- IMEXSpecs reichen aus. Spezifikationen für alle Tabellen Wenn Sie auf die Schnelle Export-Spezifikationen für alle Tabellen der Anwendung erstellen möchten, verwenden Sie beispielsweise die folgende Prozedur, um die Routine SpezifikationAnlegen für jede Tabelle einmal aufzurufen: Public Sub SpezifikationenFuerAlleTabellen() Dim db As DAO.Database Dim tdf As DAO.TableDef Set db = CurrentDb For Each tdf In db.tabledefs If tdf.name Like "MSys*" Then Else End If Next tdf Set db = Nothing SpezifikationAnlegen tdf.name Public Sub SpezifikationenFuerAlleAbfragen() Dim db As DAO.Database Dim qdf As DAO.QueryDef Set db = CurrentDb For Each qdf In db.querydefs If qdf.name Like "~*" Then Else End If Next qdf SpezifikationAnlegen qdf.name Set db = Nothing Diese beiden Prozeduren spülen schnell die benötigten Export-Spezifikationen in die beiden Tabellen MSysIMEXSpecs und MSysIMEXColumns (s. Abb. 3). Zusammenfassung und Ausblick Mit den hier vorgestellten Techniken fügen Sie einer Anwendung blitzschnell Export-Spezifikationen für alle Tabellen und Abfragen hinzu. Damit können Sie problemlos Exporte mit der VBA-Methode TransferText des DoCmd-Objekts durchführen. Dieser Befehl funktioniert seit Access 2007 nicht mehr fehlerfrei, wenn Sie keine Export-Spezifikation angeben. Für Abfragen gelingt dies analog mit der folgenden Prozedur: 47

50 Lösungen Alle Datenbanken einlesen und anzeigen Alle Datenbanken einlesen und anzeigen André Minhorst, Duisburg Für den einen oder anderen Anwendungsfall benötigen Sie einen Datei-öffnen-Dialog, um eine Datenbank auszuwählen. Dieser Dialog hat den Nachteil, dass er selten direkt die gewünschte Datenbank geschweige denn das Verzeichnis anzeigt. Wie wäre es also mit einem speziellen Dialog, der nur die Verzeichnisse einliest, die überhaupt Datenbankdateien enthalten, und diese in einem TreeView-Steuerelement zur Auswahl bereithält? Ziel Das Ziel dieses Beitrags ist es, einen Dialog zu erstellen, der alle Datenbankdateien oder auch nur die in einem bestimmten Unterordner befindlichen anzeigt und zur Auswahl anbietet. Damit sollen die üblichen Dialoge ersetzt werden, die erstens immer alle Verzeichnisse und Dateien anzeigen und zweitens nie das Verzeichnis liefern, das man gerade benötigt. Für die Erstellung eines solchen Dialogs ist eine Menge Vorarbeit nötig zum Beispiel müssen Sie eine Prozedur programmieren, die alle Verzeichnisse ab dem gewünschten Unterordner erfasst und nach Datenbankdateien durchsucht. Diese werden über die Dateiendung erkannt (.mdb,.accdb...). Der Dialog soll nur diejenigen Verzeichnisse anzeigen, die direkt oder in einem Unterverzeichnis Zusammenfassung Lernen Sie eine Lösung kennen, mit der Sie alle Datenbanken eines Verzeichnisses inklusive Unterverzeichnisse einlesen und in einem Formular anzeigen. Techniken TreeView, FileSystemObject Voraussetzungen Access 2000 Beispieldateien AlleDatenbankenEinlesen.mdb Shortlink /888 Abb. 1: Dialog zur Anzeige von Datenbankdateien mindestens eine Datenbankdatei enthalten. Abb. 1 zeigt, wie der Dialog ungefähr aussehen soll. Sie erkennen hier ein Textfeld, in das Sie das beim Einlesen zu verwendende Startverzeichnis eintragen. Dieses lässt sich mit einem Mausklick auf die Schaltfläche rechts daneben auch per Verzeichnis auswählen-dialog einlesen. Ein Klick auf die Schaltfläche Einlesen startet den Einlesevorgang, der je nach Umfang der einzulesenden Daten eine Weile dauern kann (auf meiner Festplatte, die zugegebenermaßen sehr viele Daten enthält, etwa acht Minuten planen Sie also eine Kaffeepause für diesen Vorgang ein). Wenn Sie einmal ermittelt haben, wo sich die Datenbankdateien befinden, können Sie für den nächsten Einlesevorgang 48

51 Alle Datenbanken einlesen und anzeigen Lösungen gegebenenfalls einen entsprechenden Unterordner als Startverzeichnis angeben, um Zeit zu sparen. Zu Beginn sollten Sie jedoch einmal die komplette Festplatte einlesen ich fand es jedenfalls sehr interessant, an welchen Stellen überall Datenbankdateien gespeichert sind. Die erfassten Daten werden in einer Tabelle gespeichert, die wir weiter unten vorstellen. Die Daten sollen dann in einem TreeView-Steuerelement angezeigt werden. Dazu liest die Anwendung die Daten der Tabelle aus und trägt sie in das TreeView- Steuerelement ein. Verzeichnisse und Datenbankdateien werden mit entsprechenden Symbolen gekennzeichnet. Vorerst soll das Formular lediglich beim Schließen den Pfad der aktuell ausgewählten Datenbankdatei zurückliefern. Abb. 2: Tabelle zum Speichern der Dateien und Verzeichnisse bietet Möglichkeiten, die Verzeichnisse rekursiv zu durchlaufen und die Dateien auf ihre Dateiendung hin zu untersuchen. Überlegungen Schauen wir uns die Ausgangssituation an. Das Dateisystem enthält beliebig tief verschachtelte Verzeichnisstrukturen, von denen nicht alle Access-Dateien speichern. Das zu füllende Tree- View-Steuerelement soll lediglich die Verzeichnisse anzeigen, in denen sich auch Access-Dateien befinden. Dazu müssen wir alle Verzeichnisse durchlaufen und diejenigen mit Access-Dateien ermitteln. Die Pfade der Verzeichnisse mit Access- Dateien sollen dann vom Laufwerksbuchstaben angefangen über die einzelnen Verzeichnisse im TreeView-Steuerelement abgebildet werden. Wie erledigen wir dies am einfachsten, wie werden die Daten über die Verzeichnisse und Access- Datenbanken gespeichert, wie füllen wir das TreeView-Steuerelement und wie oft soll diese Prozedur wiederholt werden? Verzeichnisse und Dateien per FileSystemObject durchlaufen Die Werkzeuge zum Einlesen der Verzeichnisse und Dateien liefert das FileSystemObject. Es Informationen speichern Die Tabelle zum Aufnehmen der Informationen muss folgende Felder enthalten und sieht, mit einigen Daten gefüllt, wie in Abb. 2 aus: DateiVerzeichnisID: Primärschlüsselfeld der Tabelle, allerdings nicht als Autowert ausgelegt mehr dazu später DateiVerzeichnisname: Name der Datei oder des Verzeichnisses IstVerzeichnis: Ja/Nein-Feld, das angibt, ob es sich bei dem Eintrag um ein Verzeichnis handelt VerzeichnisID: Wert des Feldes DateiVerzeichnisID für das übergeordnete Verzeichnis Pfad: Speichert den kompletten Pfad des aktuellen Datensatzes. Expanded: Für die Darstellung im TreeView fügen Sie der Tabelle außerdem noch ein Feld zum Speichern des Expanded-Zustands hinzu. 49

52 Lösungen Alle Datenbanken einlesen und anzeigen der Abbildung id) und für das Fremdschlüsselfeld VerzeichnisID (in der Abbildung fid). Das Speichern des ersten Elements c:\ ist kein Problem dieses soll auf jeden Fall gespeichert werden. Es erhält als Primärschlüsselwert etwa den Wert 1. Das Fremdschlüsselfeld bleibt leer, weil es ja keine übergeordneten Verzeichnisse gibt. Abb. 3: Indizierung der Verzeichnisse und Dateien Enthaltene Dateien: Speichert die Anzahl der im aktuellen Verzeichnis samt Unterverzeichnis enthaltenen Datenbankdateien. Dateien einlesen und speichern Warum verwenden wir in der Tabelle keinen Autowert für das Primärschlüsselfeld? Normalerweise würden wir so vorgehen: Wir lesen das Root-Element ein, also beispielsweise das Verzeichnis c:\ und speichern es in der Tabelle. Dann arbeiten wir uns durch alle untergeordneten Verzeichnisse. Wenn c:\ nun mit dem Wert 1 im Primärschlüsselfeld gespeichert wurde, würden wir für die untergeordneten Verzeichnisse beziehungsweise Einträge den Wert 1 im Feld VerzeichnisID eintragen. Dazu müssen wir aber jedes Verzeichnis in der Tabelle anlegen auch wenn wir feststellen, dass sich weder in diesem Verzeichnis noch in einem der Unterverzeichnisse eine Access-Datei befindet. Und genau dies wollen wir ja verhindern, um nur die notwendigsten Verzeichnisse und Dateien in der Tabelle zu speichern. Zur Veranschaulichung liefert Abb. 3 einige Verzeichnisse und Dateien. Die Beschriftungen rechts neben den Elementen enthalten die Werte für das Primärschlüsselfeld DateiVerzeichnisID (in Das Unterverzeichnis Verzeichnis 1 würde mit dem Primärschlüsselwert 2 gespeichert. Das Feld VerzeichnisID erhält den Primärschlüsselwert des übergeordneten Verzeichnisses, also 1. Das Unterverzeichnis Verzeichnis 1-1 erhält den Primärschlüsselwert 3 und wird über den Wert 2 für das Feld VerzeichnisID dem Verzeichnis mit dem Primärschlüsselwert 2 untergeordnet. Nun folgt die erste Datei, die nach dem gängigen Schema den Wert 4 im Feld DateiVerzeichnisID und den Wert 3 im Fremdschlüsselfeld VerzeichnisID erhält. Wenn alle Verzeichnisse am Ende mindestens eine Datenbankdatei im letzten Verzeichnis enthielten, könnte man die Dateien auf diese Weise anlegen und durchlaufen. Es müssen jeweils die übergeordneten Verzeichnisse zuerst angelegt werden, damit den darunter befindlichen Elementen die Primärschlüsselwerte als Fremdschlüsselwert zugeordnet werden können. Nun gibt es aber Verzeichnisse wie Verzeichnis1-2, das leer ist oder nur Dateien enthält, die nicht in die Tabelle aufgenommen werden sollen. Wir würden es mit den Werten 5 im Feld DateiVerzeichnisID und 2 im Feld VerzeichnisID speichern. Erst danach würden wir die in diesem Verzeichnis enthaltenen Elemente durchlaufen und schließlich feststellen, dass dort keine Datenbankdatei zu finden ist. In diesem Fall gibt es kein weiteres untergeordnetes Verzeichnis, sodass die Untersuchung schnell abgeschlossen ist. Was aber nun mit dem Datensatz für das Verzeichnis mit dem Namen Verzeichnis 1-2? Der Datensatz kann wieder gelöscht werden, da er ja nicht mehr benötigt wird. Dummerweise gibt es gelegentlich sehr tiefe 50

53 Alle Datenbanken einlesen und anzeigen Lösungen Verzeichnisstrukturen, in denen sich keine Datenbankdateien finden lassen. Dort würde man erst einige Datensätze für die Verzeichnisstruktur anlegen und müsste diese anschließend wieder löschen. Dies ist der Grund, warum wir keinen Autowert als Primärschlüsselwert verwenden: Damit die Datensätze für Verzeichnisse ohne untergeordnete Datenbanken gar nicht erst angelegt werden, soll die entsprechende Funktion sich erst rekursiv bis zum Ende der Verzeichnisstruktur bewegen und prüfen, ob dort Datenbankdateien vorliegen. Ist dies der Fall, legt die Funktion zunächst das Element für die Datenbankdatei an und dann die darüber liegenden Verzeichnisse. Sprich: Im Falle von Datei 1 würde erst ein Datensatz für die Datei, dann jeweils einer für Verzeichnis 1-1 und für Verzeichnis 1 angelegt werden. Dummerweise wissen wir beim Anlegen der untergeordneten Elemente noch nicht, welchen Primärschlüsselwert dessen Verzeichnis in der Tabelle aufweist. Wir müssen beim Navigieren in Richtung untergeordneter Verzeichnisse einen Primärschlüsselwert vorhalten und diesen dann von unten nach oben als Fremdschlüsselwert des jeweils untergeordneten Elements einfügen. Wenn dabei wie im Fall von Verzeichnis 1-2 zunächst ein Primärschlüsselwert wie etwa 5 festgelegt wird, sich aber herausstellt, dass dieses Verzeichnis keine Access-Datenbanken enthält und somit nicht gespeichert werden soll, kann der Primärschlüsselwert 5 für das nachfolgend untersuchte Verzeichnis reserviert werden. Rekursive Einlesefunktion Wie lässt sich dies per VBA umsetzen? Ganz einfach mit einer rekursiv definierten Funktion. Diese besteht im vorliegenden Fall aus einer initialisierenden Funktion, die einen oder mehrere Datensätze für das angegebene Root-Verzeichnis schreibt und dann die eigentliche rekursive Funktion aufruft. Schauen wir uns zunächst die Parameter der Startprozedur DateienEinlesen an (s. Listing 1): strpfad: Enthält die Angabe des Startverzeichnisses für den Einlesevorgang. Wenn Sie den Parameter weglassen, liest die Prozedur das komplette Verzeichnis c:\ ein. inttiefemax: Dies ist eher ein Parameter, der für Entwicklungstests verwendet wurde. Damit können Sie angeben, wie tief die Funktion nach Access-Dateien suchen soll. Wenn Sie den Parameter weglassen, durchsucht die Funktion alle Verzeichnisebenen. Die Prozedur deklariert zunächst ein Objekt auf Basis von Scripting.FileSystemObject. Dieses liefert die Methoden und Eigenschaften, um auf das Dateisystem zuzugreifen. Außerdem benötigen wir eine Database-Variable, um per Execute-Methode SQL-Aktionsabfragen ausführen zu können. Die Prozedur prüft zunächst, ob der Parameter strpfad übergeben wurde und ersetzt diesen gegebenenfalls durch das Verzeichnis c:\. Der folgende Aufruf der GetFolder-Funktion des File- SystemObjects entledigt den Inhalt von strpfad eventuell anhängender Backslash-Zeichen, aus c:\ Daten\ wird also c:\daten. Die folgende Anweisung kopiert den kompletten Inhalt der Tabelle tbldateienverzeichnisse in eine neue Tabelle, die den gleichen Namen erhält, jedoch um Datum und Uhrzeit ergänzt. Dieses Feature war während der Entwicklung hilfreich, um umfangreiche erfolgreiche Einlesevorgänge zu sichern, bevor der Code weiter verfeinert wurde. Danach leert die Tabelle tbldateienverzeichnisse, da diese ja nun neu gefüllt werden soll. Ist das in strpfad angegebene Verzeichnis vorhanden, beginnt die eigentliche Bearbeitung. Wenn der Benutzer einen Pfad angibt, der aus mehr als nur dem Laufwerksbuchstaben besteht, soll die Prozedur nämlich für jedes enthaltene Verzeichnis gleich einen Eintrag zur Tabelle tbldateienverzeichnisse hinzufügen und zwar verschachtelt. Dazu überträgt die Prozedur zunächst mit der Split-Funktion alle Verzeichnisse des Pfades in ein Array namens strverzeichnisse(). 51

54 Lösungen Alle Datenbanken einlesen und anzeigen Listing 1: Prozedur zum Initiieren des rekursiven Dateieinlese-Vorgangs Public Sub DateienEinlesen(Optional strpfad As String, Optional inttiefemax As Integer) Dim objfso As Scripting.FileSystemObject Dim db As DAO.Database Dim strverzeichnisse() As String Dim i As Long Set objfso = New Scripting.FileSystemObject Set db = CurrentDb If Len(strPfad) = 0 Then strpfad = "c:\" End If strpfad = objfso.getfolder(strpfad) If Right(strPfad, 1) = "\" Then strpfad = Left(strPfad, Len(strPfad) - 1) End If db.execute "SELECT * INTO tbldateienverzeichnisse_" & Format(Now, "yyyymmdd_hhnnss") _ & " FROM tbldateienverzeichnisse", dbfailonerror db.execute "DELETE FROM tbldateienverzeichnisse", dbfailonerror If objfso.folderexists(strpfad) Then strverzeichnisse = Split(strPfad, "\") For i = LBound(strVerzeichnisse) To UBound(strVerzeichnisse) If i = 0 Then db.execute "INSERT INTO tbldateienverzeichnisse(dateiverzeichnisid, µ DateiVerzeichnisName, IstVerzeichnis) VALUES(" & i + 1 & ", '" _ & strverzeichnisse(i) & "', -1)", dbfailonerror Else db.execute "INSERT INTO tbldateienverzeichnisse(dateiverzeichnisid, µ DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID) VALUES(" & i + 1 & ", '" _ & strverzeichnisse(i) & "', -1, " & i & ")", dbfailonerror End If Next i End If lngaktuellid = i + 1 DateienEinlesenRek db, objfso, objfso.getfolder(strpfad & "\"), i, 0, inttiefemax, 0 Die folgende For...Next-Schleife durchläuft dazu alle Elemente dieses Arrays und legt jeweils einen neuen Eintrag in der Tabelle tbldateienverzeichnisse an. Dabei gibt es wiederum zwei Möglichkeiten: Hat die Laufvariable i den Wert 0, wird das erste Element mit einer SQL-Anweisung wie folgt in die Tabelle tbldateienverzeichnisse eingetragen: INSERT INTO tbldateienverzeichnisse( DateiVerzeichnisID, DateiVerzeichnisName, IstVerzeichnis) VALUES(1, 'C:', -1) Das heißt, dass das Feld VerzeichnisID zum Eintragen der Referenz auf das übergeordnete Verzeichnis leer bleibt. Für die übrigen Einträge gibt die Prozedur jeweils das übergeordnete Verzeichnis als weiteren Parameter der INSERT INTO-Anweisung an: INSERT INTO tbldateienverzeichnisse( DateiVerzeichnisID, DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID) VALUES(2, 'Daten', -1, 1) In diesem Fall referenziert das hier angelegte zweite Element mit dem Primärschlüsselwert 2 das erste Element mit dem Primärschlüsselwert 1 über das Feld VerzeichnisID mit dem Wert 1. Wenn Sie mit dem Parameter strpfad also bei- 52

55 Alle Datenbanken einlesen und anzeigen Lösungen spielsweise den Pfad c:\da- ten\fachartikel\accessim- Unternehmen\2013\03\ übergeben, sieht der Inhalt der Tabelle tbldateienverzeichnisse nach dem Durchlaufen der For...Next-Schleife wie in Abb. 4 aus. Damit ist der erste Teil erledigt alle Verzeichnisse des übergebenen Pfades wurden in der Tabelle angelegt. Nun geht es mit der eigentlichen rekursiven Funktion weiter, die alle unterhalb dieses Pfades befindlichen Verzeichnisse und Dateien untersucht. Vorher stellt die Prozedur jedoch noch die wie folgt global deklarierte Variable lngaktuellid auf den Wert der Laufvariablen i ein: Dim lngaktuellid As Long lngaktuellid speichert den jeweils zu verwendenden Primärschlüsselwert beim Anlegen eines neuen Datensatzes. Rekursive Funktion Die rekursiv definierte Funktion DateienEinlesenRek erwartet die folgenden Parameter: db: Verweis auf das Database-Objekt für die aktuelle Datenbank objfso: Verweis auf das FileSystemObject objverzeichnis: Verzeichnisse, deren enthaltene Unterverzeichnisse und Dateien in diesem Aufruf untersucht werden sollen lngverzeichnisid: Wert des Feldes DateiVerzeichnisID des übergeordneten Verzeichnisses in der Tabelle tbldateienverzeichnisse Abb. 4: Datensätze für den als Parameter übergebenen Pfad lnganzahl: Rückgabeparameter mit der Anzahl der im zu untersuchenden Unterverzeichnis enthaltenen Datenbankdateien Die Funktion DateienEinlesenRek stellt zunächst die als Parameter übergebene Variable lnganzahl auf den Wert 0 ein (s. Listing 2). Diese Variable soll, sofern das aktuelle Verzeichnis Datenbankdateien enthält, entsprechend angepasst werden. Außerdem werden noch die in den unterhalb des aktuellen Verzeichnisses befindlichen Datenbankdateien hinzugezählt. Dann prüft sie, ob der Benutzer überhaupt einen Wert für den Parameter inttiefemax angegeben hat und somit eine maximal zu durchsuchende Verzeichnistiefe. Falls ja, vergleicht sie diesen Wert mit der in inttiefe gespeicherten aktuellen Verzeichnistiefe. Sollte die maximale Tiefe erreicht worden sein, bricht die Funktion sich selbst ab. Danach untersucht die Funktion zunächst alle Dateien des aktuellen Verzeichnisses, und zwar in einer For Each-Schleife über alle Objekte der Files-Auflistung des mit objverzeichnis referenzierten aktuellen Verzeichnisses. Die folgende Select Case-Bedingung prüft den Wert der mit der Funktion GetExtensionName ermittelten Dateiendung. Hat diese den Wert mdb, accdb, mda, accda, mde oder accde, handelt es sich um eine Datenbankdatei. inttiefe: Aktuelle Verzeichnistiefe inttiefemax: Maximal zu untersuchende Verzeichnistiefe Sie können an dieser Stelle weitere Dateiendungen hinzufügen oder diese komplett ändern, um beispielsweise alle Word-Dokumente eines Verzeichnisses zu ermitteln. Wurde eine der angegebenen 53

56 Lösungen Alle Datenbanken einlesen und anzeigen Listing 2: Rekursiver Teil der Routinen zum Einlesen der Verzeichnisstruktur und der enthaltenen Dateien Public Function DateienEinlesenRek(db As DAO.Database, objfso As Scripting.FileSystemObject, _ objverzeichnis As Scripting.Folder, lngverzeichnisid As Long, inttiefe As Integer, _ inttiefemax As Integer, lnganzahl As Long) As Boolean Dim objunterverzeichnis As Scripting.Folder Dim objdatei As Scripting.File Dim lngdateiverzeichnisid As Long Dim boldiesesverzeichnisspeichern As Boolean Dim bolvaterverzeichnisspeichern As Boolean Dim lnganzahlrek As Long lnganzahl = 0 If (inttiefemax > 0) And (inttiefe > inttiefemax) Then End If Exit Function On Error Resume Next For Each objdatei In objverzeichnis.files Select Case objfso.getextensionname(objdatei.name) Case "mdb", "accdb", "mda", "accda", "mde", "accde" End Select Next objdatei lnganzahl = lnganzahl + 1 db.execute "INSERT INTO tbldateienverzeichnisse(dateiverzeichnisid, µ DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID, Pfad) VALUES(" _ & lngaktuellid & ", '" & objdatei.name & "', 0, " & lngverzeichnisid & ", '" _ & objdatei.path & "')", dbfailonerror lngaktuellid = lngaktuellid + 1 DateienEinlesenRek = True bolvaterverzeichnisspeichern = False For Each objunterverzeichnis In objverzeichnis.subfolders lngdateiverzeichnisid = lngaktuellid lngaktuellid = lngaktuellid + 1 boldiesesverzeichnisspeichern = DateienEinlesenRek(db, objfso, objunterverzeichnis, _ lngdateiverzeichnisid, inttiefe + 1, inttiefemax, lnganzahlrek) lnganzahl = lnganzahl + lnganzahlrek bolvaterverzeichnisspeichern = bolvaterverzeichnisspeichern Or boldiesesverzeichnisspeichern If boldiesesverzeichnisspeichern = True Then End If db.execute "INSERT INTO tbldateienverzeichnisse(dateiverzeichnisid, µ DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID, EnthalteneDateien) VALUES(" _ & lngdateiverzeichnisid & ", '" & objunterverzeichnis.name & "', -1, " _ & lngverzeichnisid & ", " & lnganzahlrek & ")", dbfailonerror Next objunterverzeichnis DateienEinlesenRek = DateienEinlesenRek Or bolvaterverzeichnisspeichern End Function Dateiendungen gefunden, erhöht die Funktion den Wert von lnganzahl um eins. Dann trägt sie die gefundene Datenbankdatei in die Tabelle tbldateienverzeichnisse ein, und zwar beispielsweise mit folgender SQL-Anweisung: INSERT INTO tbldateienverzeichnisse( DateiVerzeichnisID, DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID, Pfad) VALUES(12, 'ABCAnalyse.mdb', 0, 11, 'C:\Daten\...\ABCAnalyse.mdb') 54

57 Alle Datenbanken einlesen und anzeigen Lösungen Danach erhöht die Funktion den Wert von lngaktuellid um eins. Diese Variable hat eine wichtige Aufgabe: Sie liefert den Wert für den jeweils neu anzulegenden Datensatz in der Tabelle tbldateienverzeichnisse sowohl beim Anlegen von Dateien als auch bei Verzeichnissen. Weiter oben haben wir ja bereits darauf hingewiesen, dass die Tabelle tbldateienverzeichnisse keinen Autowert für das Primärschlüsselfeld verwendet, daher muss dieser Wert von der Funktion DateienEinlesenRek gepflegt werden. Um lngaktuellid nicht immer als Parameter von Aufruf zu Aufruf weiterreichen zu müssen, haben wir diese Variable extern als modulweit gültige Variable deklariert. Sie läuft also quasi neben den Funktionsaufrufen her und wird darin jeweils erhöht, um immer einen eindeutigen Primärschlüsselwert bereitzustellen. Wenn die Funktion in diesem Durchlauf mindestens eine Datenbankdatei gefunden hat, stellt sie den Wert des Rückgabewertes DateienEinlesenRek auf True ein. Dieser Wert bleibt auch erhalten, bis alle Dateien und Unterverzeichnisse des aktuellen Verzeichnisses durchlaufen wurden, und wird höchstens mehrfalls auf True eingestellt. Nachdem alle eventuell vorhandenen Dateien durchlaufen und auf Datenbankdatei-Endungen geprüft wurden, durchläuft die Funktion die enthaltenen Unterverzeichnisse ebenfalls in einer For Each-Schleife. Zuvor stellt die Prozedur noch eine Variable namens bolvaterverzeichnisspeichern auf False ein dazu später mehr. Für jedes gefundene Verzeichnis speichert die Funktion zunächst den aktuellen Wert von lng- AktuellID, unserer Primärschlüsselwert-Quelle, in der Variablen lngdateiverzeichnisid und erhöht lngaktuellid wiederum um eins. Bevor das aktuell durchlaufene Verzeichnis gespeichert wird, ruft sich die Funktion zunächst erneut selbst auf, um die in diesem Verzeichnis enthaltenen Unterverzeichnisse zu untersuchen. Warum das? Nun: Wenn Sie das Verzeichnis vorher schon speichern, ohne dass dieses eine Datenbankdatei enthält und ohne die Unterverzeichnisse zu durchsuchen, kann es sein, dass dieses Verzeichnis später wieder gelöscht werden muss. In unserer Variante des Speicherns der Verzeichnisstruktur durchlaufen wir zunächst alle Unterverzeichnisebenen und speichern Verzeichnisse erst, wenn mindestens eine Datenbankdatei in einem der Unterverzeichnisse enthalten ist. Das ist ja der Trick: Die Lösung soll nur solche Verzeichnisse liefern, die auch Datenbankdateien enthalten. Alles andere würde nur die Übersicht verschlechtern. Zurück zur Funktion: Diese ruft sich wie erwähnt erneut selbst auf, und zwar so lange, bis keine weiteren Unterverzeichnisse mehr gefunden werden oder bis die maximal zu durchsuchende Verzeichnistiefe erreicht ist. Wenn die Funktion irgendwann während dieses Vorgangs eine Datenbankdatei gefunden hat, liefert sie als Funktionswert den Wert True zurück dies geschieht ja bereits weiter oben beim Durchlaufen der im aktuellen Verzeichnis enthaltenen Dateien. Aber nicht nur das: Beim Aufruf der Funktion DateienEinlesenRek liefert der Rückgabeparameter lnganzahlrek den in diesem Aufruf ermittelten Wert der Variablen lnganzahl, also die Anzahl der im Verzeichnis gefundenen Datenbankdateien. Dieser durch die Funktion gefüllte Wert wird zum aktuellen Wert der Variablen lnganzahl hinzuaddiert. Auf diese Weise wird die Anzahl der Datenbankdateien von den untersten Verzeichnisebenen nach oben hin aufkumuliert, sodass für jedes Verzeichnis die insgesamt in allen Unterverzeichnissen enthaltene Anzahl Datenbankdateien gespeichert werden kann. Eine weitere Variable namens bolvaterverzeichnisspeichern legt fest, ob das übergeordnete Verzeichnis entweder wegen einer in diesem Verzeichnis liegenden Datenbankdatei oder wegen einer in den darunter liegenden Verzeichnissen enthaltenen Datenbankdatei gespeichert werden soll. bolvaterverzeichnisspeichern wird beim ersten Auftauchen eines Verzeichnisses mit Datenbankdatei auf True eingestellt und Ebene für Ebene in der Hierarchie der Funktionsaufrufe nach oben durchgereicht. 55

58 Lösungen Alle Datenbanken einlesen und anzeigen Hat boldiesesverzeichnisspeichern den Wert True, legt die Prozedur in der Tabelle tbldateienverzeichnisse einen Datensatz für das aktuelle Verzeichnis an. Das bedeutet, dass bei Durchlaufen eines Pfades wie c:\verzeichnis1\verzeichnis2\verzeichnis3 und dem Auffinden einer Datenbankdatei in Verzeichnis 3 die rekursive Funktion zunächst in das Verzeichnis c:\verzeichnis1\verzeichnis2\ Verzeichnis3 abtaucht und dieses speichert und erst dann c:\verzeichnis1\verzeichnis2 und c:\ Verzeichnis1. Schließlich gibt die Prozedur als Funktionswert den Wert True zurück, wenn in diesem oder einen weiteren rekursiven Aufruf mindestens eine Datenbankdatei gefunden werden konnte. Nach dem Aufruf und dem Abarbeiten der rekursiven Funktion ist die Tabelle tbldateienverzeichnisse mit den gewünschten Daten gefüllt und kann für die Anzeige im TreeView-Steuerelement weiterverwendet werden. Formular erstellen Nach den etwas umfangreicheren Vorbereitungen erstellen wir nun das Formular zur Anzeige und Auswahl von Datenbankdateien. Das Formular soll frmdateienverzeichnisse heißen. Im Kopf des Formulars legen wir ein Textfeld namens txt- Startverzeichnis zur Eingabe/Auswahl des Startverzeichnisses beim Einlesen der Verzeichnisse an. Rechts daneben platzieren wir eine Schaltfläche, die einen Verzeichnisauswahl-Dialog einblendet und die getroffene Auswahl in das Textfeld txt- Startverzeichnis überträgt. Diese Schaltfläche verwendet die folgende Prozedur, um eine im Modul mdltools befindliche Funktion zum Ermitteln eines Verzeichnisses aufzurufen: Private Sub cmdverzeichniswaehlen_click() Me!txtStartverzeichnis = _ OpenPathName(CurrentProject.Path, _ "Startverzeichnis auswählen") Darunter platzieren wir zwei Schaltflächen namens cmdeinlesen und cmdbaumfuellen. Die Schaltfläche cmdeinlesen startet die Prozedur DateienEinlesen mit dem im Textfeld angegebenen Verzeichnis: Private Sub cmdeinlesen_click() DateienEinlesen Nz(Me!txtStartverzeichnis) Die Schaltfläche cmdbaumfuellen ruft die noch zu erstellende Prozedur BaumFuellen auf: Private Sub cmdbaumfuellen_click() BaumFuellen Da das Formular nicht an eine Datenherkunft gebunden ist, können Sie Eigenschaften wie Navigationsschaltflächen, Datensatzmarkierer und Bildlaufleisten auf Nein einstellen. Dateien im TreeView-Steuerelement Nun soll das TreeView-Steuerelement mit den Daten der Tabelle tbldateienverzeichnisse gefüllt werden. Das TreeView-Steuerelement soll ein paar aussagekräftige Icons anzeigen, es soll sich merken, welche Einträge beim vorherigen Bearbeiten ein- und welche ausgeklappt waren, und es soll folgende Kontextmenüeinträge für die Datenbankeinträge bereitstellen (s. Abb. 6): Zu Verzeichnis wechseln: Öffnet das Verzeichnis, in dem sich die Datenbank befindet. Datenbank öffnen: Öffnet Access mit der angegebenen Datenbank. Löschen: Löscht die Datenbank nach vorheriger Rückfrage. Außerdem soll das Textfeld txtdatei im unteren Bereich nach einem Klick auf einen der TreeView- Einträge mit dem Namen der jeweiligen Datenbankdatei gefüllt werden. Klickt der Benutzer auf ein Verzeichnis, soll das Textfeld geleert werden. 56

59 Alle Datenbanken einlesen und anzeigen Lösungen Mit diesem lässt sich das TreeView leicht konfigurieren und füllen. Außerdem bringt der TreeViewHandler einige Funktionen wie das Speichern der Expanded- Eigenschaft mit, die Sie sonst selbst programmieren müssten. TreeViewHandler konfigurieren Alle für den TreeViewHandler benötigten Komponenten sind bereits in der Beispieldatenbank AlleDatenbankenEinlesen.mdb enthalten. Um das Steuerelement zu konfigurieren, öffnen Sie das Formular frmtreeviewconf der Beispieldatenbank. Abb. 6: Kontextmenü eines Datenbankeintrags Dies sind bereits einige Anforderungen an ein TreeView-Steuerelement. Grund genug, den TreeViewHandler, den wir zuletzt im Beitrag TreeView-Konfigurator erweitert ( vorgestellt haben, einzusetzen. Die erste Ebene soll allein den Root-Eintrag der Tabelle tbldateienverzeichnisse anzeigen, also denjenigen, dessen Feld VerzeichnisID den Wert Null enthält. Speziell für diesen Zweck haben wir eine Abfrage namens qrydateienverzeichnisseroot angelegt (s. Abb. 5), das nur den besagten Root- Eintrag liefert. Abb. 5: Diese Abfrage liefert das Root-Element für das TreeView-Steuerelement 57

60 Lösungen Alle Datenbanken einlesen und anzeigen Abb. 7: Eigenschaften für das Root-Element im TreeView-Konfigurator Im TreeView-Konfigurator legen Sie nun einen neuen Eintrag an und stellen die Eigenschaften wie in Abb. 7 ein: Tabelle/Abfrage: qrydateienverzeichnisseroot Primärschlüssel: DateiVerzeichnisID Schlüssel: v0 Elementtext/Feld: DateiVerzeichnisname Icon/Standardwert: folder.png Expanded-Wert: Expanded Aktiv: Wahr Zur Eigenschaft Icon ist anzumerken, dass wir die verwendeten Bilddateien zunächst mit dem Tool aus dem Artikel Bilder per Add-In in OLE- Feld speichern ( de/890) in der Tabelle tblimages gespeichert haben. Der TreeView-Konfigurator verwendet eine solche Tabelle, um die Bilddateien für die Tree- View- und Kontextmenü-Icons zu beziehen. Wir wollen diesen einen Eintrag zunächst im Tree- View-Steuerelement erscheinen lassen. Dazu fügen Sie dem Formular frmdateienverzeichnisse ein ImageList-Steuerelement namens ctlimage- List und ein TreeView-Steuerelement namens ctltreeview hinzu. Dazu legen Sie zunächst eine Objektvariable für die TreeViewHandler-Klasse im Kopf des Klassenmoduls Form_frmDateienVerzeichnisse an: Dim WithEvents objtreeviewhandler As clstreeviewhandler Fügen Sie dann eine Ereignisprozedur hinzu, die durch das Ereignis Beim Laden des Formulars ausgelöst wird. Diese enthält aktuell nur eine einzige Anweisung: Private Sub Form_Load() BaumFuellen Die hier aufgerufene Prozedur BaumFuellen sieht wie folgt aus: Abb. 8: Das TreeView-Steuerelement zeigt zunächst nur das Root-Element an. Private Sub BaumFuellen() Set objtreeviewhandler = New clstreeviewhandler 58

61 Alle Datenbanken einlesen und anzeigen Lösungen With objtreeviewhandler Set.TreeViewInst = Me!ctlTreeview.Object Set.ImageListInst = Me!ctlImageList.Object End With.InitTreeView (7).Style = tvwtreelinesplusminuspicturetext.linestyle = tvwrootlines.indentation = 5.FontName = "Calibri".FontSize = 10.LabelEdit = tvwmanual.filltree Die Prozedur instanziert ein neues Objekt auf Basis der Klasse clstreeviewhandler und stellt dessen Eigenschaften ein. Unter anderem weist sie ihr zunächst Objektverweise auf das zu verwendende ImageList- und das TreeView-Steuerelement zu. Dann stellt sie mit der InitTreeView-Methode die ID der zu verwendenden TreeView-Konfiguration aus dem Formular frmtreeviewconf ein in diesem Fall lautet diese 7 (sieht frmtreeviewconf, oben links unter Aktuelle ID). Danach legt die Prozedur einige optische Eigenschaften fest und füllt das TreeView-Steuerelement schließlich mit der FillTree-Methode. Im ersten Versuch sieht dies wie in Abb. 8 aus. Weitere Verzeichnisse anzeigen Nun folgt ein weiterer Eintrag im TreeView-Konfigurator, der für die erste Ebene unter dem Root- Element verantwortlich ist. Auch für diesen legen wir wieder eine spezielle Datenherkunft an sie sieht wie in Abb. 9 aus und heißt qryverzeichnissebaum. Das zweite Feld dieser Abfrage mit dem Namen DateiVerzeichnis enthält den folgenden Ausdruck: DateiVerzeichnis: [DateiVerzeichnisname] & Wenn([EnthalteneDateien];" (" & [EnthalteneDateien] & ")";"") Dieser ergänzt den Verzeichnisnamen gegebenenfalls um die in Klammern eingefasste Anzahl der in diesem Verzeichnis enthaltenen Datenbankdateien. Für das Feld IstVerzeichnis haben wir als Kriterium Wahr eingestellt und für das Fremdschlüsselfeld VerzeichnisID das Kriterium Ist Nicht Null. Auf diese Weise werden nur Verzeichnisse erfasst, und nur solche, die Unterverzeichnis eines anderen Verzeichnisses sind. Im TreeView-Konfigurator stellen Sie die folgenden Eigenschaften für den neuen Eintrag für diese Ebene ein: Abb. 9: Datenherkunft für die zweite und die folgenden Ebenen im TreeView-Steuerelement 59

62 Lösungen Alle Datenbanken einlesen und anzeigen Tabelle/Abfrage: qryverzeichnissebaum Übergeordnete Tabelle: qrydateienverzeichnisseroot Primärschlüssel: DateiVerzeichnisID Fremdschlüssel: VerzeichnisID Schlüssel: vv Die übrigen Eigenschaften entsprechen denen des übergeordneten Elements. Durch diesen Eintrag werden in der zweiten Ebene des TreeViews alle Einträge der Abfrage qryverzeichnissebaum eingefügt, deren Fremdschlüsselfeld VerzeichnisID dem Primärschlüsselfeld des Elements der ersten Ebene entspricht. Weitere Verzeichnisebenen Nun wollen wir nicht jede Ebene einzeln anlegen (das wäre auch kompliziert, da wir nicht wissen, wie viele Ebenen es gibt). Aber wir wissen ja, dass die Tabelle tbldateien- Verzeichnisse mit sich selbst verknüpfte Elemente enthält. Und da der TreeView-Konfigurator auch reflexive Daten unterstützt, legen wir dort als weitere Ebene eine solche an. Die Eigenschaften sehen so aus: Abb. 10: Rekursiv angelegte Verzeichnisstruktur Tabelle/Abfrage: qryverzeichnissebaum Übergeordnete Tabelle: qryverzeichnisbaum Primärschlüssel: DateiVerzeichnisID Fremdschlüssel: VerzeichnisID Schlüssel: vr Die Elemente für diesen Eintrag referenzieren also Elemente der gleichen Tabelle, deren Primärschlüsselfeld den Wert des Fremdschlüsselfelds des aktuellen Datensatzes aufweist. Auf diese Weise werden die folgenden Verzeichnisebenen rekursiv angelegt. Das Zwischenergebnis sieht wie in Abb. 10 aus. Dateien im TreeView Abb. 11: Datenherkunft für die Datei-Ebene im TreeView-Steuerelement Nun fehlen nur noch die Dateien der jeweiligen Verzeichnisse. Dazu legen Sie eine vierte und letzte Ebene im TreeView-Konfigurator an. Auch diese basiert wieder auf einer eigens zu diesem Zweck erzeugten Abfrage. Sie heißt qrydateienbaum und sieht wie in Abb. 11 aus. Die Besonderheit dieser Abfrage liegt darin, dass sie ausschließlich 60

63 Alle Datenbanken einlesen und anzeigen Lösungen solche Datensätze liefert, deren Feld IstVerzeichnis den Wert Falsch enthält. Die Eigenschaften für den entsprechenden Eintrag im TreeView-Konfigurator lauten wie folgt: Tabelle/Abfrage: qrydateienbaum Übergeordnete Baum Tabelle: qryverzeichnisse- Primärschlüssel: DateiVerzeichnisID Fremdschlüssel: VerzeichnisID Schlüssel: dd Icon/Standard (abweichend von den Verzeichnis-Einträgen): data_16.png Beim nächsten Anzeigen des Formulars frm- DateienVerzeichnisse erscheinen nun auch die Einträge für die Datenbankdateien im TreeView- Steuerelement. Kontextmenüeinträge Für die im TreeView angezeigten Dateien fehlen noch die Kontextmenü-Einträge. Diese fügen Sie ebenfalls über den TreeView-Konfigurator hinzu. Dazu tragen Sie im unteren Bereich einfach die Bezeichnungen ein und geben die Bilddateien an (s. Abb. 12). Außerdem können Sie unter ContextmenuParameter noch einen Parameter eintragen, der beim Anklicken eines der Kontextmenü-Einträge an die dadurch ausgelöste Ereignisprozedur weitergeleitet wird. Die Einträge sehen wie folgt aus: Zu Verzeichnis wechseln: Parameter Show- Folder, Image folder.png Datenbank öffnen: Parameter OpenDatabase, Image data_16.png Löschen: Parameter Delete, Image delete.png Nun fehlen nur noch ein paar Ereignisprozeduren. Abb. 12: Konfiguration für die Dateieinträge samt Kontextmenü-Einträgen 61

64 Lösungen Alle Datenbanken einlesen und anzeigen Listing 3: Ereignisprozedur, die durch das Anklicken eines Kontextmenü-Eintrags ausgelöst wird Private Sub objtreeviewhandler_shortcutmenuclick(objnode As MSComctlLib.Node, _ strparameter As String, strthistable As String, strtablebase As String, strpkid As String, _ dblpkidvalue As Double) Dim strdateiname As String strdateiname = DLookup("Pfad", "tbldateienverzeichnisse", "DateiVerzeichnisID = " & dblpkidvalue) Select Case strparameter Case "Delete" If MsgBox("Datei '" & strdateiname & "' löschen?", vbyesno + vbexclamation, _ "Datei löschen") = vbyes Then Kill strdateiname objtreeviewhandler.deletecurrentnode End If Case "OpenDatabase" Shell "Explorer.exe " & strdateiname, vbnormalfocus Case "ShowFolder" strdateiname = Left(strDateiname, InStrRev(strDateiname, "\")) Shell "Explorer.exe " & strdateiname, vbnormalfocus End Select Ereignisprozeduren des TreeView- Steuerelements Schauen wir uns zunächst die Prozedur an, die durch das Betätigen der Kontextmenü-Einträge ausgelöst wird. Diese fügen Sie dem Klassenmodul Form_frmDateienVerzeichnisse über die Kombinationsfelder oben im Code-Fenster hinzu (links objtreeviewhandler auswählen, rechts ShortcutMenuClick). Die nun erscheinende Prozedur ergänzen Sie wie in Listing 3. Die Prozedur ermittelt zunächst per DLookup-Funktion den Pfad der Datei, die der Benutzer mit der rechten Maustaste angeklickt hat. Sie erhält außerdem über den Parameter strparameter den für ContextMenuParameter festgelegten Ausdruck, also entweder Delete, Open- Database oder ShowFolder. In Abhängigkeit davon führt die Prozedur einen der drei Zweige der Select Case-Bedingung aus. Der erste löscht die aktuelle Datenbankdatei nach vorheriger Rückfrage, der zweite öffnet den Windows Explorer und navigiert dort gleich zum Verzeichnis, in dem sich die Datenbank befindet, und der dritte öffnet die Datenbank mit Access. Bei Klick Dateipfad anzeigen Eine weitere Ereignisprozedur wird durch einen Mausklick auf einen beliebigen Eintrag im TreeView-Steuerelement ausgelöst. Die Prozedur heißt objtreeviewhandler_nodeclick und liefert beispielsweise den Primärschlüsselwert des angeklickten Elements. Damit ermittelt die Ereignisprozedur den passenden Dateinamen aus der Tabelle tbldateienverzeichnisse und zeigt diesen im Textfeld txtdatei Listing 4: Ereignisprozedur, die durch das Anklicken eines Datei-Eintrags ausgelöst wird Private Sub objtreeviewhandler_nodeclick(objnode As MSComctlLib.Node, strtable As String, _ strtablebase As String, strpkid As String, dblpkid As Double) Me!txtDatei = DLookup("Pfad", "tbldateienverzeichnisse", "DateiVerzeichnisID = " & dblpkid) 62

65 Lösungen Alle Datenbanken einlesen und anzeigen Listing 5: Aufruf des Formulars mit Rückgabe der gewählten Datenbankdatei Public Function DatenbankErmitteln(strPfad As String) DoCmd.OpenForm "frmdateienverzeichnisse", WindowMode:=acDialog, OpenArgs:=strPfad If IstFormularGeoeffnet("frmDateienVerzeichnisse") Then DatenbankErmitteln = Forms!frmDateienVerzeichnisse!txtDatei DoCmd.Close acform, "frmdateienverzeichnisse" End If End Function an, den wir noch unterhalb des TreeView-Steuerelements einfügen (s. Listing 4). Rückgabe des gewählten Verzeichnisnamens Der Sinn des Formulars besteht unter anderem darin, zu bestimmten Gelegenheiten zu erscheinen, die Auswahl einer Datenbankdatei zu erlauben und diese dann weiterzuverarbeiten. Dies gelingt mit ein paar Erweiterungen der aktuellen Version. Die Funktion aus Listing 5 öffnet das Formular als modalen Dialog und wartet, bis dieses wieder geschlossen wird. Da Sie einem geschlossenen Formular keine gewählten Werte mehr entlocken können, wird es nicht direkt geschlossen, sondern unsichtbar gemacht so läuft der aufrufende Code weiter und kann direkt auf die Steuerelemente des Formulars zugreifen. Im Formular realisieren wir das Verstecken des Formulars durch eine OK-Schaltfläche mit folgender Ereignisprozedur: Private Sub cmdok_click() Me.Visible = False Nach dem Schließen liest die Funktion DatenbankErmitteln den Inhalt des Textfeldes txtdatei aus und schließt das Formular dann endgültig. Damit das Formular direkt das gewünschte Startverzeichnis anzeigt, erlaubt die Funktion DatenbankErmitteln die Angabe einer entsprechenden Zeichenkette. Diese leitet die Funktion per Open- Args-Parameter an das zu öffnende Formular weiter. Beim Öffnen des Formulars wertet die erweiterte Fassung der Form_Load-Prozedur das Öffnungsargument aus und schreibt es in die Variable straktuellesverzeichnis. Nun ist es so, dass es nicht gerade trivial ist, genau das gewünschte Element im TreeView-Steuerelement aufzuklappen. Deshalb benötigen wir dazu eine eigene Prozedur namens ZielverzeichnisAusklappen. Diese erwartet das gewünschte Verzeichnis sowie eine weitere Variable, welche den Wert der Eigenschaft Key des resultierenden Elements zurückliefert. Dieses verarbeitet die Prozedur weiter, indem sie genau dieses Element mit der ClickNode-Methode des TreeViewHandler-Objekts markiert: Private Sub Form_Load() Dim strkey As String Dim straktuellesverzeichnis As String straktuellesverzeichnis = Nz(Me.OpenArgs) If Len(strAktuellesVerzeichnis) > 0 Then End If ZielverzeichnisAusklappen _ BaumFuellen straktuellesverzeichnis, strkey If Len(strKey) > 0 Then End If objtreeviewhandler.clicknode,, strkey Die Prozedur ZielverzeichnisAusklappen wirkt sich nicht direkt auf die Anzeige der Elemente im TreeView-Steuerelement aus. Daher ist vor dem Markieren des Zielelements noch die Anzeige mit der Prozedur BaumFuellen zu aktualisieren. 63

66 Lösungen Alle Datenbanken einlesen und anzeigen Listing 6: Prozedur, die alle Elemente bis zum angegebenen Verzeichnis ausklappt Private Sub ZielverzeichnisAusklappen(strVerzeichnis As String, strkey As String) Dim lngdateiverzeichnisid As Long Dim lngverzeichnisid As Long Dim db As DAO.Database Set db = CurrentDb lngdateiverzeichnisid = Nz(DLookup("DateiVerzeichnisID", "tbldateienverzeichnisse", _ "Pfad LIKE '" & strverzeichnis & "*'"), 0) lngverzeichnisid = Nz(DLookup("VerzeichnisID", "tbldateienverzeichnisse", _ "DateiVerzeichnisID = " & lngdateiverzeichnisid), 0) If Not lngverzeichnisid = 0 Then ElementMarkierenRek db, lngdateiverzeichnisid, Len(strVerzeichnis) - _ Len(Replace(strVerzeichnis, "\", "")) + 1, strkey End If Direktes Anzeigen eines Verzeichnisses beim Öffnen Das Arbeitstier beim Ausklappen eines gewünschten Zielverzeichnisses ist die Prozedur ZielverzeichnisAusklappen mit ihrer rekursiven Ergänzung ElementMarkierenRek (s. Listing 6). Die erstgenannte Prozedur erwartet die genannten Parameter und ermittelt zunächst einen Eintrag aus der Tabelle tbldateienverzeichnisse, dessen Pfad dem mit strverzeichnis übergebenen nahekommt. Mit dessen Primärschlüsselwert ermittelt die Prozedur dann den übergeordneten Eintrag. Ist dieser vorhanden, ruft die Prozedur die rekursive Funktion ElementMarkierenRek auf. Bevor wir diese ansehen, ein Ausblick auf das, was nun geschieht: Wir haben in der Tabelle tbldateienverzeichnisse den Datensatz ermittelt, der dem Pfad zu dem zu markierenden Element im TreeView entspricht. Nun wollen wir dafür sorgen, dass dieses angezeigt wird. Dazu müssen wir den Wert des Feldes Expanded für diesen Datensatz und für alle Datensätze, die diesem direkt übergeordnet sind, auf den Wert True einstellen. Wenn wir dann das TreeView-Steuerelement neu füllen, sollten alle Elemente bis zum Zielelement ausgeklappt sein und das Zielelement kann markiert werden. Die Funktion ElementMarkierenRek Zum Einstellen des Feldes Expanded auf den Wert True arbeiten wir uns Stück für Stück in der Hierarchie nach oben. Dazu benötigen wir eine rekursiv definierte Funktion, in diesem Fall ElementMarkierenRek (s. Listing 7). Diese erwartet als Parameter einen Verweis auf das aktuelle Database-Objekt, die ID des zu untersuchenden Elements, eine Variable zum Übergeben der Verzeichnistiefe (ermittelt aus der Anzahl der Backslash-Zeichen des Verzeichnisses) und die Variable strkey, welche die Key-Eigenschaften der einzelnen Elemente bis zum Zielverzeichnis auflistet. Dazu müssen Sie wissen, dass der TreeView- Konfigurator den Wert der Eigenschaft Key hierarchisch anlegt. Das bedeutet, dass das Root- Element v01 heißt, das erste untergeordnete Element v01 vv1, das nächste v01 vv1 vr1 und so weiter. Wenn wir also am Ende das gewünschte Verzeichnis-Element markieren möchten, müssen wir die Key-Eigenschaft genau zusammenstellen. Und hier folgt auch der Grund, warum die Eigenschaft als rekursive Funktion ausgelegt ist und nicht einfach als Do While-Schleife, die bis zum Erreichen des Root-Elements läuft: Die Funktion navigiert vom Ziel-Element nach oben bis zum Root-Element und stellt derweil das Expanded- Feld für alle durchlaufenen Elemente auf True ein. Hinter dem Aufruf der rekursiven Funktion folgt jedoch immer noch eine Anweisung, die den Key aus dem in strkey gelieferten bisherigen Key- Ausdruck und dem aktuellen Key-Wert zusammensetzt. 64

67 Lösungen Alle Datenbanken einlesen und anzeigen Listing 7: Rekursiver Teil der Funktion zum Ausklappen bis zu einem bestimmten Verzeichnis Private Sub ElementMarkierenRek(db As DAO.Database, lngverzeichnisid As Long, intlevel As Integer, _ Optional ByRef strkey As String) Dim lngdateiverzeichnisid As Long lngdateiverzeichnisid = lngverzeichnisid lngverzeichnisid = Nz(DLookup("VerzeichnisID", "tbldateienverzeichnisse", _ "DateiVerzeichnisID = " & lngverzeichnisid), 0) If Not lngverzeichnisid = 0 Then lngdateiverzeichnisid = lngverzeichnisid db.execute "UPDATE tbldateienverzeichnisse SET Expanded = True WHERE DateiVerzeichnisID = " _ & lngdateiverzeichnisid, dbfailonerror Select Case intlevel Case 1 strkey = " v0" & lngdateiverzeichnisid & strkey Case 2 strkey = " vv" & lngdateiverzeichnisid & strkey Case Else strkey = " vr" & lngdateiverzeichnisid & strkey End Select ElementMarkierenRek db, lngverzeichnisid, intlevel - 1, strkey If Left(strKey, 1) = " " Then strkey = Mid(strKey, 2) End If End If Die Funktion speichert den Primärschlüsselwert des aktuellen Elements in lngdateiverzeichnis- ID zwischen und ermittelt dann per DLookup den Primärschlüsselwert des übergeordneten Elements. Solange die Prozedur noch nicht beim Root-Element angekommen ist (lngverzeichnisid = 0), ändert sie die Eigenschaft des Feldes Expanded für den übergeordneten Datensatz auf Wahr. Außerdem ermittelt sie anhand der in intlevel gespeicherten Verzeichnisebene, ob die Funktion gerade die erste, zweite oder eine andere Ebene beackert. Die ersten beiden werden gemäß Konfiguration des TreeViews mit den Key-Präfixen v0 und vv versehen, die übrigen mit vr. Dies ist wichtig für das Zusammenstellen des Key-Wertes für den später zu markierenden Datensatz. Neben den Präfixen besteht der Key-Wert übrigens aus dem Primärschlüsselwert des jeweiligen Datensatzes. Nach dem rekursiven Aufruf der Funktion für die nächsthöhere Ebene erweitert die Funktion noch den Inhalt von strkey um den aktuellen Key-Wert. Auf diese Weise stellt die Prozedur die Expanded- Eigenschaft für alle Elemente des Pfades auf True ein und markiert nach dem Neufüllen des Tree- View-Steuerelements das angegebene Verzeichnis. Zusammenfassung und Ausblick Mit der hier vorgestellten Lösung erweitern Sie Anwendungen um die Möglichkeit, Datenbankdateien komfortabel auszuwählen. Vielleicht möchten Sie die Datenbank auch als Basis für eigene Add-Ins verwenden, um beispielsweise Datenbanken für den Export oder Import von Daten auszuwählen. Grundsätzlich ist dies eine einfache Möglichkeit, um schnell nur auf die Datenbankdateien im Dateisysten zuzugreifen. 65

68 Lösungen Abonnements verwalten, Teil 3 Abonnements verwalten, Teil 3 André Minhorst, Duisburg Die ersten beiden Teile dieser Beitragsreihe haben uns Formulare zum Verwalten von Produkten, Abonnements und Kunden sowie Funktionen zum Anlegen, Verlängern, Kündigen und Stornieren der Abonnements beschert. Fehlt nur noch eine wichtige Funktion: der Versand der jeweiligen Ausgaben beziehungsweise die Lieferung der Empfängerlisten. Von der Aboverwaltung zum Versand Wenn Sie Produkte, Kunden und Abonnements in einer Datenbank verwalten was definitiv sinnvoll ist, denn mit steigender Kunden- und Abonnementzahl wird es schnell unübersichtlich, benötigen Sie eine optimale Vorbereitung des eigentlichen Versands einer jeden Ausgabe. Dabei kommt es zunächst darauf an, um was für ein Medium es sich überhaupt handelt. Es könnte um ein Printmagazin im klassischen Sinne gehen, wobei die Anwendung eine Liste der Adressaten der aktuellen Ausgabe ausspucken sollte. Wenn Sie das Magazin selbst versenden, drucken Sie auf Basis der Adressenliste entsprechende Adressetiketten oder gleich mit Porto versehene Aufkleber. Kümmert sich ein Dienstleister um den Versand, schicken Sie ihm die Liste der Adressaten zu. Vielleicht handelt es sich auch um ein Onlinemagazin. Hier gibt es wiederum mindestens zwei verschiedene Möglichkeiten: entweder Sie verschicken das Magazin etwa im PDF-Format direkt Zusammenfassung Lernen Sie eine Anwendung zum Verwalten von Abonnements, Kunden, Produkten und Ausgaben kennen. Techniken Abfragen, Formulare, VBA Voraussetzungen Access 2000 und höher Beispieldateien Abonnementverwaltung.mdb Shortlink /889 per an den Kunden. Oder Sie stellen das Magazin auf einer Webseite zum Download bereit und schicken dem Kunden einen entsprechenden Link. Wir schauen uns in diesem Beitrag sowohl die Möglichkeit der Listenerstellung als auch die des Versands des Produkts per an. Versand protokollieren Wichtig ist in beiden Fällen, dass Sie den Versand einer Ausgabe an einen Kunden im Rahmen eines Abonnements vermerken am besten unter Angabe des Versanddatums. Dabei ist mit Versanddatum allerdings nur im Falle des -Versands das tatsächliche Versanddatum gemeint. Sollte eine Liste mit dem Adressaten erstellt werden, um diese an einen Dienstleister weiterzuleiten oder erstellen Sie selbst Adressetiketten, vermerkt die Anwendung das Datum, an dem die Ausgabe für den Versand vorgemerkt wurde. Ausgabe auswählen Wenn Sie wie in den vorherigen Folgen der Beitragsreihe bereits Tabellen und Formulare zur Verwaltung von Produkten, Ausgaben, Abonnements und Versendungen erstellt haben, können Sie damit leicht auch den Versand einer Ausgabe organisieren. Wie starten wir diesen Vorgang? Am einfachsten ist es, zunächst das Produkt und die zu versendende Ausgabe zu ermitteln. Dazu erstellen wir ein Formular namens frmversendungen. Dieses binden wir nicht an die Datenherkunft, sodass wir die Eigenschaften Navigationsschaltflächen, Datensatzmarkierer und Bildlaufleisten auf Nein einstellen können. 66

69 Abonnements verwalten, Teil 3 Lösungen Diesem Formular fügen Sie zunächst ein Kombinationsfeld namens cboprodukte zur Auswahl des zu versendenden Produkts hinzu. Dieses verwendet die Tabelle tblprodukte als Datenherkunft. Damit das Kombinationsfeld nur den Produktnamen und nicht den Primärschlüsselwert als gebundene Spalte anzeigt, stellen Sie die Eigenschaften Spaltenanzahl und Spaltenbreiten auf die Werte 2 und 0cm ein. Nach der Auswahl des Produkts folgt schon die Festlegung der Ausgabe, deren Exemplare versendet werden sollen und zwar mit einem weiteren Kombinationsfeld namens cboausgaben (s. Abb. 1). Am einfachsten ist es, darin einfach alle Ausgaben anzuzeigen. Allerdings sollte die Liste zumindest eine Einschränkung nach dem zuvor gewählten Produkt enthalten. Noch schöner wäre es, wenn zusätzlich nur diejenigen Ausgaben angezeigt würden, für die überhaupt Versendungen geplant sind für die also entsprechende Datensätze in der Tabelle tblversendungen vorliegen. Abb. 1: Erstellen eines Formulars zum Auswählen von Produkt und Ausgabe Um diese Ausgaben zu ermitteln, erstellen wir eine neue Abfrage namens qryausgabennach- ProduktIDOffen (s. Abb. 2). Diese Abfrage enthält nicht nur die beiden Tabellen tblausgaben und tblprodukteausgaben, die für die Ermittlung aller Ausgaben eines Produkts nötig wären, sondern zusätzlich noch die Tabelle tblversendungen. Dies ermöglicht gleichzeitig die Berechnung der offenen Versendungen einer Ausgabe eines bestimmten Produkts. Die Felder AusgabeID und AusgabeBezeichnung sollen später im Kombinationsfeld cboausgaben erscheinen. ProduktID dient dem Filtern nach dem Produkt, das der Benutzer im Kombinationsfeld cboprodukte festgelegt hat. AusgabeJahr und AusgabeNummer sortieren die Datensätze chronologisch. Bei den beiden letzten Feldern wird es interessant. Zunächst einmal aktivieren Sie die Gruppierungsfunktion für die Abfrage, denn anderenfalls würde sie im Ergebnis jede Ausgabe entsprechend der Anzahl der passenden Datensätze in der Tabelle tblversendungen ausgeben. Es soll aber jede Ausgabe nur einmal erscheinen. Daher gruppieren wir nach allen Feldern der Tabellen tblausgaben und tblprodukteausgaben. Das Feld Versanddatum der Tabelle tblversendungen wird mit der Funktion Bedingung versehen und mit dem Kriterium Ist Null ausgestattet. Außerdem wird es ausgeblendet. Das Feld Offen mit dem Ausdruck VersendungID versehen Sie mit der Funktion Anzahl, damit dieses die Anzahl der Datensätze der Tabelle tblversendungen zu- Abb. 2: Datensatzherkunft des Kombinationsfeldes zur Anzeige der offenen Ausgaben 67

70 Lösungen Abonnements verwalten, Teil 3 rückgibt, die noch nicht als versendet gekennzeichnet wurden. Das Ergebnis der Abfrage sieht wie in Abb. 3 aus. Damit das Kombinationsfeld cboausgaben nach der Auswahl eines der Einträge des Kombinationsfeldes cbo- Produkte die gewünschten Daten anzeigt, fügen Sie für die Ereignisprozedur Nach Aktualisierung von cbo- Produkte die Prozedur aus Listing 1 hinzu. Abb. 3: Anzahl der noch zu versendenden Exemplare je Ausgabe und Produkt Diese ermittelt die AusgabeID und einen aus der Bezeichnung und der Anzahl der offenen Versendungen zusammengesetzten Ausdruck für das gewählte Produkt und zeigt nach der Auswahl eines Produkts gleich die Liste der Ausgaben mit noch offenen Versendungen an (s. Abb. 4). Zu versendende Exemplare in Unterformular anzeigen Nun benötigen wir ein Unterformular oder ein Listenfeld zur Anzeige der noch offenen Versendungen, das mit der Auswahl des Kombinationsfeldes cboausgaben gefüllt wird. Da wir auch die Möglichkeit offenhalten möchten, eine Versendung manuell einzutragen, verwenden wir ein Unterformular Abb. 4: Anzeige der Ausgaben mit noch offenen Versendungen in der Datenblattansicht, um die offenen Versendungen anzuzeigen. Dieses soll den Kunden mit Bezeichnung und -Adresse sowie ein Feld zur Eingabe des Versanddatums anzeigen. Listing 1: Aktualisieren des Kombinationsfeldes zur Anzeige der offenen Ausgaben Private Sub cboprodukte_afterupdate() Dim strsql As String strsql = "SELECT AusgabeID, AusgabeBezeichnung & '(' & Offen & ')' AS Ausgabe µ FROM qryausgabennachproduktidoffen WHERE ProduktID = " & Me!cboProdukte With Me!cboAusgaben.RowSource = strsql.setfocus.dropdown End With 68

71 Abonnements verwalten, Teil 3 Lösungen Abb. 5: Datenherkunft des Unterformulars zur Anzeige aller noch zu versendenden Exemplare Dies erledigt die Abfrage aus Abb. 5. Die Abfrage liefert alle offenen Versendungen inklusive der Kunden aus der Tabelle tblkunden, die über die Tabelle tblabonnements mit tblversendungen verknüpft ist. Die gelieferten Datensätze werden dabei auf solche eingeschränkt, deren Feld Versanddatum den Wert Null enthält. Das Unterformular sfmversendungen zeigt die Felder VersendungID, Kundenbezeichnung, und Versanddatum dieser Abfrage an und wird wie in Abb. 6 in das Hauptformular frmversendungen eingebettet. Da das Hauptformular keine Datenherkunft hat, kann Access beim Einfügen des Unterformulars auch nicht automatisch eine Verknüpfung zwischen den Daten aus Haupt- und Unterformular herstellen. Dies erledigen wir manuell: Die Eigenschaft Verknüpfen von erhält den Wert AusgabeID, die Eigenschaft Verknüpfen nach den Wert des Steuerelements cboausgaben. Auf diese Weise zeigt das Unterformular immer die zum aktuell mit diesem Kombinationsfeld ausgewählten Datensätze an. Dies sieht schließlich wie in Abb. 7 aus. Versandliste erstellen Nun benötigen wir verschiedene Möglichkeiten, um die offenen Versendungen durchzuführen. Allen gemein ist, dass das Feld Versanddatum anschließend das entsprechende Datum enthalten soll. Als erstes Beispiel wollen wir eine Versandliste für die Weiterverarbeitung in einer anderen Anwendung erstellen. Dazu fügen Sie eine Schaltfläche namens cmdversandtextdatei zum Formular hinzu. Abb. 6: Unterformular zur Anzeige der noch offenen Versendungen mit den Verknüpfungseigenschaften zwischen Haupt- und Unterformular Diese Schaltfläche löst die Prozedur aus Listing 2 aus. Dort wollen wir mit der TransferText-Methode eine 69

72 Lösungen Abonnements verwalten, Teil 3 Textdatei auf Basis der im Unterformular angezeigten Daten erstellen. Leider ist dies nicht so einfach möglich, da die Daten dieses Formulars über die Verknüpfen von/verknüpfen nach-eigenschaften gefiltert werden. Die einfache Angabe der Datenherkunft des Formulars als Parameter der TransferText-Methode ist somit nicht möglich aber das ist auch nicht schlimm, da wir für die Ausgabe ohnehin den kompletten Satz Kundendaten aus der Tabelle tblkunden exportieren möchten. Also erstellen wir eine temporäre Abfrage auf Basis einer neuen Abfrage namens qrykundenausgaben (s. Abb. 8), deren AusgabeID mit dem entsprechenden Wert im Kombinationsfeld cboausgaben im Hauptformular übereinstimmt. Diese Abfrage übergeben wir dann als Parameter an die TransferText-Methode. Ein weiterer Parameter dieser Methode ist der Dateiname. Dieser soll etwa wie folgt gestaltet werden: Abb. 7: Anzeige der noch offenen Versendungen im Unterformular Versand_Access_im_Unternehmen_2013_1.txt Dazu stellt die Prozedur einige Informationen aus dem Hauptformular und aus der Tabelle tblausgaben zusammen und ersetzt einige Sonderzeichen wie das Leerzeichen oder den Schrägstrich. Vorbereitend müssen Sie ab Access 2007 noch eine Export-Spezifikation für diese Tabelle erstellen, da sonst ein Fehler beim Aufruf der Transfer- Listing 2: Start des Versands durch Übertragen der Kundendaten in eine Textdatei Private Sub cmdversandtextdatei_click() Dim db As DAO.Database Dim qdf As DAO.QueryDef Dim strdateiname As String Dim strausgabe As String Set db = CurrentDb On Error Resume Next db.querydefs.delete "qrytemp" On Error GoTo 0 Set qdf = db.createquerydef("qrytemp", "SELECT * FROM qrykundenausgaben WHERE AusgabeID = " _ & Me!cboAusgaben) strausgabe = DLookup("AusgabeJahr & '_' & AusgabeNummer", "tblausgaben", "AusgabeID = " _ & Me!cboAusgaben) strdateiname = CurrentProject.Path & "\Versand_" & Me!cboProdukte.Column(1) & "_" & strausgabe _ & ".txt" strdateiname = Replace(strDateiname, "/", "_") strdateiname = Replace(strDateiname, " ", "_") DoCmd.TransferText acexportdelim, "Spec_qryKundenAusgaben", "qrytemp", strdateiname db.execute "UPDATE tblversendungen SET Versanddatum = " & ISODatum(Now) _ & " WHERE AusgabeID = " & Me!cboAusgaben, dbfailonerror Me!sfmVersendungen.Form.Requery Me!cboAusgaben.Requery 70

73 Abonnements verwalten, Teil 3 Lösungen Abb. 8: Datenherkunft für den Textexport Text-Methode ausgelöst wird. Mehr dazu erfahren Sie im Beitrag VBA-Textexport unter Access 2007 und jünger (/887). Schließlich wird die TransferText-Methode ausgeführt. Anschließend ändert die Prozedur noch das Feld Versanddatum auf den aktuellen Zeitpunkt und aktualisiert das Kombinationsfeld cbo- Ausgaben und das Unterformular. Mit der daraus resultierenden Textdatei können Sie dann weitere Anwendungen füttern. Ausgaben per verschicken Vielleicht verschicken Sie die Ausgaben Ihres Abonnements per als PDF. In diesem Fall gelingt dies am einfachsten per Outlook. Für die Versendung per sind Änderungen am Datenmodell nötig. Die erste ist ein neues Feld in der Tabelle tblversendungen. Das Feld heißt MailingID und soll den Datensatz einer ebenfalls neu zu erstellenden Tabelle referenzieren, welcher Detailinformationen zu der zu versendenden E- Mail enthält. Diese Tabelle enthält die Felder aus Abb. 9. Das Feld AusgabeID referenziert die betroffene Ausgabe aus der Tabelle tblausgaben. Dem Formular frmversenden fügen wir eine Schaltfläche namens cmdversand hinzu. Dieses soll ein weiteres Formular aufrufen, mit dem Sie das Mailing vorbereiten können. Diese Schaltfläche löst die Prozedur aus Listing 3 aus. Die DoCmd.OpenForm-Anweisung öffnet das Formular frmmailings und übergibt die ID des Produkts und der Ausgabe per Öffnungsargument an das Formular getrennt durch das Pipe-Zeichen ( ). Das zu öffnende Formular frmmailings soll dann etwa wie in Abb. 10 aussehen. Damit dies der Fall ist, sind noch einige VBA- Anweisungen nötig. Zunächst einmal nutzt das Formular die folgenden beiden Variablen, um die übergebenen Daten zu speichern und während der Nutzung des Formulars modulweit nutzbar zu machen. Die Variablen legen Sie im Modul Form_ frmmailings an: Dim lngproduktid As Long Dim lngausgabeid As Long Abb. 9: Entwurf der Tabelle zum Speichern der Mailing- Daten 71

74 Lösungen Abonnements verwalten, Teil 3 Listing 3: Aufruf des Mailing-Formulars Private Sub cmdversand _click() If Not IsNull(Me!cboProdukte) And Not IsNull(Me!cboAusgaben) Then DoCmd.OpenForm "frmmailings", OpenArgs:=Me!cboProdukte & " " & Me!cboAusgaben Else MsgBox "Wählen Sie Produkt und Ausgabe aus." End If Einen Anhang fügen Sie mit einem Klick auf die Schaltfläche cmdanhang hinzu: Private Sub cmdanhang_click() Me!Anhang = OpenFileName(CurrentProject.Path, _ "Anhang auswählen", "Alle Dateien (*.*)") Beim Laden wird die Prozedur aus Listing 4 ausgelöst. Diese Prozedur prüft, ob ein Öffnungsargument übergeben wurde, und liest die beiden Werte in Variablen ein. Dann prüft sie, ob bereits ein Mailing zu dieser Ausgabe angelegt wurde, und speichert die MailingID gegebenenfalls in der Variablen lngmailingid. In diesem Fall zeigt das Formular direkt beim Öffnen den passenden Datensatz an, sonst einen neuen, leeren Datensatz. In diesem Fall wird der Betreff direkt mit dem Produktnamen und der Ausgabe gefüllt. Nach dem Eintragen des Inhalts (dort können Platzhalter für die in der Abfrage qrykunden- Ausgaben enthaltenen Felder in eckigen Klammern angegeben werden) und dem Hinzufügen des Anhangs können Sie das Mailing mit einem Klick auf die Schaltfläche cmdsenden auf den Weg bringen. Abb. 10: Das Formular zum Bearbeiten der Mailings Beitrag Outlook-Mails mit Klasse ( vorgestellt wird. Die Prozedur durchläuft dann alle Datensätze des Recordsets und versendet für jeden eine neue E- Mail. Dabei ersetzt die Prozedur jeweils die Platzhalter im Inhalt der Mail durch die Werte der entsprechenden Felder des Recordsets. Schließlich trägt sie für jede versendete die MailingID und das Versanddatum in die Tabelle tblversendungen ein. Zusammenfassung und Ausblick In diesem Teil der Beitragsreihe haben Sie zwei Möglichkeiten zum Steuern des Versands kennengelernt. Die Prozedur cmdsenden_click erstellt dann ein Recordset auf Basis der Abfrage qrykunden- Ausgaben, wobei nach der betroffenen Ausgabe gefiltert wird (s. Listing 5). Dann instanziert sie ein Objekt auf Basis der Klasse clsmails, die im Es gibt noch einige weitere Möglichkeiten, die Versendungen zu realisieren beispielsweise durch Erstellen entsprechender Versandetiketten. Gegebenenfalls kommen wir in einem weiteren Beitrag auf diese Möglichkeiten zurück. 72

Verknüpfte Daten kopieren

Verknüpfte Daten kopieren Das Kopieren einfacher Datensätze ist schnell erledigt. Markieren, kopieren, einfügen schon liegt der neue Datensatz vor. Was aber geschieht, wenn an dem zu kopierenden Datensatz noch weitere Daten hängen

Mehr

ACCESS. Berechnete Felder in Tabellen TABELLEN ENTWERFEN BERECHNETE FELDER IN TABELLEN BASICS

ACCESS. Berechnete Felder in Tabellen TABELLEN ENTWERFEN BERECHNETE FELDER IN TABELLEN BASICS Berechnete Felder in Tabellen Berechnete Felder in Tabellen sind ein Feature, das mit der Version 2010 von Access hinzugekommen ist. Dabei handelt es sich um die Möglichkeit, die Inhalte der übrigen Felder

Mehr

Zweitens über eine Abfrage, welche die Tabellen tblartikel und tbllieferanten verknüpft. Auf diese Weise würde das Kombinationsfeld

Zweitens über eine Abfrage, welche die Tabellen tblartikel und tbllieferanten verknüpft. Auf diese Weise würde das Kombinationsfeld Filterkriterien für Formulare, Teil III: Kombinationsfelder In den ersten beiden Teilen dieser Artikelreihe haben Sie erfahren, wie Sie Felder der verschiedenen Datentypen filtern. Nun geht es ans Eingemachte:

Mehr

ACCESS. 1:1-Beziehungen TABELLEN ENTWERFEN 1:1-BEZIEHUNGEN BASICS

ACCESS. 1:1-Beziehungen TABELLEN ENTWERFEN 1:1-BEZIEHUNGEN BASICS 1:1-Beziehungen 1:1-Beziehungen können für eine ganze Reihe von Anwendungzwecken sinnvoll sein. Sie können damit beispielsweise die Liefer- und/oder die Rechnungsanschrift für einen Kundendatensatz in

Mehr

Werte zu Kombinationsfeldern hinzufügen

Werte zu Kombinationsfeldern hinzufügen Kombinationsfelder bieten meist Daten aus Lookup-Tabellen zur Auswahl an. Das bedeutet, dass Sie damit etwa die Anrede oder den Titel einer Person festlegen können, wobei Anreden und Titel in separaten

Mehr

ACCESS. Formulare per VBA referenzieren FORMULARE MIT VBA PROGRAMMIEREN FORMULARE PER VBA REFERENZIEREN BASICS

ACCESS. Formulare per VBA referenzieren FORMULARE MIT VBA PROGRAMMIEREN FORMULARE PER VBA REFERENZIEREN BASICS Formulare per VBA referenzieren Wenn Sie Formulare und Steuerelemente programmieren wollen, müssen Sie wissen, wie Sie diese referenzieren. Nicht immer geschieht dies vom Klassenmodul des Formulars selbst

Mehr

ACCESS. Access-Daten nach Excel verknüpfen INTERAKTIV ACCESS-DATEN NACH EXCEL VERKNÜPFEN BASICS

ACCESS. Access-Daten nach Excel verknüpfen INTERAKTIV ACCESS-DATEN NACH EXCEL VERKNÜPFEN BASICS -DATEN NACH EXCEL VERKNÜPFEN Access-Daten nach Excel verknüpfen Wir haben uns bereits in verschiedenen Artikeln angesehen, wie Sie von Access aus auf die Daten einer Excel-Datei zugreifen können ob per

Mehr

ACCESS. Laufende Summen in Tabellen TABELLEN ENTWERFEN LAUFENDE SUMMEN IN TABELLEN BASICS

ACCESS. Laufende Summen in Tabellen TABELLEN ENTWERFEN LAUFENDE SUMMEN IN TABELLEN BASICS Laufende Summen in Tabellen Immer wieder taucht die Frage auf, wie man in Access die Inhalte von Zahlenfelder mehrerer Datensätze aufsummiert. Unter Excel ist das einfach dort trägt man einfach die Summe

Mehr

ACCESS. Kombinationsfeld um Suche erweitern FORMULARE FÜR DIE DATENEINGABE KOMBINATIONSFELD UM SUCHE ERWEITERN BASICS

ACCESS. Kombinationsfeld um Suche erweitern FORMULARE FÜR DIE DATENEINGABE KOMBINATIONSFELD UM SUCHE ERWEITERN BASICS Kombinationsfeld um Suche erweitern Kombinationsfelder sind schon eine praktische Einrichtung: Sie erlauben nicht nur die Auswahl von Einträgen, die schon nach dem Alphabet voreingestellt sind, sondern

Mehr

Erstellung von abhängigen Kombinationsfeldern mit dazugehörigen Unterformular...1

Erstellung von abhängigen Kombinationsfeldern mit dazugehörigen Unterformular...1 Erstellung von abhängigen Kombinationsfeldern mit dazugehörigen Inhaltsverzeichnis Erstellung von abhängigen Kombinationsfeldern mit dazugehörigen...1 Inhaltsverzeichnis...1 Einleitung...1 Vorgaben...1

Mehr

Das Erstellen einer Datenbank in MS Access 2010

Das Erstellen einer Datenbank in MS Access 2010 Das Erstellen einer Datenbank in MS Access 2010 1. Eine Datenbank anlegen und 1.1. eine Tabelle entwerfen Leere Datenbank, erstellen anklicken vorher Pfad und definieren 1. 2. Es erscheint dieser Bildschirm

Mehr

ACCESS. Aufgabenplaner LÖSUNGEN AUFGABENPLANER BASICS

ACCESS. Aufgabenplaner LÖSUNGEN AUFGABENPLANER BASICS Aufgabenplaner Im Artikel Berichtsansicht haben Sie eine neue Ansicht für Berichte kennen gelernt, die ganz neue Möglichkeiten eröffnet. Sie können damit hierarchische Daten anzeigen, ohne das Tree- View-Steuerelement

Mehr

Formulare für die Dateneingabe Mehrere Formularinstanzen anzeigen

Formulare für die Dateneingabe Mehrere Formularinstanzen anzeigen Die Datensätze einer Tabelle zeigen Sie meist in einer Übersicht wie einem Datenblatt oder einem Listenfeld an. Für die Bearbeitung öffnen Sie den gewünschten Datensatz in einem Detailformular, das die

Mehr

- Welche Beziehungstypen werden von ACCESS unterstützt? ACCESS unterstützt die Beziehungen + 1:1 + 1:n bzw. 1:cn + m:n

- Welche Beziehungstypen werden von ACCESS unterstützt? ACCESS unterstützt die Beziehungen + 1:1 + 1:n bzw. 1:cn + m:n ACCESS 1. Aufgabe - Welche Beziehungstypen werden von ACCESS unterstützt? ACCESS unterstützt die Beziehungen + 1:1 + 1:n bzw. 1:cn + m:n - Was versteht man unter referentieller Integrität? Dies sind Regeln,

Mehr

Access [basics] Rechnen in Berichten. Beispieldatenbank. Datensatzweise berechnen. Berechnung im Textfeld. Reporting in Berichten Rechnen in Berichten

Access [basics] Rechnen in Berichten. Beispieldatenbank. Datensatzweise berechnen. Berechnung im Textfeld. Reporting in Berichten Rechnen in Berichten Berichte bieten die gleichen Möglichkeit zur Berechnung von Werten wie Formulare und noch einige mehr. Im Gegensatz zu Formularen bieten Berichte die Möglichkeit, eine laufende Summe zu bilden oder Berechnungen

Mehr

ACCESS IM UNTERNEHMEN

ACCESS IM UNTERNEHMEN Ausgabe 02/2017 ACCESS STÜCKLISTEN, TEIL II Erweitern Sie die Stücklisten-Lösung um komfortable Kontextmenüs (ab S. 46). In diesem Heft: TICKETSYSTEM Beantworten Sie Kundenanfragen mit vorgefertigten und

Mehr

MiniPPS - Systembeschreibung

MiniPPS - Systembeschreibung MiniPPS - Systembeschreibung Hans-Christian Walter Beuth Hochschule für Technik Einführungsbeispiel für Access Version 04.11.2012 Inhalt 1. Access einrichten 2 2. Tabellen 5 3. Abfrage 9 4. Formulare 10

Mehr

Mastertabelle. Feldliste

Mastertabelle. Feldliste Auswahlabfrage 2010 Niko Becker Mit Hilfe von Abfragen können Sie Datensätze bearbeiten, Berechnungen durchführen und dabei Funktionen oder Aggregatfunktionen in Formeln einbinden, Datengruppen erstellen

Mehr

Listenfeldauswahl speichern und wiederherstellen

Listenfeldauswahl speichern und wiederherstellen Wie Sie die durch einen Benutzer ausgewählten Einträgen im Listenfeld auslesen, haben Sie bereits im Artikel "Mehrfachauswahl in Listenfeldern auslesen" erfahren. In diesem Folgeartikel geht es darum,

Mehr

Microsoft Access Abfragen. Verknüpfung von Tabellen

Microsoft Access Abfragen. Verknüpfung von Tabellen Microsoft Access Abfragen. Verknüpfung von Tabellen Welche Bestellungen hat Kunde... aufgegeben? Welche Kunden im Staat USA haben Waren im Wert von mindestens... bestellt? Welche Waren wurden nicht bestellt?

Mehr

4 Artikel verwalten. 4.1 Übersichtsformular erstellen

4 Artikel verwalten. 4.1 Übersichtsformular erstellen 4 Artikel verwalten Ich glaube, dass ich es bereits vor einigen Kapiteln erwähnt habe: Faule Access-Entwickler kommen grundsätzlich schneller zum Ziel als andere. So werden wir es uns beim Gestalten der

Mehr

[basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen

[basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen Ausgabe 17. August 2010 Access [basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen Tabellen entwerfen Teil III: Mitarbeiter per m:n-beziehung zu Projektteams zusammenstellen Die Zuordnung

Mehr

TREEVIEW: VERKNKÜPF- TE DATEN, TEIL I

TREEVIEW: VERKNKÜPF- TE DATEN, TEIL I Ausgabe 09/2013 ACCESS DAS ACCESS-MAGAZIN FÜR ALLE, DIE VON 0 AUF 100 WOLLEN In diesem Heft: ANLAGEFELDER UND VBA ERFAHREN SIE, WIE SIE BIL- DER UND ANDERE DATEIEN PER VBA IN ANLAGEFELDER EINFÜGEN UND

Mehr

ECDL Datenbank ADVANCED

ECDL Datenbank ADVANCED 4 Formulare sind Datenbankobjekte, die dazu verwendet werden, Daten zu erfassen und zu bearbeiten. Dadurch wird die Datenbank einerseits benutzerfreundlich und außerdem wird durch die Verwendung eines

Mehr

1 Erste Schritte...13

1 Erste Schritte...13 Inhalt 1 Erste Schritte...13 1.1 Access starten, Datenbank öffnen... 14 1.2 Eine neue Datenbank erstellen... 17 Mit einer leeren Datenbank beginnen... 18 Dateiformate... 19 1.3 Bestandteile einer Access

Mehr

IM UNTERNEHMEN EINFACH NAVIGIEREN LOOKUP-DATEN: AUS ZWEI MACH EINS

IM UNTERNEHMEN EINFACH NAVIGIEREN LOOKUP-DATEN: AUS ZWEI MACH EINS Ausgabe 04/2014 EINFACH NAVIGIEREN Sie sind während der Bearbeitung einer Bestellung schnell zur nächsten gesprungen, weil ein neuer Kunde anruft? Und dann wollen Sie schnell wieder zurück zur vorherigen

Mehr

ACCESS. basics. Das Access-Magazin für alle, die von 0 auf 100 wollen. In diesem Heft: per VBA. Ausgabe 1/2014. Neben den numerischen

ACCESS. basics. Das Access-Magazin für alle, die von 0 auf 100 wollen. In diesem Heft: per VBA. Ausgabe 1/2014. Neben den numerischen Ausgabe 1/2014 Das Access-Magazin für alle, die von 0 auf 100 wollen In diesem Heft: Tabellen entwerfen: GUIDS Neben den numerischen Autowerten können Sie auch GUIDS verwenden. Was das ist und wie Sie

Mehr

1. Tabellen-Beziehungen

1. Tabellen-Beziehungen 1. Tabellen-Beziehungen Ein relationales DBMS wie MS ACCESS verteilt, wie in vorherigen Kapiteln gezeigt, die Daten auf verschiedene Tabellen. Trotz dieser sinnvollen und notwendigen Trennung der Daten

Mehr

Verlag: readersplanet GmbH Neuburger Straße Passau.

Verlag: readersplanet GmbH Neuburger Straße Passau. MICROSOFT ACCESS 2010 - BASISWISSEN Verlag: readersplanet GmbH Neuburger Straße 108 94036 Passau http://www.readersplanet-fachbuch.de info@readersplanet-fachbuch.de Tel.: +49 851-6700 Fax: +49 851-6624

Mehr

Access Programmierung. Ricardo Hernández García. 1. Ausgabe, November 2013 ACC2013P

Access Programmierung. Ricardo Hernández García. 1. Ausgabe, November 2013 ACC2013P Access 2013 Ricardo Hernández García 1. Ausgabe, November 2013 Programmierung ACC2013P Die VBA-Entwicklungsumgebung 5 Weitere Eingabehilfen Im Menü Bearbeiten finden Sie noch weitere Hilfen, die Ihnen

Mehr

Microsoft Access Abfragen: Informationen anzeigen und sortieren

Microsoft Access Abfragen: Informationen anzeigen und sortieren Microsoft Access Abfragen: Informationen anzeigen und sortieren Alle Kunden Die Namen der Mitarbeiter und deren E-Mail-Adresse Bestellungen, nach dem Datum sortiert Anja Aue 16.11.16 Abfragen Zusammenstellung

Mehr

Sie haben mehrere Möglichkeiten neue Formulare zu erstellen. Achten Sie darauf, dass das Objekt Formulare aktiviert ist: Klicken Sie auf.

Sie haben mehrere Möglichkeiten neue Formulare zu erstellen. Achten Sie darauf, dass das Objekt Formulare aktiviert ist: Klicken Sie auf. 9. FORMULARE Mit Formularen können Sie sehr komfortabel Daten in eine Tabelle eingeben und auch anzeigen lassen, da Sie viele Eingabemöglichkeiten zur Verfügung haben. EIN EINFACHES FORMULAR ERSTELLEN

Mehr

Anleitung Dokumente versenden aus Pinus-Faktura via

Anleitung Dokumente versenden aus Pinus-Faktura via Dokumente versenden aus Pinus-Faktura via E-Mail Seite 1 von 14 Anleitung Dokumente versenden aus Pinus-Faktura via E-Mail Dokumente versenden aus Pinus-Faktura via E-Mail Seite 2 von 14 Anleitung Dokumente

Mehr

zur Verfügung gestellt durch das OpenOffice.org Dokumentations-Projekt

zur Verfügung gestellt durch das OpenOffice.org Dokumentations-Projekt Serienbriefe Wie Sie einen Serienbrief mittels Calc und Writer erstellen zur Verfügung gestellt durch das OpenOffice.org Dokumentations-Projekt Inhaltsverzeichnis 1. Erzeugen einer Quelldatei 2. Erzeugung

Mehr

Modell Bahn Verwaltung. Tutorial. Links. Min. Programm Version 0.65, März w w w. r f n e t. c h 1 / 11

Modell Bahn Verwaltung. Tutorial. Links. Min. Programm Version 0.65, März w w w. r f n e t. c h 1 / 11 Modell Bahn Verwaltung Tutorial Links Min. Programm Version 0.65, März 2015 Tutorial Version 04.01.2017 rfnet Software w w w. r f n e t. c h 1 / 11 Vorwort... 3 1 Links... 4 1.1 Einführung... 4 1.2 Link

Mehr

Empfänger. Alle Empfänger, die sich für Ihre(n) Newsletter angemeldet haben, werden in der Empfängerverwaltung erfasst.

Empfänger. Alle Empfänger, die sich für Ihre(n) Newsletter angemeldet haben, werden in der Empfängerverwaltung erfasst. Empfänger Alle Empfänger, die sich für Ihre(n) Newsletter angemeldet haben, werden in der Empfängerverwaltung erfasst. Für eine größere Flexibilität in der Handhabung der Empfänger erfolgt der Versand

Mehr

myfactory.go! - Einkauf Tutorial: Wie nutze ich die Bestellvorschläge? Inhalt

myfactory.go! - Einkauf Tutorial: Wie nutze ich die Bestellvorschläge? Inhalt Tutorial: Wie nutze ich die Bestellvorschläge? Sie haben die Möglichkeit in der Version automatisierte Bestellvorschläge aufzurufen. Anhand der beim Artikel hinterlegten Dispositionsmethode, der Wiederbeschaffungszeiten

Mehr

Inhalt Vorwort... I So benutzen Sie dieses Buch... II Inhalt... V Datenmodelle... 1 MS Access... 9

Inhalt Vorwort... I So benutzen Sie dieses Buch... II Inhalt... V Datenmodelle... 1 MS Access... 9 Inhalt Vorwort... I So benutzen Sie dieses Buch... II Inhalt... V Datenmodelle... 1 Hierarchisches Datenmodell...1 Relationales Datenmodell...2 Objektorientiertes Datenmodell...3 Datenbank - Lebenszyklus...4

Mehr

> Berechtigungen. BEREICH

> Berechtigungen. BEREICH BEREIH Berechtigungen In diesem Bereich der Dokumentation werden die Programme beschrieben, über die Sie die Zugriffsberechtigungen der Mitarbeiter steuern. Die hier beschriebenen Programme finden Sie

Mehr

Durch die Anwahl des Menüpunktes (1) KIS im Menüband auf der linken Seite gelangen Sie in den Bereich des Kanzlei-Informations-Systems.

Durch die Anwahl des Menüpunktes (1) KIS im Menüband auf der linken Seite gelangen Sie in den Bereich des Kanzlei-Informations-Systems. K U R Z A N L E I T U N G R Z L B O A R D S E R I E N B R I E F RZL Software GmbH Hannesgrub Nord 5 49 Tumeltsham Version:. August 07/ng. Öffnen des Kanzlei-Informations-Systems Durch die Anwahl des Menüpunktes

Mehr

Allgemeine Hinweise zum Erstellen einer einfachen Datenbank

Allgemeine Hinweise zum Erstellen einer einfachen Datenbank Allgemeine Hinweise zum Erstellen einer einfachen Datenbank 1. Tabellen Öffnen Sie das Programm MS-ACCESS durch Doppelklick auf das Symbol oder durch Auswahl des Programms in der Taskleiste Start Programme

Mehr

Klappe Access ist sowohl eine Entwicklungsumgebung für die Benutzeroberfläche als auch ein Datenbankmanagementsystem.

Klappe Access ist sowohl eine Entwicklungsumgebung für die Benutzeroberfläche als auch ein Datenbankmanagementsystem. 2 Datenmodell Am Anfang eines jeden Access-Projekts steht eine Idee. Im vorliegenden Fall soll eine Kundenund Bestellverwaltung erstellt werden, die dem Benutzer so viel Arbeit wie möglich abnimmt. Das

Mehr

Schnellübersichten. Access 2016 Grundlagen für Datenbankentwickler

Schnellübersichten. Access 2016 Grundlagen für Datenbankentwickler Schnellübersichten Access 2016 Grundlagen für Datenbankentwickler 1 Access kennenlernen 2 2 Mit Datenbanken arbeiten 3 3 Tabellen 4 4 Feldeigenschaften 6 5 Indizes festlegen 7 6 Beziehungen zwischen Tabellen

Mehr

Formulare. Datenbankanwendung 113

Formulare. Datenbankanwendung 113 Formulare Wenn Sie mit sehr umfangreichen Tabellen arbeiten, werden Sie an der Datenblattansicht von Access nicht lange Ihre Freude haben, sind dort doch immer zu wenig Felder gleichzeitig sichtbar. Um

Mehr

[basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen

[basics]  Das Access-Magazin für alle, die schnell von 0 auf 100 wollen Access [basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen Editorial Die aktuelle Ausgabe liefert einiges Know-how zum Thema Abfragen. Sie erfahren, wie Sie das Ergebnis einer Abfrage

Mehr

Projekte verwalten Projekte bieten in Synago eine Möglichkeit, Freizeiten Einladungsaktionen oder Rundbriefe zu organisieren. So funktioniert es

Projekte verwalten Projekte bieten in Synago eine Möglichkeit, Freizeiten Einladungsaktionen oder Rundbriefe zu organisieren. So funktioniert es Projekte verwalten Projekte bieten in Synago eine Möglichkeit, Freizeiten Einladungsaktionen oder Rundbriefe zu organisieren. Die Projektverwaltung besteht aus 4 Bausteinen: 1) Projekte Hier legen Sie

Mehr

Document Portal 1. Document Portal

Document Portal 1. Document Portal 1 Mit dem von Lexmark können Sie in Ihrem Unternehmen Formulare auf einfache Weise verwenden. Stellen Sie sich vor den Sensorbildschirm, wählen Sie Ihre Dokumente aus, und drücken Sie auf Start. ist eine

Mehr

Arbeiten mit Nachrichten im Fakultäts-Typo3-System

Arbeiten mit Nachrichten im Fakultäts-Typo3-System Arbeiten mit Nachrichten im Fakultäts-Typo3-System Stand: 28.01.2016 Autor: Heiko Schwarzenberg, Universitätsrechenzentrum Inhaltsverzeichnis Arbeiten mit Nachrichten im Fakultäts-Typo3-System... 0 1.

Mehr

ACCESS KOMFORTABEL SUCHEN IM UNTERNEHMEN. In diesem Heft: GESPEICHERTE PROZEDUREN KOMBINATIONSFELD PER TASTE COM-ADD-INS FÜR DEN VBA-EDITOR SEITE 2

ACCESS KOMFORTABEL SUCHEN IM UNTERNEHMEN. In diesem Heft: GESPEICHERTE PROZEDUREN KOMBINATIONSFELD PER TASTE COM-ADD-INS FÜR DEN VBA-EDITOR SEITE 2 Ausgabe 01/2019 KOMFORTABEL SUCHEN Suchen Sie nach verschiedenen Suchbegriffen in unterschiedlichen Feldern und das mit nur einem einzigen Steuerelemenet! (ab S. 61) In diesem Heft: GESPEICHERTE PROZEDUREN

Mehr

Access [basics] Aktionsabfragen per VBA ausführen. Beispieldatenbank. Aktionsabfragen. Die Execute-Methode. Datenzugriff per VBA

Access [basics] Aktionsabfragen per VBA ausführen. Beispieldatenbank. Aktionsabfragen. Die Execute-Methode. Datenzugriff per VBA Aktionsabfragen lassen sich bequem mit der Entwurfsansicht für Abfragen zusammenstellen. Sie können damit Daten an Tabellen anfügen, bestehende Daten ändern oder löschen und sogar gleich die passende Tabelle

Mehr

Was Sie bald kennen und können

Was Sie bald kennen und können Kontakte 6 In diesem Kapitel erfahren Sie, wie Sie Kontaktadressen im Outlook- Ordner Kontakte bequem und übersichtlich verwalten können. Es ist beispielsweise möglich, einen Absender einer E-Mail direkt

Mehr

easybill- Schnittstellenhandbuch

easybill- Schnittstellenhandbuch easybill- Schnittstellenhandbuch Stand: 15.06.2017 2017 Virthos Systems GmbH www.pixtacy.de 2 Einleitung Pixtacy verfügt ab Version 2.3 über eine Schnittstelle zu dem Online-Fakturierungsprogramm easybill.de.

Mehr

Bilderverwaltung mit Access

Bilderverwaltung mit Access Bilderverwaltung mit Access (1) Tabelle anlegen Der große Nachteil beim Speichern von Bilddateien in Datenbanken ist, dass sie nicht in dem herkömmlichen Format, sondern in einem Windows-internen Format

Mehr

Whitepaper. Produkt: combit Relationship Manager 5. Import von Adressen nach Firmen und Personen. combit GmbH Untere Laube Konstanz

Whitepaper. Produkt: combit Relationship Manager 5. Import von Adressen nach Firmen und Personen. combit GmbH Untere Laube Konstanz combit GmbH Untere Laube 30 78462 Konstanz Whitepaper Produkt: combit Relationship Manager 5 Import von Adressen nach Firmen und Personen Import von Adressen nach Firmen und Personen - 2 - Inhalt Ausgangssituation

Mehr

Dokumentation zur Online- Versandanzeige von Fried-Sped

Dokumentation zur Online- Versandanzeige von Fried-Sped Dokumentation zur Online- Versandanzeige von Fried-Sped Anmeldung Melden Sie sich mit den Ihnen zugewiesenen Logindaten an. Tragen Sie dazu Ihren Benutzernamen und Ihr Passwort in die vorgesehenen Felder

Mehr

Indizes. Index. Datenfeld Normale Tabelle. Gesucht wird: Zugriff. 3. Zugriff 1. Zugriff.

Indizes. Index. Datenfeld Normale Tabelle. Gesucht wird: Zugriff. 3. Zugriff 1. Zugriff. Indizes Gesucht wird: 44791 Index Normale Tabelle 1. Zugriff 1 44789 2. Zugriff 2 44801 3. Zugriff 3 44797 4. Zugriff 4 44388 5. Zugriff 5 44746 6. Zugriff 6 44787 7. Zugriff 7 44793 8. Zugriff 8 44799

Mehr

Microsoft Access Relationen. Anja Aue

Microsoft Access Relationen. Anja Aue Microsoft Access Relationen Anja Aue 10.11.16 Beziehungen zwischen Tabellen Verknüpfung zwischen zwei Tabellen. Darstellung von Beziehungen zwischen Objektgruppen. Verweis in einer Tabelle auf den Datensatz

Mehr

Microsoft Access 2010 Bilder

Microsoft Access 2010 Bilder Microsoft Access 2010 Bilder Hyperlinks... arbeiten ähnlich wie ein Link in einer Webseite. sind ein Verweis auf eine Datei (access2010\material\beispiel\tabledevelop\automat.accdb). können ein Verweis

Mehr

1 Einführung Was macht eine Datenbank? Entwickler und Benutzer Warum sollten Sie mit Datenbanken arbeiten?

1 Einführung Was macht eine Datenbank? Entwickler und Benutzer Warum sollten Sie mit Datenbanken arbeiten? Inhalt 1 Einführung 19 1.1 Was macht eine Datenbank? 19 1.2 Entwickler und Benutzer 20 1.3 Warum sollten Sie mit Datenbanken arbeiten? 20 1.4 Wer sollte dieses Buch lesen? 21 1.5 Wie sind relationale Datenbanken

Mehr

3 Die Tabellen von PROJEKT. Tabellenerstellung in der Entwurfsansicht Dateneingabe direkt in die Tabelle Tabellen mit dem Tabellen-Assistenten anlegen

3 Die Tabellen von PROJEKT. Tabellenerstellung in der Entwurfsansicht Dateneingabe direkt in die Tabelle Tabellen mit dem Tabellen-Assistenten anlegen PROJEKT 3 Die Tabellen von Access 2002 TRAINING Access 2002 ISBN 3-8272-6192-9 Lektion 1 Lektion 2 Lektion 3 Lektion 4 Lektion 5 Lektion 6 Lektion 7 Lektion 8 Lektion 9 Lektion 10 Lektion 11 Lektion 12

Mehr

Schnellübersichten. ECDL Datenbanken mit Windows 10 und Access 2016

Schnellübersichten. ECDL Datenbanken mit Windows 10 und Access 2016 Schnellübersichten ECDL Datenbanken mit Windows 10 und Access 2016 1 Access kennenlernen 2 2 Access verwenden 3 3 Tabellen 4 4 Informationen abfragen 5 5 Formulare 6 6 Outputs 7 1 Access kennenlernen Datenbank

Mehr

Handbuch Franklin Templeton Webshop. Inhaltsverzeichnis. 1. Wo finde ich was? Das Wichtigste im Überblick Registrieren als neuer Webshop-Kunde 3

Handbuch Franklin Templeton Webshop. Inhaltsverzeichnis. 1. Wo finde ich was? Das Wichtigste im Überblick Registrieren als neuer Webshop-Kunde 3 Handbuch Franklin Templeton Webshop Inhaltsverzeichnis 1. Wo finde ich was? Das Wichtigste im Überblick 2 2. Registrieren als neuer Webshop-Kunde 3 3. Anmeldung als registrierter Kunde 5 4. Passwort vergessen

Mehr

3. Synchronisation von Formularen

3. Synchronisation von Formularen 3. 3.1. Datenmodell Die folgenden Überlegungen basieren auf einem einfachen Datenmodell von drei Tabellen, die jeweils in 1:n Beziehungen zueinander stehen. Gemeinden sind Bezirken zugeordnet und Bezirke

Mehr

Inhalt 1 2. Über dieses Buch 9. Eigene Web Apps erstellen 15. Web Apps weiterentwickeln 27

Inhalt 1 2. Über dieses Buch 9. Eigene Web Apps erstellen 15. Web Apps weiterentwickeln 27 Inhalt 1 2 3 Über dieses Buch 9 Neue Funktionen in Access 2013........................................... 10 Ein kurzer Überblick...................................................... 12 Voraussetzungen.........................................................

Mehr

[basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen

[basics]  Das Access-Magazin für alle, die schnell von 0 auf 100 wollen Access [basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen Editorial Geschafft! Das erste vollständige Jahr Access [basics] ist vorüber (2010 habe ich erst im Mai begonnen und nur acht

Mehr

BauBit PRO Formulare und Begleitbriefe

BauBit PRO Formulare und Begleitbriefe BauBit PRO Formulare und Begleitbriefe 17.03.2015 ABBF Bausoft AG rte André Piller 29 CH-1762 Givisiez Telefon +41.26.469 70 30 Fax +41.26.469 70 50 email info@abbf.ch 1 Formulare und Begleitbriefe mit

Mehr

7 Synchronisation, Kombination, Unterformular

7 Synchronisation, Kombination, Unterformular 7 Synchronisation, Kombination, Unterformular»Tutte le strade portano a Roma. Alle Straßen führen nach Rom.«Ja, es gibt viele Wege, ein Ziel zu erreichen. Auch wenn Sie gleichzeitig auf Angaben aus unterschiedlichen

Mehr

November 2012, Update 1.13.17

November 2012, Update 1.13.17 November 2012, Update 1.13.17 Sehr geehrte Nutzer der Software MMC, im Internet erhalten Sie ab sofort den neuen Programmstand 1.13.17 zum Download. Sie können diesen wie gewohnt über den Programmpunkt

Mehr

Handbuch. Warenkorb R1. Kapitel Lieferantenbestellung. Bestell- und Planungssystem. Version 1.2

Handbuch. Warenkorb R1. Kapitel Lieferantenbestellung. Bestell- und Planungssystem. Version 1.2 Handbuch Kapitel Lieferantenbestellung Bestell- und Planungssystem Warenkorb R1 Version 1.2 Handbuch Bremen, den 28.06.2015 Berufliche Schulen für Hauswirtschaft und Sozialpädagogik Inhaltsverzeichnis

Mehr

Access [basics] Kunden per Bezeichnung verwalten. Beispieldatenbank. Kundenbezeichnung erwünscht. Separates Bezeichnungsfeld

Access [basics] Kunden per Bezeichnung verwalten. Beispieldatenbank. Kundenbezeichnung erwünscht. Separates Bezeichnungsfeld Beim Umgang mit Kundendaten benötigen Sie oft eine allgemeine Bezeichnung eines Kunden. Diese soll beispielsweise als Überschrift im Formular zur Verwaltung der Stammdaten eines Kunden dargestellt werden

Mehr

Dokumentation zur Online- Versandanzeige von Fried-Sped

Dokumentation zur Online- Versandanzeige von Fried-Sped Dokumentation zur Online- Versandanzeige von Fried-Sped Anmeldung Melden Sie sich mit den Ihnen zugewiesenen Logindaten an. Tragen Sie dazu Ihren Benutzernamen und Ihr Passwort in die vorgesehenen Felder

Mehr

Microsoft Office Word Inhaltsverzeichnis I: Erstellen eines automatischen Inhaltsverzeichnisses

Microsoft Office Word Inhaltsverzeichnis I: Erstellen eines automatischen Inhaltsverzeichnisses Microsoft Office Word 2007 Inhaltsverzeichnis I: Erstellen eines automatischen Inhaltsverzeichnisses Inhalt der Schulung Übersicht: Schnelles und einfaches Inhaltsverzeichnis Lektion: Erste Schritte für

Mehr

VERTRÄGE MIT ORGAMAX ERSTELLEN

VERTRÄGE MIT ORGAMAX ERSTELLEN VERTRÄGE MIT ORGAMAX ERSTELLEN Inhalt 1 Einführung... 1 2 Erstellung eines Vertrags... 2 2.1 Die allgemeinen Vertragsdaten... 3 2.2 Laufzeiten & Fristen... 5 2.3 Rechnungs-Daten... 7 2.4 Rechnungs-Texte...

Mehr

Wie erreiche ich was?

Wie erreiche ich was? Wie erreiche ich was? Projekt: Bezeichnung: Auftragsverwaltung intern Interne Auftragsverwaltung Version: 9.0 Datum: 12.02.2013 Kurzbeschreibung: Mit diesem Leitfaden erhalten Sie eine tabellarische Kurzanleitung,

Mehr

öffnen den Tabellenverknüpfungs-Manager. Bild 1: Verknüpfte Tabellen in einer Datenbank Bild 2: Fehlgeschlagener Zugriff auf eine verknüpfte Tabelle

öffnen den Tabellenverknüpfungs-Manager. Bild 1: Verknüpfte Tabellen in einer Datenbank Bild 2: Fehlgeschlagener Zugriff auf eine verknüpfte Tabelle Der neue Tabellenverknüpfungs-Manager Still und heimlich wurde der alte Tabellen-Verknüpfungsmanager von Microsoft ausgetauscht. Der Tabellenverknüpfungs-Manager dient dazu, bestehende Verknüpfungen mit

Mehr

Access [basics] Lookup-Daten per Formular verwalten. Beispieldatenbank. Ausgangsformular. Formular zum Bearbeiten von Lookup- Daten

Access [basics] Lookup-Daten per Formular verwalten. Beispieldatenbank. Ausgangsformular. Formular zum Bearbeiten von Lookup- Daten Lookup-Daten per Formular verwalten Wenn Sie Daten wie Anreden, Funktionen, Abteilungen et cetera in Lookup-Tabellen speichern und diese Daten in weiteren Tabellen per Nachschlagefeld verfügbar machen,

Mehr

FastFinder Plus: Funktionsweisen

FastFinder Plus: Funktionsweisen FastFinder Plus: Funktionsweisen Auf Grund des ständig anwachsenden Datenvolumens ist es wichtig, die Übersicht über die Daten nicht zu verlieren und in Bezug auf Fertigungsprozesse Fehler zu vermeiden.

Mehr

Benutzerhandbuch Beispielapplikation Finanzsituation

Benutzerhandbuch Beispielapplikation Finanzsituation Benutzerhandbuch Beispielapplikation Finanzsituation 1 Dokument-Information Dokument-ID: BA-BH Version: 1.0, gültig ab: 01.05.2010 Ersetzt Version: Autor(en): Isabelle Neuburg Geltungsbereich: Entwicklung

Mehr

Erstellen. Zunächst erscheint wie auch beim Start von Profi die Maske zur Anmeldung des Benutzers: Abb.: Benutzeranmeldung

Erstellen. Zunächst erscheint wie auch beim Start von Profi die Maske zur Anmeldung des Benutzers: Abb.: Benutzeranmeldung 90 Kapitel 5: Stammdaten verwalten Katalogimport Das Katalogimportprogramm dient dem Einlesen verschiedener Kataloge, die in Form von Text-, CSV- oder Excel-Dateien vorliegen. Neben dem Importieren und

Mehr

Access Grundlagen für Anwender. Sabine Spieß, Andrea Weikert. 1. Ausgabe, 1. Aktualisierung, September Trainermedienpaket ACC2010_TMP

Access Grundlagen für Anwender. Sabine Spieß, Andrea Weikert. 1. Ausgabe, 1. Aktualisierung, September Trainermedienpaket ACC2010_TMP Sabine Spieß, Andrea Weikert Access 2010 Grundlagen für Anwender 1. Ausgabe, 1. Aktualisierung, September 2012 Trainermedienpaket ACC2010_TMP 3 Access 2010 - Grundlagen für Anwender 3 Daten in Formularen

Mehr

Handbuch. Kostenlose Online-Lernmittelverwaltung mit Bestandspflege. Bildnachweis: istockphoto/dominik Pabis W_009 (06/13)

Handbuch. Kostenlose Online-Lernmittelverwaltung mit Bestandspflege.  Bildnachweis: istockphoto/dominik Pabis W_009 (06/13) Handbuch Kostenlose Online-Lernmittelverwaltung mit Bestandspflege www.schule-weise.de Bildnachweis: istockphoto/dominik Pabis W_009 (06/13) Inhaltsverzeichnis 1. Start und Anmeldung 1.1 Start der Lernmittelverwaltung

Mehr

Stand: Fremddateneinzug Modulbeschreibung

Stand: Fremddateneinzug Modulbeschreibung Seite 1 Inhalt Allgemein...3 Installation...3 So nutzen Sie den...3 Ablauf des s...4 Datenausgabe mit dem...6 Datenimport in die Belegerfassung (Aufträge usw.)...6 Seite 2 Allgemein Der ermöglicht Ihnen

Mehr

[basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen

[basics]  Das Access-Magazin für alle, die schnell von 0 auf 100 wollen 9/2011 Access [basics] Das Access-Magazin für alle, die schnell von 0 auf 100 wollen Editorial Wollen Sie Daten wie Postleitzahlen, Orte, Länder und so weiter immer wieder komplett eintippen müssen? Nein!

Mehr

Wichtige Standardaktionen durchführen

Wichtige Standardaktionen durchführen Anhang Wichtige Standardaktionen durchführen Die Themen dieses Anhangs So geht es mit Access 2000/2003 So geht es mit Access 2007 In diesem Anhang wird dargestellt, wie verschiedene Standardaktionen in

Mehr

MS Access 2016 Grundlagen. Inhalt

MS Access 2016 Grundlagen. Inhalt Inhalt Vorwort... I So benutzen Sie dieses Buch... II Inhalt... V Einführung... 1 Allgemeines zu Datenbanken...1 Typische Anwendungsbeispiele...2 Datenbanken mit Access...3 Zusammenfassung...5 MS Access

Mehr

Inhaltsverzeichnis/Impressum

Inhaltsverzeichnis/Impressum Inhaltsverzeichnis/Impressum Formulare und Steuerelemente Kombinationsfeld mit Bearbeitungsfunktion 2 Steuerelemente an Datenblatt anpassen 11 TreeView: Neue Elemente anlegen 17 Sicherheit Frontend/Backend

Mehr

Architrave GmbH Handbuch für Bieter

Architrave GmbH Handbuch für Bieter Architrave GmbH Handbuch für Bieter / Handbuch für Bieter 1 Architrave GmbH Handbuch für Bieter Bieterhandbuch [erstellt: September 2017] Handbuch für Bieter.doc; Version: 1.0 Architrave GmbH, Berlin 2017

Mehr

SCHULSPEZIFISCHEN ROLLENRECHTE

SCHULSPEZIFISCHEN ROLLENRECHTE Bei BASISDATEN > ADMINISTRATION organisieren Sie, wer SOKRATES an Ihrer Schule mit welchen Rechten nutzen kann. Außerdem können unter ADMINISTRATION mit SOKRATES intern Texte an andere Schulen geschickt

Mehr

So geht s Schritt-für-Schritt-Anleitung

So geht s Schritt-für-Schritt-Anleitung So geht s Schritt-für-Schritt-Anleitung Software WISO Mein Büro 365 inkl. Webselling Thema Import von Vorgängen über das Modul Webselling Version/Datum ab 16.00.05.100 Inhaltsverzeichnis 1. Einführung...

Mehr

2care4u. Modul EK. Einkauf. EK Bestellwesen 1

2care4u. Modul EK. Einkauf. EK Bestellwesen 1 Modul EK Einkauf EK Bestellwesen 1 Inhalt 1 Bestellwesen 3 1.1 Allgemein 3 1.2 Materialanforderungen an das Einkaufsmodul EK 4 2 Funktionen des Bestellwesens 5 2.1 Maske Bestellungen 5 2.2 Erzeugen einer

Mehr

CHARGEN- UND SERIENNUMMERNVERWALTUNG MIT ORGAMAX

CHARGEN- UND SERIENNUMMERNVERWALTUNG MIT ORGAMAX CHARGEN- UND SERIENNUMMERNVERWALTUNG MIT ORGAMAX 1 Sie Seriennummernverwaltung... 2 1.1 Seriennummern im Artikelstamm eintragen... 2 1.2 Weitere Funktionen -> Schnellerfassung... 4 1.3 Weitere Funktionen

Mehr

IMS-Audit Pro. Kurzanleitung 2 / 14

IMS-Audit Pro. Kurzanleitung 2 / 14 Schneller Einstieg Version 11.2018 2 / 14 Inhaltsverzeichnis Inhaltsverzeichnis 1 Einleitung... 4 1.1 Installation... 4 1.2 Bildschirm Übersichten... 4 2 Stammdaten eintragen... 5 2.1 Mandanten anlegen...

Mehr

INHALTSVERZEICHNIS 1 VORWORT 11 ZU DIESER TRAININGSUNTERLAGE 12 2 ACCESS ERSTE SCHRITTE DATENBANK schlffiben 25

INHALTSVERZEICHNIS 1 VORWORT 11 ZU DIESER TRAININGSUNTERLAGE 12 2 ACCESS ERSTE SCHRITTE DATENBANK schlffiben 25 INHALTSVERZEICHNIS 1 VORWORT 11 ZU DIESER TRAININGSUNTERLAGE 12 2 ACCESS 2003 - ERSTE SCHRITTE 13 2.1 ACCESS 2003 STARTEN 14 2.2 BILDSCHIRMELEMENTE 16 2.2.1 MENÜS 16 2 3 DATENBANK ÖFFNEN 17 2.4 DIE HAUPTÜBERSICHT

Mehr

TRIAS-AMOS Handbuch Band 3 Benutzerverwaltung Seite: 1

TRIAS-AMOS Handbuch Band 3 Benutzerverwaltung Seite: 1 TRIAS-AMOS Handbuch Band 3 Benutzerverwaltung Seite: 1 Inhaltsverzeichnis 1. Benutzerverwaltung... 3 a. Zugeordnetes Profil... 5 b. Werke... 5 c. Kostenstellen... 6 d. Persönliche Einstellungen löschen...

Mehr

2 In wenigen Schritten zu einer guten Tabellenstruktur

2 In wenigen Schritten zu einer guten Tabellenstruktur 1 Excel Schulung Andreas Todt 1 Inhaltsverzeichnis 2 In wenigen Schritten zu einer guten Tabellenstruktur... 1 2.1 Eine Excel-Tabelle erstellen... 1 2.2 Filterpfeile entfernen... 2 2.3 Format beibehalten,

Mehr

Inhaltsverzeichnis. Teil I Erste Schritte. 1 Einleitung Was kann Access? Datei: 5217_A02Inhalt.doc, Seite3 15.

Inhaltsverzeichnis. Teil I Erste Schritte. 1 Einleitung Was kann Access? Datei: 5217_A02Inhalt.doc, Seite3 15. Datei: 5217_A02Inhalt.doc, Seite3 15. November 2010 Teil I Erste Schritte 1 Einleitung.... 11 1.1 Die Themenschwerpunkte dieses Buches... 11 Datenmodellierung... 11 Oberflächengestaltung... 12 Programmierung...

Mehr