{"id":55000857,"date":"2012-10-01T00:00:00","date_gmt":"2020-05-22T21:48:54","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=857"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Programmierung_der_KVA","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/","title":{"rendered":"Programmierung der KVA"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg05.met.vgwort.de\/na\/3d578ac87dc8432cac84f9efba2f7df5\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Im Beitrag Kunden, Vertr&auml;ge und Anschreiben verwalten lernen Sie eine komplette Anwendung kennen. Der vorliegende Beitrag beschreibt die Technik, die sich hinter dieser Anwendung verbirgt &#8211; angefangen mit dem Datenmodell &uuml;ber die Abfragen, Formulare und Berichte bis hin zu den verwendeten VBA-Prozeduren. Spezielle Themen werden in weiteren Beitr&auml;gen vertieft, auf die wir an geeigneter Stelle verweisen.<\/b><\/p>\n<p><b>Datenmodell<\/b><\/p>\n<p>Das Datenmodell umfasst einige Tabellen, welche die Daten f&uuml;r die eigentliche Anwendung liefern &#8211; n&auml;mlich die Verwaltung von Kunden, Vertr&auml;gen und Anschreiben bez&uuml;glich dieser Kunden und Vertr&auml;ge. Zus&auml;tzlich gibt es noch eine Optionen-Tabelle, eine Tabelle, welche Informationen &uuml;ber Laufzeitfehler speichert sowie eine zum Speichern tempor&auml;rer Daten beim Erstellen eines Word-Dokuments.<\/p>\n<p>Wir durchlaufen das Datenmodell etwa in der Reihenfolge, in der wir die Elemente der Benutzeroberfl&auml;che im Beitrag <b>Kunden, Vertr&auml;ge und Anschreiben verwalten <\/b>(<b>www.access-im-unternehmen.de\/854<\/b>) beschrieben haben. Dort beginnen wir mit dem &Uuml;bersichtsformular zur Anzeige der Kunden, welches als Datenherkunft die Tabelle <b>tblKunden<\/b> verwendet. Zumindest steht dies in der entsprechenden Eigenschaft des Unterformulars <b>sfmKundenuebersicht<\/b> &#8211; tats&auml;chlich gibt es in der Datenbank aber gar keine Tabelle namens <b>tblKunden<\/b>. Diese Tabelle gab es aber im ersten Entwurf der Datenbank &#8211; und sie sah genau so aus wie die Tabelle, die jetzt <b>tblKundenBase <\/b>hei&szlig;t (s. Bild 1). Warum der Name dieser Tabelle ge&auml;ndert wurde, erfahren Sie weiter unten.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic002.png\" alt=\"pic002.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Entwurf der Tabelle tblKundenBase (fr&uuml;her tblKunden)<\/span><\/b><\/p>\n<p>Die Tabelle enth&auml;lt alle f&uuml;r die Kommunikation mit einem Kunden notwendigen Daten wie die <b>Kundennummer <\/b>(die manuell vergeben wird und vom Wert des Prim&auml;rschl&uuml;sselfeldes <b>KundeID <\/b>abweichen kann), <b>AnredeID<\/b>, <b>Vorname<\/b>, <b>Nachname <\/b>und weitere Felder.<\/p>\n<p>Felder, die auf <b>ID <\/b>enden, deuten normalerweise auf das Vorhandensein von Beziehungen zu anderen Tabellen hin, die als Lookup-Tabellen zur Auswahl von Werten f&uuml;r das betroffene Feld dienen k&ouml;nnen. So ist es auch bei der Tabelle <b>tblKundenBase<\/b> im Fall der Felder <b>AnredeID <\/b>und <b>PersoenlicheAnredeID<\/b>. Beide Felder sind mit entsprechenden Lookup-Tabellen verkn&uuml;pft, die Sie in Bild 2 vorfinden.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic003.png\" alt=\"pic003.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Die Tabellen tblAnreden und tblPersoenlicheAnreden<\/span><\/b><\/p>\n<p><b>Vertr&auml;ge speichern<\/b><\/p>\n<p>Die Vertr&auml;ge zu jedem Kunden werden in der Tabelle <b>tblVertraege <\/b>gespeichert. Diese enth&auml;lt Felder zum Eintragen der wesentlichen Vertragsdaten, die selbst nicht in der Datenbank verwaltet werden (s. Bild 3).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic004.png\" alt=\"pic004.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Entwurf der Tabelle tblVertraege<\/span><\/b><\/p>\n<p>Ein sehr wichtiges Feld dieser Tabelle hei&szlig;t <b>KundeID <\/b>und dient zum Eintragen des Wertes des Feldes <b>KundeID <\/b>der Tabelle <b>tblKundenBase <\/b>f&uuml;r den Kunden, dem der Vertrag zugeordnet ist.<\/p>\n<p>Weitere Fremdschl&uuml;sselfelder dieser Tabelle hei&szlig;en <b>ZahlweiseID<\/b>, <b>GesellschaftID, VertragsartID<\/b> und <b>BankverbindungID<\/b>.<\/p>\n<p>Bei der mit dem Feld <b>ZahlweiseID <\/b>verkn&uuml;pften Tabelle <b>tblZahlweisen <\/b>handelt es sich wiederum um eine einfache Lookup-Tabelle, die lediglich die entsprechenden Werte zur Auswahl enth&auml;lt (s. Bild 5 aussehen.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic006.png\" alt=\"pic006.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Datenblattansicht der Tabelle tblZahlweisen<\/span><\/b><\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic007.png\" alt=\"pic007.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Eigenschaften des Nachschlagefeldes ZahlweiseID<\/span><\/b><\/p>\n<p>Das Feld <b>VertragsartID<\/b> soll ebenfalls als Nachschlagefeld eingerichtet werden und die Datens&auml;tze der Tabelle <b>tblVertragsarten <\/b>anzeigen. Dies sieht sp&auml;ter so aus wie in Bild 6.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic008.png\" alt=\"pic008.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 6: Das Nachschlagefeld VertragsartID<\/span><\/b><\/p>\n<p>Etwas umfangreicher und nicht mehr als einfache Lookup-Tabelle zu bezeichnen ist die Tabelle <b>tblGesellschaften<\/b>, welche die f&uuml;r das Feld <b>GesellschaftID <\/b>zur Verf&uuml;gung stehenden Eintr&auml;ge anbietet. Diese Tabelle enth&auml;lt aber nicht nur die im Nachschlagefeld angezeigten Datens&auml;tze, sondern auch noch weitere Felder, die Sie in Bild 7 erkennen k&ouml;nnen.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic005.png\" alt=\"pic005.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 7: Entwurf der Tabelle tblGesellschaften<\/span><\/b><\/p>\n<p>Richtig kompliziert wird es dann beim Fremdschl&uuml;sselfeld <b>BankverbindungID<\/b>. Diese dient zwar letztlich auch wieder nur zur Auswahl von Datens&auml;tzen einer verkn&uuml;pften Tabelle namens <b>tblBankverbindungen<\/b>, allerdings handelt es sich bei der verkn&uuml;pften Tabelle um eine Hilfe zur Herstellung einer Beziehung zwischen den Tabellen <b>tblVertraege <\/b>und <b>tblGeldinstitute <\/b>&#8211; und dabei wird dann auch noch das Fremdschl&uuml;sselfeld <b>KundeID <\/b>einbezogen.<\/p>\n<p>Um dies nachzuvollziehen, werfen wir einen Blick auf die &Uuml;bersicht des kompletten Datenmodells in Bild 8.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic001.png\" alt=\"pic001.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 8: &Uuml;bersicht &uuml;ber das Datenmodell<\/span><\/b><\/p>\n<p>Dort wird deutlich, dass die Tabelle <b>tblBankverbindungen <\/b>zun&auml;chst einmal die Tabellen <b>tblKunden <\/b>und <b>tblGeldinstitute <\/b>zusammenf&uuml;hrt. Eigentlich k&ouml;nnte man dem Kunden auch einfach ein Feld namens <b>BLZ <\/b>und eines namens <b>Kontonummer <\/b>zuweisen, aber die Anwendung soll f&uuml;r jeden Kunden mehrere Bankverbindungen speichern k&ouml;nnen &#8211; was ja auch realistisch ist, denn Hausbesitzer m&ouml;gen beispielsweise alle Vertr&auml;ge bez&uuml;glich des Hauses von einem eigenen Konto aus bezahlen und andere, wie etwa eine Lebensversicherung, von einem anderen Konto aus.<\/p>\n<p>Aber dies h&auml;tte sich realisieren lassen, indem wir einfach eine Tabelle mit den Feldern <b>BLZ<\/b>, <b>Kontonummer <\/b>und <b>KundeID <\/b>erstellen, der wir dann pro Kunde mehrere Bankverbindungen zuweisen k&ouml;nnen. F&uuml;r die Kontonummer ist dies in Ordnung, denn die ist wohl f&uuml;r jede Bankverbindung eindeutig, aber die BLZ kann durchaus bei mehreren Bankverbindungen verschiedener Kunden gleich sein. Also legen wir eine eigene Tabelle an, die <b>tblGeldinstitute <\/b>hei&szlig;t und neben dem Namen des Geldinstituts auch noch die Bankleitzahl enth&auml;lt. Statt eines Feldes <b>BLZ <\/b>f&uuml;gen wir der Tabelle <b>tblBankverbindungen <\/b>also ein Fremdschl&uuml;sselfeld namens <b>GeldinstitutID <\/b>zur Auswahl des Geldinstituts hinzu.<\/p>\n<p>So k&ouml;nnen Sie also nun die Bankverbindungen f&uuml;r einen Kunden definieren. Um diese Bankverbindungen nun auch den Vertr&auml;gen zuweisen zu k&ouml;nnen, damit die Beitr&auml;ge auch vom richtigen Konto abgebucht werden, wenn ein Kunde mehrere Bankverbindungen angegeben hat, erh&auml;lt die Tabelle <b>tblVertraege <\/b>auch noch ein Fremdschl&uuml;sselfeld, mit dem die Bankverbindung ausgew&auml;hlt werden kann. Sp&auml;ter, beim Entwurf des Formulars zur Eingabe dieser Daten, zeigt dieses Feld nat&uuml;rlich nur die Bankverbindungen und Geldinstitute zum aktuellen Kunden an.<\/p>\n<p><b>Beschriftungen f&uuml;r die Tabellenfelder einstellen<\/b><\/p>\n<p>Die meisten Tabellenfelder werden auf die eine oder andere Art in einem Formular in der Formular- oder Datenblattansicht landen. Dabei ziehen Sie die Felder am einfachsten direkt aus der Feldliste in den Formularentwurf. Access legt dann automatisch Bezeichnungsfelder an, die sich an den Feldnamen orientieren. Bei Feldnamen wie <b>Strasse <\/b>der <b>EMail <\/b>ist hier in der Regel Nacharbeit erforderlich, um die Bezeichnungsfelder mit Texten wie <b>Stra&szlig;e <\/b>oder <b>E-Mail <\/b>auszustatten. Um diese Arbeit kommen Sie nicht herum, aber Sie k&ouml;nnen diese zumindest minimieren &#8211; n&auml;mlich durch Eintragen entsprechender Texte f&uuml;r die Eigenschaft <b>Beschriftung <\/b>der Felder im Tabellenentwurf. Wenn n&auml;mlich Beschriftungen vorhanden sind, &uuml;bernimmt Access diese statt der Feldnamen als Text f&uuml;r die Bezeichnungsfelder.<\/p>\n<p>In den folgenden Abschnitten schauen wir uns nun die Formulare der Anwendung an.<\/p>\n<p><b>Die Kunden&uuml;bersicht<\/b><\/p>\n<p>Das Formular <b>frmKundenuebersicht <\/b>soll gleich beim Start der Anwendung ge&ouml;ffnet werden und eine &Uuml;bersichtsliste der Kunden anzeigen. Dabei soll es die M&ouml;glichkeit bieten, die Details zu einem Kunden anzuzeigen, einen Kunden zu l&ouml;schen oder einen neuen Kunden anzulegen.<\/p>\n<p>Die Anzeige der Kundenliste soll in einem Unterformular in der Datenblattansicht erfolgen, da dieses gegen&uuml;ber einem Listenfeld ausreichend Komfort zur Anpassung von Spaltenbreiten und -anordnung oder auch zur Sortierung der Datens&auml;tze bietet. Deshalb legen Sie zuerst ein entsprechendes Unterformular namens <b>sfmKundenuebersicht<\/b> an. Dieses verwendet die Tabelle <b>tblKunden <\/b>als Datenherkunft und zeigt all ihre Felder an (s. Bild 9).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic009.png\" alt=\"pic009.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 9: Entwurf des Unterformulars sfmKundenuebersicht<\/span><\/b><\/p>\n<p>Dieses Formular f&uuml;gen wir nach dem Speichern und Schlie&szlig;en gleich nach dem Anlegen in ein weiteres neues, leeres Formular ein &#8211; und zwar wie in Bild 10 in den Detailbereich. Dies erledigen Sie, indem Sie das Unterformular <b>sfmKundenuebersicht <\/b>aus dem Datenbankfenster beziehungsweise Navigationsbereich in den Formularentwurf ziehen und dann seine Gr&ouml;&szlig;e anpassen. Unter Access 2007 und j&uuml;nger stellen Sie au&szlig;erdem die Eigenschaften <b>Horizontaler Anker <\/b>und <b>Vertikaler Anker <\/b>jeweils auf den Wert <b>Beide <\/b>ein.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic010.png\" alt=\"pic010.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 10: Haupt- und Unterformular<\/span><\/b><\/p>\n<p>Dieses Formular speichern Sie unter dem Namen <b>frmKundenuebersicht<\/b>. F&uuml;gen Sie dem Kopfbereich ein geeignetes Bild und eine Beschriftung hinzu. Legen Sie dort au&szlig;erdem eine Schaltfl&auml;che namens <b>cmdSuche <\/b>an. Im Formularfu&szlig; landen weitere Schaltfl&auml;chen namens <b>cmdOK<\/b>, <b>cmdNeu<\/b>, <b>cmdBearbeiten <\/b>und <b>cmdLoeschen <\/b>&#8211; die Beschriftungen k&ouml;nnen Sie der Abbildung entnehmen.<\/p>\n<p>Die Schaltfl&auml;che <b>cmdOK <\/b>soll schlicht das Formular schlie&szlig;en. Dies erreichen Sie durch Anlegen der folgenden Ereignisprozedur:<\/p>\n<pre>Private Sub cmdOK_Click()\r\n    DoCmd.Close acForm, Me.Name\r\nEnd Sub<\/pre>\n<p>Zum Anlegen der Prozedur markieren Sie die Schaltfl&auml;che <b>cmdOK <\/b>in der Entwurfsansicht, aktivieren mit <b>F4 <\/b>das Eigenschaftsfenster, w&auml;hlen f&uuml;r die Eigenschaft <b>Beim Klicken <\/b>den Wert <b>[Ereignisprozedur] <\/b>aus und klicken dann auf die Schaltfl&auml;che mit den drei Punkten. Die nun erscheinende Prozedur im VBA-Editor erg&auml;nzen Sie wie oben angegeben.<\/p>\n<p><b>tblKunden und tblKundenBase<\/b><\/p>\n<p>Nun k&uuml;mmern wir uns um die weiteren Schaltfl&auml;chen, die ja zum Beispiel dem L&ouml;schen eines der Kundendatens&auml;tze dienen. Wollen wir einen Kunden aber wirklich gleich komplett l&ouml;schen Und damit auch alle Daten, die mit diesem verkn&uuml;pft sind Nein, das soll nicht geschehen. Zumal Sie ja Ihre Kommunikation dokumentiert wissen wollen. Wie also l&ouml;scht man einen Kunden, der nicht mehr aktiv ist Man k&ouml;nnte diesen archivieren und diesen anschlie&szlig;end l&ouml;schen. Einfacher ist es aber, den Kunden nur als gel&ouml;scht zu markieren. Und alle Kunden, die so markiert sind, nicht mehr in den Formularen der Anwendung anzuzeigen. Also kommt nun das Feld <b>GeloeschtAm <\/b>zum Einsatz, das ja bereits in der Abbildung weiter oben zu sehen war.<\/p>\n<p>Wenn Sie sich nun vorstellen, dass die Anwendung in der Entwicklung schon weiter fortgeschritten ist als es im Rahmen dieses Beitrags beschrieben wurde, m&uuml;ssten Sie alle Stellen, an denen die Anwendung auf die Tabelle <b>tblKunden <\/b>zugreift, so &auml;ndern, dass nur noch die Datens&auml;tze angezeigt werden, deren Feld <b>GeloeschtAm <\/b>den Wert <b>Null <\/b>hat.<\/p>\n<p>Nun unterscheidet Access an keiner Stelle, die sich auf Datenherk&uuml;nfte oder Datensatzherk&uuml;nfte bezieht, zwischen Tabellen oder Abfragen. Es spricht also nichts dagegen, einfach die Tabelle <b>tbKunden <\/b>in <b>tblKundenBase <\/b>umzubenennen und eine Abfrage namens <b>tblKunden <\/b>zu erstellen, die nur noch die Datens&auml;tze anzeigt, die noch nicht als gel&ouml;scht markiert wurden. Diese Abfrage sieht wie in Bild 11 aus.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic011.png\" alt=\"pic011.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 11: Die Abfrage tblKunden liefert alle Kunden, die nicht als gel&ouml;scht markiert wurden.<\/span><\/b><\/p>\n<p><b>Schaltfl&auml;chen aktivieren und deaktivieren<\/b><\/p>\n<p>Abh&auml;ngig davon, ob das Unterformular &uuml;berhaupt einen Datensatz anzeigt, sollen die Schaltfl&auml;chen mit den Beschriftungen <b>Bearbeiten <\/b>und <b>L&ouml;schen <\/b>aktiviert oder deaktiviert werden. <\/p>\n<p>Dazu stellen wir eine kleine Funktion namens <b>SchaltflaechenAktivieren <\/b>bereit, die pr&uuml;ft, ob das Unterformular aktuell Datens&auml;tze enth&auml;lt, und die Schaltfl&auml;chen <b>cmdBearbeiten <\/b>und <b>cmdLoeschen <\/b>entsprechend aktiviert oder deaktiviert:<\/p>\n<pre>Private Sub SchaltflaechenAktivieren()\r\n    Dim bolNotNull As Boolean\r\n    bolNotNull = Not (objSfmKundenuebersicht.Recordset.RecordCount = 0)\r\n    Me!cmdBearbeiten.Enabled = bolNotNull\r\n    Me!cmdLoeschen.Enabled = bolNotNull\r\nEnd Sub<\/pre>\n<p>Was aber ist <b>objSfmKundenuebersicht <\/b>&#8211; wir wollen doch das Unterformular <b>sfmKundenuebersicht <\/b>abfragen, das mit <b>Me!sfmKundenuebersicht.Form <\/b>referenziert werden kann Nun, wir haben doch einiges mehr mit diesem Unterformular vor und deshalb speichern wir eine Referenz auf dieses Unterformular in einer eigenen Objektvariable, die im Kopf der Klasse des Formulars wie folgt deklariert wird:<\/p>\n<pre>Dim WithEvents objSfmKundenuebersicht As Form<\/pre>\n<p>Und wo belegen wir dieses Objekt mit dem entsprechenden Verweis auf das im Unterformular-Steuerelement enthaltene Formular In der Prozedur, die durch das Ereignis <b>Beim Laden <\/b>des Hauptformulars ausgel&ouml;st wird (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-70-anchor\">Listing 1<\/a><\/span>).<\/p>\n<p class=\"listingueberschrift\">Listing 1: Ereignis beim Laden des Formulars frmKundenuebersicht<\/p>\n<pre>Private Sub Form_Load()\r\n    Set objSfmKundenuebersicht = Me!sfmKundenuebersicht.Form\r\n    With objSfmKundenuebersicht\r\n        .OnCurrent = &quot;[Event Procedure]&quot;\r\n    End With\r\n    Set objColumnWidths = New clsColumnWidths\r\n    With objColumnWidths\r\n        Set .DataSheetForm = objSfmKundenuebersicht\r\n        .OptimizeColumnWidths\r\n    End With\r\n    Set objDatasheetSelector = New clsDatasheetSelector\r\n    Set objDatasheetSelector.DataSheetForm = objSfmKundenuebersicht\r\n    SchaltflaechenAktivieren\r\nEnd Sub<\/pre>\n<p>Und dort geschieht noch eine Menge mehr. Zum Beispiel stellen wir die Eigenschaft <b>OnCurrent <\/b>f&uuml;r die Variable <b>objSfmKundenuebersicht <\/b>auf den Wert <b>[Ereignisprozedur] <\/b>ein. Dies sorgt daf&uuml;r, dass wir im gleichen Klassenmodul eine Ereignisprozedur anlegen k&ouml;nnen, die ausgel&ouml;st wird, wenn das referenzierte Unterformular einen neuen Datensatz anzeigt &#8211; und das geschieht auch beim Datensatzwechsel. Alles, was wir tun m&uuml;ssen, damit wir diese Ereignisprozedur im Klassenmodul des Hauptformulars statt im Klassenmodul des Unterformulars anlegen k&ouml;nnen, sind vier Schritte:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Deklarieren einer Objektvariablen auf das Unterformular mit dem Schl&uuml;sselwort <b>With-Events <\/b>(bereits erledigt),<\/li>\n<li class=\"aufz-hlung\">Festlegen der Eigenschaft <b>OnCurrent <\/b>mit dem Wert <b>&quot;[Event Procedure]&quot; <\/b>(auch schon erledigt),<\/li>\n<li class=\"aufz-hlung\">Einstellen der Eigenschaft <b>Hat Modul <\/b>des Unterformulars auf den Wert <b>Ja <\/b>und<\/li>\n<li class=\"aufz-hlung\">Anlegen der entsprechenden Ereignisprozedur im Klassenmodul des Hauptformulars.<\/li>\n<\/ul>\n<p>Diese Ereignisprozedur sieht wie folgt aus:<\/p>\n<pre>Private Sub objsfmKundenuebersicht_Current()\r\n    SchaltflaechenAktivieren\r\nEnd Sub<\/pre>\n<p>Dies sorgt daf&uuml;r, dass die Prozedur <b>SchaltflaechenAktivieren <\/b>bei jedem Datensatzwechsel im Unterformular ausgel&ouml;st wird und die beiden dadurch aktivierten oder deaktivierten Schaltfl&auml;chen immer den richtigen Status haben. Dies gilt auch, wenn der letzte Datensatz im Unterformular gel&ouml;scht wird &#8211; in diesem Fall werden die beiden Schaltfl&auml;chen dann deaktiviert.<\/p>\n<p><b>Spaltenbreite anpassen<\/b><\/p>\n<p>Die Prozedur <b>Form_Load <\/b>erledigt aber noch mehr. Zum Beispiel sorgt sie daf&uuml;r, dass die Spaltenbreiten entsprechend des Inhalts der einzelnen Spalten optimiert werden.<\/p>\n<p>Die wesentliche Funktionalit&auml;t hierzu befindet sich in einem Klassenmodul namens <b>clsColumnWidths<\/b>, das Sie im Kopf des Moduls <b>Form_frmKundendetails <\/b>wie folgt deklarieren (sollten Sie diese Klasse aus der Beispieldatenbank in eine andere Datenbank &uuml;bertragen k&ouml;nnen, &ouml;ffnen Sie einfach den VBA-Editor beider Anwendungen und ziehen Sie die Klasse von einem VBA-Projekt zum anderen):<\/p>\n<pre>Dim objColumnWidths As clsColumnWidths<\/pre>\n<p>In der Prozedur <b>Form_Load <\/b>sorgen diese Zeilen daf&uuml;r, dass die Klasse instanziert und die Spaltenbreiten optimiert werden:<\/p>\n<pre>Set objColumnWidths = New clsColumnWidths\r\nWith objColumnWidths\r\n    Set .DataSheetForm = objSfmKundenuebersicht\r\n    .OptimizeColumnWidths\r\nEnd With<\/pre>\n<p>Die erste Anweisung instanziert ein neues Objekt auf Basis der Klasse, die &uuml;brigen weisen der Klasse das zu optimierende Formular zu und f&uuml;hren schlie&szlig;lich mit <b>OptimizeColumnWidth <\/b>die Optimierung durch (mehr zu dieser Klasse erfahren sie im Beitrag <b>Datenblatt-Spaltenbreiten automatisch anpassen<\/b>, <b>www.access-im-unternehmen.de\/752<\/b>).<\/p>\n<p><b>Zeile bei Klick komplett markieren<\/b><\/p>\n<p>Weitere zwei Zeilen sorgen daf&uuml;r, dass der Benutzer die Daten nicht direkt im Datenblatt bearbeiten kann. Dazu wird beim Anklicken eines Datensatzes direkt der komplette Datensatz markiert. Die daf&uuml;r n&ouml;tige Klasse deklarieren Sie im Modulkopf:<\/p>\n<pre>Dim WithEvents objDatasheetSelector As clsDatasheetSelector<\/pre>\n<p>Diese Klasse wird wieder mit dem Schl&uuml;sselwort <b>WithEvents <\/b>deklariert. Das bedeutet, dass es wieder die M&ouml;glichkeit gibt, auf Ereignisse dieser Klasse zu reagieren &#8211; dazu gleich mehr. Zun&auml;chst die beiden Zeilen, mit denen Sie die Klasse einrichten und einen Verweis auf das betroffene Unterformular &uuml;bergeben:<\/p>\n<pre>Set objDatasheetSelector = New clsDatasheetSelector\r\nSet objDatasheetSelector.DataSheetForm = objSfmKundenuebersicht<\/pre>\n<p>Nun zum Ereignis, das Sie f&uuml;r dieses Objekt implementieren k&ouml;nnen. Es sieht so aus und wird durch einen Doppelklick auf einen der Datens&auml;tze ausgel&ouml;st: <\/p>\n<pre>Private Sub objDatasheetSelector_DblClick()\r\n    KundeBearbeiten objSfmKundenuebersicht!txtKundeID\r\nEnd Sub<\/pre>\n<p>Die einzige Anweisung ruft die Prozedur <b>KundeBearbeiten <\/b>auf. Dabei &uuml;bergibt sie als Parameter den aktuellen Wert im Steuerelement <b>txtKunde-ID <\/b>des Unterformulars &#8211; hierzu sp&auml;ter mehr.<\/p>\n<p>Damit die Datens&auml;tze nicht nur nicht bearbeitet werden k&ouml;nnen, sondern auch noch kein neuer Datensatz angezeigt wird, stellen Sie die drei Eigenschaften <b>Anf&uuml;gen zulassen<\/b>, <b>L&ouml;schen zulassen <\/b>und <b>Bearbeitungen zulassen <\/b>jeweils auf den Wert <b>Nein <\/b>ein.<\/p>\n<p><b>Schaltfl&auml;chen aktivieren<\/b><\/p>\n<p>Schlie&szlig;lich wird beim Laden des Formulars noch die Prozedur <b>SchaltflaechenAktivieren <\/b>ausgel&ouml;st, damit die Schaltfl&auml;chen gleich beim &Ouml;ffnen den richtigen Status aufweisen. Man k&ouml;nnte auch davon ausgehen, dass es ausreicht, wenn dies beim Ausw&auml;hlen eines Datensatzes im Unterformular geschieht &#8211; schlie&szlig;lich ist das auch beim &Ouml;ffnen des Formulars der Fall. Allerdings l&ouml;st das Unterformular das Ereignis <b>Beim Anzeigen <\/b>bereits zum ersten Mal aus, bevor das Ereignis <b>Beim Laden <\/b>im Hauptformular feuert.<\/p>\n<p>Das hei&szlig;t, dass die im Klassenmodul des Hauptformulars implementierte Ereignisprozedur, die durch den Datensatzwechsel im Unterformular ausgel&ouml;st wird, beim Anzeigen des ersten Datensatzes nach dem &Ouml;ffnen des Unterformulars noch gar nicht zum Einsatz kommt. Also m&uuml;ssen wir die Prozedur <b>SchaltflaechenAktivieren <\/b>im Ereignis <b>Beim Laden <\/b>des Hauptformulars einmal auf andere Art und Weise ausl&ouml;sen.<\/p>\n<p><b>L&ouml;schen eines Kundendatensatzes<\/b><\/p>\n<p>Einen Kundendatensatz l&ouml;scht der Benutzer durch einen Mausklick auf die Schaltfl&auml;che <b>cmdLoeschen<\/b>. Dies l&ouml;st die Prozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-71-anchor\">Listing 2<\/a><\/span> aus. Wie oben besprochen, sollen Datens&auml;tze der Tabelle <b>tblKundenBase <\/b>aber gar nicht gel&ouml;scht, sondern nur als gel&ouml;scht markiert werden.<\/p>\n<p class=\"listingueberschrift\">Listing 2: L&ouml;schen eines Kundendatensatzes per Schaltfl&auml;che<\/p>\n<pre>Private Sub cmdLoeschen_Click()\r\n    Dim db As DAO.Database\r\n    Dim lngKundeID As Long\r\n    Dim strSQL As String\r\n    lngKundeID = objSfmKundenuebersicht!KundeID\r\n    Set db = CurrentDb\r\n    strSQL = &quot;UPDATE tblKundenBase SET GeloeschtAm = &quot; &amp; ISODatum(Now) &amp; &quot; WHERE KundeID = &quot; _\r\n        &amp; lngKundeID\r\n    db.Execute strSQL, dbFailOnError\r\n    objSfmKundenuebersicht.Requery\r\n    SchaltflaechenAktivieren\r\n    Set db = Nothing\r\nEnd Sub<\/pre>\n<p><!--30percent--><\/p>\n<p>Genau dies erledigt die Prozedur: Sie ermittelt zun&auml;chst den Wert des Feldes <b>KundeID <\/b>des aktuell im Unterformular markierten Datensatzes und speichert diesen Wert in der Variablen <b>lngKundeID<\/b>. Dieser wird bei der Formulierung einer <b>UPDATE<\/b>-Abfrage wieder aufgegriffen. Diese <b>UPDATE<\/b>-Abfrage soll das Feld <b>GeloeschtAm <\/b>f&uuml;r den betroffenen Datensatz auf das aktuelle Datum samt Uhrzeit einstellen.<\/p>\n<p>Die <b>Execute<\/b>-Methode der zuvor deklarierten und mit einem Verweis auf die aktuell verwendete Datenbank gef&uuml;llten Objektvariablen <b>db <\/b>f&uuml;hrt die SQL-Aktionsabfrage schlie&szlig;lich aus. Danach wird der Inhalt des Unterformulars mit der <b>Requery<\/b>-Methode aktualisiert und ein Aufruf der Prozedur <b>SchaltflaechenAktivieren <\/b>sorgt f&uuml;r die Aktualisierung des Aktiviert-Status der Schaltfl&auml;chen <b>L&ouml;schen <\/b>und <b>Bearbeiten<\/b>.<\/p>\n<p><b>Kundendetails anzeigen<\/b><\/p>\n<p>Das Anzeigen des Formulars mit den Kundendetails soll auf zwei Arten m&ouml;glich sein: erstens durch Ausw&auml;hlen des gew&uuml;nschten Datensatzes und anschlie&szlig;endes Bet&auml;tigen der <b>Bearbeiten<\/b>-Schaltfl&auml;che und zweitens durch einen Doppelklick auf den Eintrag im Unterformular.<\/p>\n<p>Da es gleich zwei Wege gibt, einen Kunden im Detailformular anzuzeigen, bringen wir die notwendigen Befehle in einer separaten Prozedur unter. Diese wird beim Anklicken der Schaltfl&auml;che <b>cmdBearbeiten <\/b>&uuml;ber die entsprechende Ereignisprozedur wie folgt aufgerufen:<\/p>\n<pre>Private Sub cmdBearbeiten_Click()\r\n    KundeBearbeiten objSfmKundenuebersicht!txtKundeID\r\nEnd Sub<\/pre>\n<p>Den Aufruf &uuml;ber die Prozedur, die durch einen Doppelklick auf einen der Eintr&auml;ge im Unterformular ausgel&ouml;st wird, haben Sie ja bereits weiter oben kennengelernt.<\/p>\n<p>Die Prozedur <b>KundeBearbeiten <\/b>sieht wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-72-anchor\">Listing 3<\/a><\/span> aus.<\/p>\n<p class=\"listingueberschrift\">Listing 3: &Ouml;ffnen eines weiteren Formulars zum Bearbeiten eines Kunden<\/p>\n<pre>Private Sub KundeBearbeiten(lngKundeID As Long)\r\n    Dim strWhereCondition As String\r\n    strWhereCondition = &quot;KundeID = &quot; &amp; lngKundeID\r\n    DoCmd.OpenForm &quot;frmKundenDetails&quot;, DataMode:=acFormEdit, WhereCondition:=strWhereCondition\r\n    Set objFrmKundenDetails = Forms!frmKundenDetails\r\n    With objFrmKundenDetails\r\n        .OnClose = &quot;[Event Procedure]&quot;\r\n        .AfterUpdate = &quot;[Event Procedure]&quot;\r\n    End With\r\nEnd Sub<\/pre>\n<p>Sie erwartet die ID des anzuzeigenden Kunden und f&uuml;gt mit diesem ein Kriterium zusammen, das beispielsweise so aussieht:<\/p>\n<pre>KundeID = 123<\/pre>\n<p>Dann &ouml;ffnet sie das Formular <b>frmKundenDetails <\/b>und &uuml;bergibt dieses Kriterium mit dem Parameter <b>WhereCondition<\/b>. Au&szlig;erdem wird das Formular mit <b>DataMode:=acFormEdit <\/b>auf den Bearbeitungsmodus eingestellt.<\/p>\n<p>Es ist wichtig, dass eventuelle &Atilde;&#8220;nderungen an dem im Detail ge&ouml;ffneten Datensatz gleich nach dem Schlie&szlig;en des Detailformulars in der Kunden&uuml;bersicht dargestellt werden. Dies erreicht man meist, indem man die <b>DoCmd.OpenForm<\/b>-Methode mit dem Parameter <b>WindowMode:=acDialog <\/b>&ouml;ffnet. Man kann dann abwarten, bis das Formular geschlossen oder unsichtbar geschaltet wird, und das aufrufende Formular mit den folgenden Anweisungen der zwischenzeitlich angehaltenen Prozedur aktualisieren.<\/p>\n<p>Wir machen es hier etwas anders &#8211; auch damit Sie w&auml;hrend der Bearbeitung des aktuellen Kunden im Formular <b>frmKundenDetails <\/b>weiter mit dem Formular <b>frmKundenuebersicht <\/b>arbeiten k&ouml;nnen. <\/p>\n<p>Das aufgerufene Formular <b>frmKundenDetails<\/b> wird dazu mit einer modulweit deklarierten Variablen referenziert:<\/p>\n<pre>Dim WithEvents objFrmKundenDetails As Form<\/pre>\n<p>F&uuml;r diese legen wir &#8211; wie schon f&uuml;r das Unterformular &#8211; Ereignisprozeduren an. Diese besitzen nur eine einzige Anweisung, welche die Funktion <b>SilentRequery <\/b>mit dem Namen des Feldes <b>KundeID <\/b>aufruft:<\/p>\n<pre>Private Sub frmKundenDetails_AfterUpdate()\r\n    SilentRequery objSfmKundenuebersicht, &quot;KundeID&quot;\r\nEnd Sub\r\nPrivate Sub frmKundenDetails_Close()\r\n    SilentRequery objSfmKundenuebersicht, &quot;KundeID&quot;\r\nEnd Sub<\/pre>\n<p>Warum legen wir dazu gleich zwei Ereignisprozeduren an Weil wir so nicht nur beim Schlie&szlig;en des Detailformulars, sondern auch beim Speichern des dort angezeigten Datensatzes die Daten in der Kunden&uuml;bersicht aktualisieren k&ouml;nnen.<\/p>\n<p>Theoretisch braucht das Formular <b>frmKundendetails <\/b>keinen eigenen Code, damit diese Vorgehensweise funktioniert. Allerdings k&ouml;nnen Sie nur auf Ereignisse dieses Formulars reagieren, wenn dieses auch ein Klassenmodul besitzt.<\/p>\n<p>Normalerweise ist dies reine Formsache, da Sie zumindest Code f&uuml;r die Schaltfl&auml;che <b>cmdOK <\/b>hinterlegen, aber zur Sicherheit: Ist dies nicht der Fall, m&uuml;ssen Sie die Eigenschaft <b>Hat Modul <\/b>des Formulars <b>frmKundendetails <\/b>auf <b>Ja <\/b>einstellen.<\/p>\n<p><b>Neuen Kunden anlegen<\/b><\/p>\n<p>Auch zum Anlegen eines neuen Kunden rufen wir das Formular <b>frmKundenDetails <\/b>auf. Dies gelingt ausschlie&szlig;lich durch einen Mausklick auf die Schaltfl&auml;che <b>cmdNeu<\/b>. Dies l&ouml;st die folgende Ereignisprozedur aus:<\/p>\n<pre>Private Sub cmdNeu_Click()\r\n    DoCmd.OpenForm &quot;frmKundenDetails&quot;, DataMode:=acFormAdd\r\n    Set objFrmKundenDetails = Forms!frmKundenDetails\r\n    With objFrmKundenDetails\r\n        .OnClose = &quot;[Event Procedure]&quot;\r\n        .AfterUpdate = &quot;[Event Procedure]&quot;\r\n    End With\r\nEnd Sub<\/pre>\n<p>Die hier verwendeten Anweisungen arbeiten prinzipiell genau so wie die zum Bearbeiten eines vorhandenen Kunden &#8211; mit der Ausnahme, dass das Formular diesmal durch den Parameter <b>Datamode:=acFormAdd <\/b>gleich einen neuen, leeren Datensatz anzeigt. Auch hier gilt: Der neue Datensatz wird sp&auml;testens beim Schlie&szlig;en des Detailformulars, aber auch bereits beim Speichern in der &Uuml;bersicht angezeigt.<\/p>\n<p><b>Suche starten<\/b><\/p>\n<p>Sie k&ouml;nnen auch das Suchformular aufrufen, um nach bestimmten Datens&auml;tzen in der Kunden&uuml;bersicht zu suchen. Dies gelingt mit einem Klick auf die Schaltfl&auml;che <b>cmdSuche<\/b>. Dies l&ouml;st schlicht die folgende Prozedur aus, die das Formular <b>frmKundensuche <\/b>&ouml;ffnet:<\/p>\n<pre>Private Sub cmdSuche_Click()\r\n    DoCmd.OpenForm &quot;frmKundensuche&quot;, OpenArgs:=&quot;sfmKundenuebersicht&quot;\r\nEnd Sub<\/pre>\n<p>Die Prozedur &uuml;bergibt den Namen des zu durchsuchenden Unterformulars als Parameter an das aufgerufene Formular.<\/p>\n<p><b>Feinheiten<\/b><\/p>\n<p>Um das Design der beiden Formulare <b>frmKundenDetails <\/b>und <b>frmKundensuche <\/b>k&uuml;mmern wir uns gleich, vorher noch einige Kleinigkeiten:<\/p>\n<p>Das Hauptformular <b>frmKundenuebersicht <\/b>zeigt selbst keine Daten an, es besteht also kein Anlass, Elemente wie den Datensatzmarkierer oder die Navigationsschaltfl&auml;chen einzublenden. Also stellen Sie die Eigenschaften <b>Datensatzmarkierer<\/b>, <b>Navigationsschaltfl&auml;chen<\/b>, <b>Trennlinien <\/b>und <b>Bildlaufleisten <\/b>auf den Wert <b>Nein <\/b>und <b>Automatisch zentrieren <\/b>auf <b>Ja <\/b>ein.<\/p>\n<p><b>Kundensuche<\/b><\/p>\n<p>Das Formular <b>frmKundensuche <\/b>wird durch einen Klick auf die entsprechende Schaltfl&auml;che des Formulars <b>frmKundenuebersicht <\/b>ge&ouml;ffnet. Beim &Ouml;ffnen sollte mit dem &Ouml;ffnungsargument, das mit <b>Me.OpenArgs<\/b> abgefragt wird, der Name des Unterformulars &uuml;bergeben werden, auf das sich die Suche bezieht. Auf diese Weise k&ouml;nnen das Suchformular und das Suchergebnis aufeinander abgestimmt werden. Details zur Funktion der Kundensuche finden Sie im Beitrag <b>Kundensuche mit Komfort <\/b>(<b>www.access-im-unternehmen.de\/858<\/b>).<\/p>\n<p><b>Kunden im Detail anzeigen<\/b><\/p>\n<p>Das Detailformular zur Anzeige eines Kunden sieht im Entwurf wie in Bild 12 aus. Es ist an die Datenherkunft <b>tblKunden<\/b> gebunden &#8211; also an die Abfrage, die den gleichen Namen wie eine Tabelle hat, um die Daten der eigentlichen Tabelle gefiltert und ohne als gel&ouml;scht markierte Datens&auml;tze zu liefern. Wir h&auml;tten hier auch die Tabelle <b>tblKundenBase<\/b> als Datenherkunft angeben k&ouml;nnen, da das Formular ohnehin nicht alle Datens&auml;tze dieser Tabelle liefert, sondern immer nur einen &#8211; und der wird &uuml;ber das &Uuml;bersichtsformular <b>frmKundenuebersicht <\/b>ausgew&auml;hlt, das keine als gel&ouml;scht markierten Datens&auml;tze anzeigt.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic019.png\" alt=\"pic019.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 12: Entwurfsansicht des Formulars frmKundendetails<\/span><\/b><\/p>\n<p>Das Formular enth&auml;lt alle Felder der Datenherkunft, wobei einige wegen des f&uuml;r die Suche verwendeten Listenfeldes oben rechts in der Abbildung nicht sichtbar sind. Das Formular enth&auml;lt au&szlig;erdem zwei Unterformulare: eines zur Anzeige der Bankverbindungen und ein weiteres f&uuml;r die Vertragsdaten. Au&szlig;erdem finden sich im Formular noch ein Textfeld und ein Listenfeld, die gemeinsam eine Schnellsuche zum flotten Auffinden und Anzeigen weiterer Kunden liefern. Schlie&szlig;lich sind da noch f&uuml;nf Schaltfl&auml;chen. Zwei &ouml;ffnen das Formular <b>frmAnschreibenErstellen<\/b>, eine zeigt einen Bericht zur Ausgabe von Adressetiketten in der Vorschau an und eine weitere druckt das Adressetikett schlie&szlig;lich aus.<\/p>\n<p>Die letzte Schaltfl&auml;che im Bunde hei&szlig;t <b>cmdOK <\/b>und schlie&szlig;t das Formular <b>frmKundendetails<\/b> wieder.<\/p>\n<p><b>&Ouml;ffnen des Formulars <\/b><\/p>\n<p>Da wir auch von diesem Hauptformular aus wieder auf die Ereignisse der Unterformulare zugreifen m&ouml;chten, werden wieder zwei entsprechende Variablen deklariert:<\/p>\n<pre>Dim WithEvents objsfmVertraege As Form\r\nDim WithEvents objsfmBankverbindungen As Form<\/pre>\n<p>Diese werden gleich in der Ereignisprozedur, die durch das Ereignis <b>Beim Laden <\/b>ausgel&ouml;st wird, gef&uuml;llt (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-73-anchor\">Listing 4<\/a><\/span>).<\/p>\n<p class=\"listingueberschrift\">Listing 4: Ereignisprozedur, die beim Laden des Formulars frmKundendetails ausgel&ouml;st wird<\/p>\n<pre>Private Sub Form_Load()\r\n    Set objsfmVertraege = Me!sfmVertraege.Form\r\n    With objsfmVertraege\r\n        .OnCurrent = &quot;[Event Procedure]&quot;\r\n    End With\r\n    Set objsfmBankverbindungen = Me!sfmBankverbindungen.Form\r\n    With objsfmBankverbindungen\r\n        .OnCurrent = &quot;[Event Procedure]&quot;\r\n    End With\r\nEnd Sub<\/pre>\n<p>Die erste Ereignisprozedur betrifft das Unterformular <b>sfmBankverbindungen<\/b>. Wann immer sich dort etwas tut &#8211; egal, ob ein Datensatz hinzugef&uuml;gt, bearbeitet oder gel&ouml;scht wird &#8211; soll ein Feld in dem anderen Unterformular, <b>sfmVertraege<\/b>, aktualisiert werden. Dabei handelt es sich um das Feld <b>cboBankverbindungID<\/b>, mit der der Benutzer die f&uuml;r einen Vertrag zu verwendende Bankverbindung ausw&auml;hlt.<\/p>\n<p>Es kann zum Beispiel sein, dass der Benutzer einen Kunden anlegt, dann einen Vertrag hinzuf&uuml;gt und schlie&szlig;lich beim Versuch, eine Bankverbindung auszuw&auml;hlen, feststellt, dass er noch gar keine Bankverbindung f&uuml;r den Kunden angelegt hat. Wenn er dies nun im anderen Unterformular <b>sfmBankverbindungen <\/b>erledigt, soll diese neue Bankverbindung auch gleich im Unterformular <b>sfmVertraege <\/b>zur Auswahl bereitstehen:<\/p>\n<pre>Private Sub objsfmBankverbindungen_Current()\r\n    objsfmVertraege!cboBankverbindungID.Requery\r\nEnd Sub<\/pre>\n<p>Die zweite Ereignisprozedur eines Unterformulars, die im Klassenmodul des Hauptformulars implementiert werden soll, wird durch das Unterformular <b>sfmVertraege<\/b> ausgel&ouml;st &#8211; ebenfalls durch das Ereignis <b>Beim Anzeigen<\/b>:<\/p>\n<pre>Private Sub objsfmVertraege_Current()\r\n    SchaltflaechenAktivieren\r\nEnd Sub<\/pre>\n<p>Dieses ruft die Prozedur <b>SchaltflaechenAktivieren<\/b> auf (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-76-anchor\">Listing 5<\/a><\/span>), die zuerst pr&uuml;ft, ob im Hauptformular &uuml;berhaupt ein Kunde angelegt wurde beziehungsweise angezeigt wird &#8211; dazu muss das Feld <b>KundeID <\/b>gef&uuml;llt sein. Das Ergebnis dieser Pr&uuml;fung landet in der Variablen <b>bolKundeNichtNull<\/b>. Eine weitere Pr&uuml;fung untersucht, ob es im Unterformular <b>sfmVertraege <\/b>bereits Datens&auml;tze zu diesem Kunden gibt. Falls ja, stellt dies die Variable <b>bolVertragNichtNull <\/b>auf <b>True <\/b>ein.<\/p>\n<p class=\"listingueberschrift\">Listing 5: Aktivieren von Schaltfl&auml;chen im Formular frmKundendetails<\/p>\n<pre>Private Sub SchaltflaechenAktivieren()\r\n    Dim bolKundeNichtNull As Boolean\r\n    Dim bolVertragNichtNull As Boolean\r\n    bolKundeNichtNull = Not IsNull(Me!KundeID)\r\n    bolVertragNichtNull = Not IsNull(objsfmVertraege!VertragID)\r\n    Me!cmdAdressetikett.Enabled = bolKundeNichtNull\r\n    Me!cmdAdressetikettVorschau.Enabled = bolKundeNichtNull\r\n    Me!cmdNeuesDokument.Enabled = bolKundeNichtNull\r\n    Me!cmdNeuesVertragsdokument.Enabled = bolKundeNichtNull And bolVertragNichtNull\r\nEnd Sub<\/pre>\n<p>Nun stellt die Prozedur in Abh&auml;ngigkeit von dieser <b>Boolean<\/b>-Variablen einige <b>Enabled<\/b>-Eigenschaften der verschiedenen Schaltfl&auml;chen ein. <b>cmdAdressetikett<\/b>, <b>cmdAdressetikettVorschau <\/b>und <b>cmdNeuesDokument <\/b>werden zum Beispiel aktiviert, wenn <b>bolKundeNichtNull <\/b>den Wert <b>True <\/b>hat. Bei der Schaltfl&auml;che <b>cmdNeuesVertragsdokument <\/b>muss zus&auml;tzlich auch noch <b>bolVertragNichtNull <\/b>den Wert <b>True <\/b>haben. Der Hintergrund ist klar: Wenn die entsprechenden Daten nicht vorliegen, soll der Benutzer auch keine Etiketten beziehungsweise Word-Dokumente auf Basis dieser Daten anlegen k&ouml;nnen. Schauen wir uns nun zun&auml;chst die Unterformulare und ihre Funktionen an.<\/p>\n<p><b>Das Unterformular sfmBankverbindungen<\/b><\/p>\n<p>Dieses Unterformular zeigt die beiden Felder <b>Geldinstitut <\/b>und <b>Kontonummer <\/b>der Tabelle <b>tblBankverbindungen <\/b>an (s. Bild 13). Es soll die Daten in einer Liste anzeigen, also stellen Sie seine Eigenschaft <b>Standardansicht<\/b> auf <b>Datenblatt <\/b>ein.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic014.png\" alt=\"pic014.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 13: Entwurf des Unterformulars sfmBankverbindungen<\/span><\/b><\/p>\n<p>Damit es nur die Bankverbindungen anzeigt, die &uuml;ber das Feld <b>KundeID <\/b>mit dem aktuell im Hauptformular angezeigten Kunden verkn&uuml;pft sind, stellen Sie die beiden Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>des Unterformularsteuerelements jeweils auf den Wert <b>KundeID <\/b>ein (s. Bild 14).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic018.png\" alt=\"pic018.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 14: Synchronisierung von Haupt- und Unterformular<\/span><\/b><\/p>\n<p>Ein Doppelklick auf das Kombinationsfeld <b>cboGeldinstitutID <\/b>soll das Formular <b>frmGeldinstitute <\/b>&ouml;ffnen, damit der Benutzer die Eintr&auml;ge der Tabelle <b>tblGeldinstitute <\/b>bearbeiten kann. Dies l&ouml;st die Prozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-75-anchor\">Listing 6<\/a><\/span> aus. Die Prozedur &ouml;ffnet das Formular <b>frmGeldinstitute<\/b> als modalen Dialog und f&uuml;llt die wie folgt deklarierte Variable mit einem Verweis auf dieses Formular:<\/p>\n<p class=\"listingueberschrift\">Listing 6: &Ouml;ffnen der Liste der Geldinstitute per Doppelklick<\/p>\n<pre>Private Sub cboGeldinstitutID_DblClick(Cancel As Integer)\r\n    DoCmd.OpenForm &quot;frmGeldinstitute&quot;, OpenArgs:=Nz(Me!cboGeldinstitutID)\r\n    Set objFrmGeldinstitute = Forms!frmGeldinstitute\r\n    With objFrmGeldinstitute\r\n        .Modal = True\r\n        .OnUnload = &quot;[Event Procedure]&quot;\r\n    End With\r\nEnd Sub\r\nDim WithEvents objFrmGeldinstitute As Form<\/pre>\n<p>Desweiteren stellt die Prozedur die Eigenschaft <b>Modal <\/b>auf <b>True <\/b>ein und legt f&uuml;r die Eigenschaft <b>OnUnload <\/b>den Wert <b>[Event Procedure] <\/b>fest. <\/p>\n<p>Damit wollen wir sicherstellen, dass beim Schlie&szlig;en dieses Formulars das dort aktuell ausgew&auml;hlte Geldinstitut als Auswahl in das Kombinationsfeld <b>cboGeldinstitute <\/b>&uuml;bernommen wird.<\/p>\n<p>Dies erledigt die folgende Ereignisprozedur, die Sie wie folgt im Klassenmodul <b>Form_sfmBankverbindungen <\/b>implementieren:<\/p>\n<pre>Private Sub objFrmGeldinstitute_Unload(Cancel As Integer)\r\n    If Not IsNull(Forms!frmGeldinstitute!lst) Then\r\n        Me!cboGeldinstitutID.Requery\r\n        Me!cboGeldinstitutID = Forms!frmGeldinstitute!lst\r\n    End If\r\nEnd Sub<\/pre>\n<p><b>Das Formular frmGeldinstitute<\/b><\/p>\n<p>Das Formular zur Verwaltung der Geldinstitute sieht im Entwurf wie in Bild 15 aus. Das Formular zeigt in einem Listenfeld namens <b>lst <\/b>die Daten der Tabelle <b>tblGeldinstitute <\/b>an &#8211; und zwar so, dass das Feld <b>GeldinstitutID <\/b>in der unsichtbaren ersten Spalte und das zweite, aus den Feldern <b>Geldinstitut <\/b>und <b>Bankleitzahl <\/b>zusammengesetzte Feld in der zweiten, sichtbaren Spalte erscheint.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic016.png\" alt=\"pic016.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 15: Das Formular frmGeldinstitute in der Entwurfsansicht<\/span><\/b><\/p>\n<p>Dazu verwendet das Listenfeld die folgende <b>Datensatzherkunft<\/b>, die auch noch nach der Bankleitzahl sortiert wird:<\/p>\n<pre>SELECT GeldinstitutID, Geldinstitut &amp; &quot; (&quot; &amp; Bankleitzahl &amp; &quot;)&quot; AS Geldinstitutname FROM tblGeldinstitute ORDER BY Bankleitzahl;<\/pre>\n<p>Damit die erste Spalte ausgeblendet wird und nur die zweite Spalte angezeigt wird, stellen Sie die beiden Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>auf die Werte <b>2 <\/b>und <b>0cm <\/b>ein.<\/p>\n<p><b>Geldinstitut vorausw&auml;hlen<\/b><\/p>\n<p>Wenn beim &Ouml;ffnen des Formulars &uuml;ber das Kombinationsfeld <b>cboGeldinstitutID <\/b>des Unterformulars <b>sfmGeldinstitute <\/b>bereits ein Eintrag im Kombinationsfeld ausgew&auml;hlt war, soll dieser gleich im Listenfeld markiert werden.<\/p>\n<p>Dies erledigt die folgende Prozedur, die beim Laden des Formulars ausgel&ouml;st wird und nicht nur die Hintergrundfarbe des Formularkopfes einstellt, sondern auch noch das Listenfeld auf den betreffenden Geldinstitut-Datensatz.<\/p>\n<p>Dieser wurde beim &Ouml;ffnen mit der <b>OpenForm<\/b>-Methode gegebenenfalls als &Ouml;ffnungsargument &uuml;bergeben:<\/p>\n<pre>Private Sub Form_Load()\r\n    Me.Formularkopf.BackColor = Kopffarbe\r\n    If Not IsNull(Me.OpenArgs) Then\r\n        Me!lst = Me.OpenArgs\r\n    End If\r\nEnd Sub<\/pre>\n<p><b>L&ouml;schen eines Geldinstituts<\/b><\/p>\n<p>Wenn Sie einen der Eintr&auml;ge l&ouml;schen m&ouml;chten, verwenden Sie die Schaltfl&auml;che <b>cmdLoeschen<\/b>. Diese l&ouml;st die Ereignisprozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-78-anchor\">Listing 7<\/a><\/span> aus, die vor dem L&ouml;schen noch eine R&uuml;ckfrage an den Benutzer richtet, ob dieser den Datensatz wirklich l&ouml;schen m&ouml;chte.<\/p>\n<p class=\"listingueberschrift\">Listing 7: L&ouml;schen eines Geldinstituts<\/p>\n<pre>Private Sub cmdLoeschen_Click()\r\n    Dim db As DAO.Database\r\n    If Not IsNull(Me!lst) Then\r\n        If MsgBox(&quot;Soll das Gelsinstitut ''''&quot; &amp; Me!lst.Column(1) &amp; &quot;'''' wirklich gel&ouml;scht werden&quot;, _\r\n                vbYesNo + vbExclamation, &quot;Geldinstitut l&ouml;schen&quot;) = vbYes Then\r\n            Set db = CurrentDb\r\n            db.Execute &quot;DELETE FROM tblGeldinstitute WHERE GeldinstitutID = &quot; &amp; Me!lst\r\n            Set db = Nothing\r\n            Me!lst.Requery\r\n        End If\r\n    End If\r\nEnd Sub<\/pre>\n<p><b>Bearbeiten eines Geldinstituts<\/b><\/p>\n<p>Auch das Bearbeiten eines Datensatzes der Tabelle <b>tblGeldinstitute <\/b>ist m&ouml;glich (gelegentlich &auml;ndern Banken ja mal ihren Namen).<\/p>\n<p>Dazu klicken Sie doppelt auf den zu &auml;ndernden Eintrag im Listenfeld und l&ouml;sen damit die Prozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-79-anchor\">Listing 8<\/a><\/span> aus.<\/p>\n<p class=\"listingueberschrift\">Listing 8: Bearbeiten eines Geldinstituts<\/p>\n<pre>Private Sub lst_DblClick(Cancel As Integer)\r\n    If Not IsNull(Me!lst) Then\r\n        DoCmd.OpenForm &quot;frmGeldinstitutdetails&quot;, WindowMode:=acDialog, _\r\n        WhereCondition:=&quot;GeldinstitutID = &quot; &amp; Me!lst, DataMode:=acFormEdit\r\n        Me!lst.Requery\r\n    End If\r\nEnd Sub<\/pre>\n<p><b>Formular frmGeldinstitute schlie&szlig;en<\/b><\/p>\n<p>Mit einem Klick auf die Schaltfl&auml;che <b>cmdOK <\/b>schlie&szlig;t der Benutzer das Formular <b>frmGeldinstitute <\/b>schlie&szlig;lich wieder:<\/p>\n<pre>Private Sub cmdOK_Click()\r\n    DoCmd.Close\r\nEnd Sub<\/pre>\n<p>Dadurch wird die im Unterformular <b>sfmBankverbindungen<\/b> definierte Ereignisprozedur <b>objFrmGeldinstitute_Unload <\/b>ausgel&ouml;st (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-89-anchor\">Listing 9<\/a><\/span>), was dazu f&uuml;hrt, dass der aktuell markierte Datensatz in der Liste der Geldinstitute in das Kombinationsfeld &uuml;bernommen wird, mit dem der Benutzer das Formular <b>frmGeldinstitute <\/b>per Doppelklick ge&ouml;ffnet hat.<\/p>\n<p class=\"listingueberschrift\">Listing 9: Aktualisieren der Geldinstitute im Kombinationsfeld<\/p>\n<pre>Private Sub objFrmGeldinstitute_Unload(Cancel As Integer)\r\n    If Not IsNull(Forms!frmGeldinstitute!lst) Then\r\n        Me!cboGeldinstitutID.Requery\r\n        Me!cboGeldinstitutID = Forms!frmGeldinstitute!lst\r\n    End If\r\nEnd Sub<\/pre>\n<p><b>Das Formular frmGeldinstitutDetails<\/b><\/p>\n<p>Das Anlegen und Bearbeiten der Datens&auml;tze der Tabelle <b>tblGeldinstitute <\/b>erfolgt im Formular <b>frmGeldinstitutDetails<\/b>, das im Entwurf wie in Bild 16 aussieht.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic017.png\" alt=\"pic017.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 16: Entwurf des Formulars frmGeldinstitutDetails<\/span><\/b><\/p>\n<p>Es verwendet die Tabelle <b>tblGeldinstitute <\/b>als Datenherkunft. Sie k&ouml;nnen den angezeigten Datensatz damit &auml;ndern oder einen neuen Datensatz eingeben.<\/p>\n<p>Ein Klick auf die Schaltfl&auml;che <b>cmdOK <\/b>schlie&szlig;t das Formular wieder:<\/p>\n<pre>Private Sub cmdOK_Click()\r\n    DoCmd.Close acForm, Me.Name\r\nEnd Sub<\/pre>\n<p><b>Das Unterformular sfmVertraege<\/b><\/p>\n<p>Damit verlassen wir das Unterformular <b>sfmBankverbindungen<\/b> und widmen uns dem Unterformular <b>sfmVertraege<\/b>.<\/p>\n<p>Dieses sieht im Entwurf wie in Bild 17 aus und bezieht seine Daten aus der Tabelle <b>tblVertraege<\/b>. Es soll genau wie das Unterformular <b>sfmBankverbindungen <\/b>nur solche Datens&auml;tze anzeigen, die mit dem aktuell im Hauptformular enthaltenen Datensatz der Datenherkunft <b>tblKunden <\/b>verkn&uuml;pft sind.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic015.png\" alt=\"pic015.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 17: Entwurf des Unterformulars sfmVertraege<\/span><\/b><\/p>\n<p>Stellen Sie also auch hier die Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>des Unterformular-Steuerelements auf den Wert <b>KundeID <\/b>ein.<\/p>\n<p>&Uuml;ber dieses Unterformular k&ouml;nnen Sie, jeweils per Doppelklick, Formulare zum Verwalten der Werte der Kombinationsfelder <b>cboGesellschaftID<\/b> und <b>cboVertragsartID <\/b>&ouml;ffnen. Bei den Gesellschaften l&ouml;st ein Doppelklick auf das Kombinationsfeld die Prozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-96-anchor\">Listing 10<\/a><\/span> aus. Dies &ouml;ffnet das Formular <b>frmGesellschaften <\/b>und &uuml;bergibt als &Ouml;ffnungsargument die <b>GesellschaftID <\/b>des aktuell im Kombinationsfeld ausgew&auml;hlten Eintrags.<\/p>\n<p class=\"listingueberschrift\">Listing 10: &Ouml;ffnen des Dialogs zum Bearbeiten der Gesellschaften<\/p>\n<pre>Private Sub cboGesellschaftID_DblClick(Cancel As Integer)\r\n    DoCmd.OpenForm &quot;frmGesellschaften&quot;, OpenArgs:=Nz(Me!cboGesellschaftID)\r\n    Set objFrmGesellschaften = Forms!frmGesellschaften\r\n    With objFrmGesellschaften\r\n        .PopUp = True\r\n        .OnUnload = &quot;[Event Procedure]&quot;\r\n    End With\r\nEnd Sub<\/pre>\n<p><b>Neues Geldinstitut anlegen<\/b><\/p>\n<p>Einen neuen Datensatz k&ouml;nnen Sie der Tabelle <b>tblGeldinstitute <\/b>hinzuf&uuml;gen, indem Sie auf die Schaltfl&auml;che <b>cmdNeu <\/b>klicken. Dies l&ouml;st die folgende Prozedur aus, die das Formular <b>frmGeldinstitutDetails <\/b>&ouml;ffnet &#8211; und zwar im Anf&uuml;gemodus:<\/p>\n<pre>Private Sub cmdNeu_Click()\r\n    DoCmd.OpenForm &quot;frmGeldinstitutdetails&quot;, WindowMode:=acDialog, DataMode:=acFormAdd\r\n    Me!lst.Requery\r\nEnd Sub<\/pre>\n<p>Ohne auf dieses Formular einzugehen, schauen wir uns noch an, was geschieht, wenn der Benutzer dieses wieder schlie&szlig;t: Dies l&ouml;st n&auml;mlich die im Klassenmodul <b>Form_sfmVertraege <\/b>implementierte Ereignisprozedur <b>objFrmGesellschaften_Unload <\/b>aus, die Sie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-84-anchor\">Listing 11<\/a><\/span> finden.<\/p>\n<p class=\"listingueberschrift\">Listing 11: Aktionen nach dem Schlie&szlig;en des Formulars frmGesellschaften<\/p>\n<pre>Private Sub objFrmGesellschaften_Unload(Cancel As Integer)\r\n    If Not IsNull(Forms!frmGesellschaften!lst) Then\r\n        Me!cboGesellschaftID.Requery\r\n        Me!cboGesellschaftID = Forms!frmGesellschaften!lst\r\n    End If\r\nEnd Sub<\/pre>\n<p>Dies &uuml;bernimmt den aktuell im Listenfeld des Formulars <b>frmGesellschaften <\/b>ausgew&auml;hlten Eintrag in das Kombinationsfeld <b>cboGesellschaftID<\/b>.<\/p>\n<p>Das durch den Doppelklick auf das Kombinationsfeld ge&ouml;ffnete Formular <b>frmGesellschaften<\/b> (s. Bild 18) ist genau so aufgebaut wie das Formular <b>frmGeldinstitute <\/b>und hat auch genau die gleichen Funktionen &#8211; bis hin zum ebenfalls &auml;hnlich gestalteten Formular <b>frmGesellschaftDetails <\/b>zum Anlegen neuer und Bearbeiten vorhandener Gesellschaften.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic0191.png\" alt=\"pic019.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 18: Entwurf des Formulars frmGesellschaften<\/span><\/b><\/p>\n<p><b>Nur Bankverbindungen des aktuellen Kunden anzeigen<\/b><\/p>\n<p>Das Kombinationsfeld <b>cboBankverbindungen <\/b>im Unterformular <b>sfmVertraege <\/b>soll nur die Bankverbindungen anzeigen, die zum aktuell im Hauptformular angezeigten Kunden geh&ouml;ren. Dazu wird diese Datensatzherkunft bei jedem Datensatzwechsel im Hauptformular aktualisiert, und zwar durch eine Ereignisprozedur, die durch das Ereignis <b>Beim Anzeigen <\/b>des Hauptformulars ausgel&ouml;st wird (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-88-anchor\">Listing 12<\/a><\/span>). Anschlie&szlig;end aktualisiert diese Prozedur durch einen Aufruf der Routine <b>SchaltflaechenAktualisieren <\/b>auch noch den Aktiviert-Status der Schaltfl&auml;chen &#8211; immerhin kann es ja sein, dass ein neuer Kunde noch keine Vertr&auml;ge aufweist und die Schaltfl&auml;che <b>cmdNeuesVertragsdokument <\/b>deaktiviert werden muss oder umgekehrt.<\/p>\n<p class=\"listingueberschrift\">Listing 12: Aktualisieren der Datensatzherkunft des Kombinationsfeldes cboBankverbindung<\/p>\n<pre>Private Sub Form_Current()\r\n    objsfmVertraege!cboBankverbindungID.RowSource = _\r\n        &quot;SELECT [tblBankverbindungen].[BankverbindungID], ''''Konto '''' &amp; &quot; _\r\n        &amp; &quot;[tblBankverbindungen].[Kontonummer] &amp; '''' bei '''' &amp; tblGeldinstitute.Geldinstitut &quot; _\r\n        &amp; &quot;FROM tblBankverbindungen INNER JOIN tblGeldinstitute &quot; _\r\n        &amp; &quot;ON tblBankverbindungen.GeldinstitutID = tblGeldinstitute.GeldinstitutID &quot; _\r\n        &amp; &quot;WHERE BankverbindungID IN (SELECT BankverbindungID FROM tblBankverbindungen &quot; _\r\n        &amp; &quot;WHERE KundeID = &quot; &amp; Me!KundeID &amp; &quot;)&quot;\r\n    SchaltflaechenAktivieren\r\n    End Sub<\/pre>\n<p><b>Doppelklick auf Kombinationsfeld publik machen<\/b><\/p>\n<p>So praktisch es ist, mit einem Doppelklick auf ein Kombinationsfeld ein Formular zum Bearbeiten der enthaltenen Daten zu &ouml;ffnen, so gering ist die Wahrscheinlichkeit, dass Otto Normalverbraucher direkt auf diese M&ouml;glichkeit kommt. Also sollten wir ihn mit der Nase darauf sto&szlig;en &#8211; am besten durch einen entsprechenden Hinweistext, der erscheint, wenn die betroffenen Kombinationsfelder den Fokus erhalten.<\/p>\n<p>Wie Ihnen sicher schon aufgefallen ist, verfolgen wir bei dieser L&ouml;sung den Ansatz, dass Abh&auml;ngigkeiten zwischen Formularen nur in eine Richtung gehen. Das hei&szlig;t, dass ein Hauptformular nat&uuml;rlich von der Existenz des als Unterformular eingesetzten Formulars wei&szlig; und auch auf dessen Steuerelemente und Eigenschaften zugreifen kann. Andersherum soll dies aber nicht der Fall sein.<\/p>\n<p>Nun m&ouml;chten wir im Hauptformular <b>frmKundendetails <\/b>einen Hinweistext in einem Steuerelement namens <b>lblHinweis <\/b>einblenden, wenn der Benutzer ein Steuerelement im Unterformular <b>sfmVertraege <\/b>anklickt (s. Bild 19). <\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic020.png\" alt=\"pic020.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 19: Anzeige von Hilfetexten im Hauptformular<\/span><\/b><\/p>\n<p>Normalerweise w&uuml;rden Sie nun entsprechende Ereignisse f&uuml;r die Kombinationsfelder im Unterformular anlegen, die sich auf das Bezeichnungsfeld im Hauptformular beziehen und dieses mit den entsprechenden Hinweistexten versehen.<\/p>\n<p>Genau dies soll aber nach der verfolgten Philosophie nicht geschehen, sondern das Hauptformular soll es erkennen, wenn der Benutzer das Steuerelement im Unterformular anklickt.<\/p>\n<p>Das ist kein Problem: Genau wie bei den Unterformularen k&ouml;nnen wir auch f&uuml;r im Unterformular enthaltene Steuerelemente Objektvariablen mit dem Schl&uuml;sselwort <b>WithEvents <\/b>deklarieren und die ben&ouml;tigten Ereignisprozeduren im Klassenmodul des Hauptformulars, hier <b>Form_frmKundendetails<\/b>, implementieren.<\/p>\n<p>Die beiden Deklarationszeilen sehen so aus:<\/p>\n<pre>Dim WithEvents objCboGesellschaftID As ComboBox\r\nDim WithEvents objCboVertragsartID As ComboBox<\/pre>\n<p>Die Ereignisprozedur <b>Form_Load <\/b>des Formulars <b>frmKundendetails <\/b>erweitern Sie um die folgenden Anweisungen:<\/p>\n<pre>Private Sub Form_Load()\r\n    ...\r\n    Set objCboGesellschaftID = Me!sfmVertraege.Form!cboGesellschaftID\r\n    With objCboGesellschaftID\r\n        .OnGotFocus = &quot;[Event Procedure]&quot;\r\n        .OnLostFocus = &quot;[Event Procedure]&quot;\r\n    End With\r\n    Set objCboVertragsartID = Me!sfmVertraege.Form!cboVertragsartID\r\n    With objCboVertragsartID\r\n        .OnGotFocus = &quot;[Event Procedure]&quot;\r\n        .OnLostFocus = &quot;[Event Procedure]&quot;\r\n    End With\r\nEnd Sub<\/pre>\n<p>Die vier Ereignisprozeduren f&uuml;r diese beiden Objekte sehen wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-100-anchor\">Listing 13<\/a><\/span> aus. Sie weisen der Eigenschaft <b>Caption <\/b>des Bezeichnungsfeldes <b>lblHinweis <\/b>einen Text zu und blenden es ein beziehungsweise aus, wenn das jeweilige Steuerelement den Fokus verliert. Dies geschieht beispielsweise, wenn der Benutzer ein anderes Steuerelement anklickt.<\/p>\n<p class=\"listingueberschrift\">Listing 13: Ein- und Ausblenden eines Hinweises beim Aktivieren von Kombinationsfeldern<\/p>\n<pre>Private Sub objCboGesellschaftID_GotFocus()\r\n    Me!lblHinweis.Caption = &quot;Klicken Sie doppelt auf die Gesellschaft, um diese zu bearbeiten.&quot;\r\n    Me!lblHinweis.Visible = True\r\nEnd Sub\r\nPrivate Sub objCboGesellschaftID_LostFocus()\r\n    Me!lblHinweis.Visible = False\r\nEnd Sub\r\nPrivate Sub objcboVertragsartID_GotFocus()\r\n    Me!lblHinweis.Caption = &quot;Klicken Sie doppelt auf die Vertragsart, um diese zu bearbeiten.&quot;\r\n    Me!lblHinweis.Visible = True\r\nEnd Sub\r\nPrivate Sub objcboVertragsartID_LostFocus()\r\n    Me!lblHinweis.Visible = False\r\nEnd Sub<\/pre>\n<p>F&uuml;r den Fall, dass das Unterformular den Fokus verliert, w&auml;hrend eines der Kombinationsfelder den Fokus hat, m&uuml;ssen wir noch die folgende Ereignisprozedur anlegen:<\/p>\n<pre>Private Sub sfmVertraege_Exit(Cancel As Integer)\r\n    Me!lblHinweis.Visible = False\r\nEnd Sub<\/pre>\n<p>Anderenfalls wird das Bezeichnungsfeld nicht ausgeblendet.<\/p>\n<p><b>Schnellsuche im Formular frmKundendetails<\/b><\/p>\n<p>Neben der Suchfunktion im &Uuml;bersichtsformular der Anwendung soll auch das Detailformular noch mit einer pfiffigen Suchfunktion ausgestattet werden. Diese soll es erm&ouml;glichen, schnell ein paar Buchstaben in ein Suchfeld einzugeben, wobei bestimmte, fest definierte Felder der Tabelle <b>tblKundenBase <\/b>durchsucht und in einem dann erscheinenden Listenfeld angezeigt werden. Der Benutzer soll dann den gew&uuml;nschten Eintrag ausw&auml;hlen und diesen per Doppelklick im Detailformular anzeigen k&ouml;nnen.<\/p>\n<p>Kern dieser Suchfunktion sind das Textfeld <b>txtSuche <\/b>zur Eingabe des Suchbegriffs und das Listenfeld <b>lstSuchergebnis <\/b>zur Anzeige und Auswahl der Suchergebnisse (s. Bild 20).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_05\/KVAEntwicklung-web-images\/pic021.png\" alt=\"pic021.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 20: Suchsteuerelemente im Formular frmKundendetails<\/span><\/b><\/p>\n<p>Den Start macht die Prozedur, die beim Eingeben eines Zeichens in das Such-Textfeld <b>txtSuche <\/b>ausgel&ouml;st wird. Wir verwenden wieder das Ereignis <b>Bei &Atilde;&#8220;nderung<\/b>, weil dieses bei der Eingabe eines jeden Zeichens ausgel&ouml;st wird.<\/p>\n<p>Die entsprechende Prozedur finden Sie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-91-anchor\">Listing 14<\/a><\/span>. Die Prozedur pr&uuml;ft, ob &uuml;berhaupt eine Zeichenkette im Textfeld vorliegt. Falls nicht, wird das Listenfeld geleert und ausgeblendet. Falls der Benutzer jedoch mindestens einen Buchstaben eingegeben hat, stellt die Prozedur einen SQL-Ausdruck zusammen, der die Tabelle beziehungsweise Abfrage <b>tblKunden <\/b>als Datenherkunft verwendet und alle Datens&auml;tze liefert, deren Felder <b>Vorname<\/b>, <b>Nachname<\/b>, <b>Strasse<\/b>, <b>PLZ <\/b>oder <b>Ort <\/b>den Suchbegriff enthalten.<\/p>\n<p class=\"listingueberschrift\">Listing 14: Ein- und Ausblenden eines Hinweises beim Aktivieren von Kombinationsfeldern<\/p>\n<pre>Private Sub txtSuche_Change()\r\n    Dim strSQL As String\r\n    If Len(Me!txtSuche.Text) &gt; 0 Then\r\n        strSQL = &quot;SELECT KundeID, Vorname &amp; '''' '''' &amp; Nachname &amp; ''''|'''' &amp; Strasse &amp; ''''|'''' &amp; PLZ &amp; '''' '''' &quot; _\r\n            &amp; &quot;&amp; Ort FROM tblKunden WHERE Vorname &amp; '''' '''' &amp; Nachname &amp; ''''|'''' &amp; Strasse &amp; ''''|'''' &amp; PLZ &quot; _\r\n            &amp; &quot;&amp; '''' '''' &amp; Ort LIKE ''''*&quot; &amp; Me!txtSuche.Text &amp; &quot;*''''&quot;\r\n        Me!lstSuchergebnis.RowSource = strSQL\r\n        If Me!lstSuchergebnis.ListCount &gt; 0 Then\r\n            Me!lstSuchergebnis.Visible = True\r\n        Else\r\n            Me!lstSuchergebnis.Visible = False\r\n        End If\r\n    Else\r\n        Me!lstSuchergebnis.RowSource = &quot;&quot;\r\n        Me!lstSuchergebnis.Visible = False\r\n    End If\r\nEnd Sub<\/pre>\n<p>Die Abfrage liefert zwei Felder zur&uuml;ck: den in <b>KundeID <\/b>gespeicherten Prim&auml;rschl&uuml;sselwert und einen aus den wichtigsten Feldern zusammengesetzten Ausdruck mit Vorname, Nachname, Stra&szlig;e und so weiter.<\/p>\n<p>Dies sind die Daten, die im Listenfeld <b>lstSuchergebnis <\/b>angezeigt werden, das Feld <b>KundeID <\/b>dient als unsichtbares Feld zur sp&auml;teren Auswahl des gesuchten Datensatzes im Formular <b>frmKundendetails<\/b>.<\/p>\n<p>Das Listenfeld erh&auml;lt f&uuml;r die Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>die Werte <b>2 <\/b>und <b>0cm<\/b>, damit nur die wichtigen Informationen angezeigt werden.<\/p>\n<p>Wenn diese SQL-Anweisung mindestens einen Datensatz zur&uuml;ckliefert, wird das Listenfeld durch Einstellen der Eigenschaft <b>Visible <\/b>auf den Wert <b>True <\/b>sichtbar gemacht, anderenfalls blendet die Prozedur das Steuerelement aus.<\/p>\n<p>Liegen Suchergebnisse vor, m&ouml;chte der Benutzer diese schnell anw&auml;hlen. Das geht am schnellsten per <b>Nach unten<\/b>-Taste, wenn der Benutzer ohnehin gerade einen Suchbegriff eingetippt hat. Die Ereignisprozedur <b>Bei Taste ab <\/b>(implementiert wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-90-anchor\">Listing 15<\/a><\/span>) springt auf solche Eingaben an und verschiebt den Fokus auf das Listenfeld, wenn der Benutzer die <b>Nach unten<\/b>-, die <b>Nach rechts<\/b>&#8211; oder die <b>Tabulator<\/b>-Taste bet&auml;tigt.<\/p>\n<p class=\"listingueberschrift\">Listing 15: Nach unten- und Nach rechts-Taste im Suchfeld<\/p>\n<pre>Private Sub txtSuche_KeyDown(KeyCode As Integer, Shift As Integer)\r\n    If Me!lstSuchergebnis.Visible = False Then\r\n        Exit Sub\r\n    End If\r\n    Select Case KeyCode\r\n        Case vbKeyTab, vbKeyRight, vbKeyDown\r\n            Me!lstSuchergebnis.SetFocus\r\n            Me!lstSuchergebnis = Me!lstSuchergebnis.ItemData(0)\r\n            KeyCode = 0\r\n        Case Else\r\n            Debug.Print KeyCode\r\n    End Select\r\nEnd Sub<\/pre>\n<p>Von dort geht es wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-92-anchor\">Listing 16<\/a><\/span> definiert weiter.<\/p>\n<p class=\"listingueberschrift\">Listing 16: Tastenanschl&auml;ge im Suchergebnis-Listenfeld<\/p>\n<pre>Private Sub lstSuchergebnis_KeyDown(KeyCode As Integer, Shift As Integer)\r\n    Dim bolZurueck As Boolean\r\n    Select Case KeyCode\r\n        Case vbKeyEscape\r\n            Me!txtSuche.SetFocus\r\n            Me!txtSuche.SelStart = Me!txtSuche.SelLength\r\n            Me!lstSuchergebnis.Visible = False\r\n            Me!lstSuchergebnis = Null\r\n            KeyCode = 0\r\n        Case 13\r\n            DatensatzAnzeigen\r\n            KeyCode = 0\r\n            Exit Sub\r\n        Case vbKeyUp, vbKeyLeft\r\n            bolZurueck = True\r\n        Case vbKeyTab\r\n            If Shift = acShiftMask Then\r\n                bolZurueck = True\r\n            End If\r\n        Case Else\r\n            Debug.Print KeyCode\r\n    End Select\r\n    If bolZurueck And Me!lstSuchergebnis.ListIndex = 0 Then\r\n        Me!txtSuche.SetFocus\r\n        Me!txtSuche.SelStart = Me!txtSuche.SelLength\r\n        Me!lstSuchergebnis = Null\r\n        KeyCode = 0\r\n    End If\r\nEnd Sub<\/pre>\n<p>Klickt der Benutzer im Listenfeld auf <b>Escape<\/b>, landet der Fokus wieder im Suchfeld <b>txtSuche<\/b> und die Ergebnisliste wird ausgeblendet. Bet&auml;tigt er die Eingabetaste, wird der aktuell im Suchergebnis markierte Datensatz im Formular <b>frmKundendetails <\/b>angezeigt &#8211; dies erledigt die Prozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-93-anchor\">Listing 17<\/a><\/span>.<\/p>\n<p class=\"listingueberschrift\">Listing 17: Auswahl eines Suchergebnisses<\/p>\n<pre>Private Sub DatensatzAnzeigen()\r\n    Me.Recordset.FindFirst &quot;KundeID = &quot; &amp; Me!lstSuchergebnis\r\n    Me!lstSuchergebnis = Null\r\n    Me!txtSuche = Null\r\n    Me!txtSuche.SetFocus\r\n    Me!lstSuchergebnis.Visible = False\r\nEnd Sub<\/pre>\n<p>Fehlt noch eine Prozedur, die beim Mausklick auf einen der Eintr&auml;ge den gew&uuml;nschten Datensatz anzeigt:<\/p>\n<pre>Private Sub lstSuchergebnis_Click()\r\n    DatensatzAnzeigen\r\nEnd Sub<\/pre>\n<p>Und schlie&szlig;lich soll der Benutzer auch noch per Tastenkombination <b>Strg + F <\/b>zum Suchfenster gelangen, um dort direkt den Suchbegriff eingeben zu k&ouml;nnen.<\/p>\n<p>Dies erm&ouml;glicht die Prozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-94-anchor\">Listing 18<\/a><\/span>, die alle Tastenanschl&auml;ge bei aktiviertem Formular erfasst und bei der angegebenen Tastenkombination den Fokus auf das Textfeld <b>txtSuche <\/b>verschiebt.<\/p>\n<p class=\"listingueberschrift\">Listing 18: Aktivieren der Suchfunktion<\/p>\n<pre>Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)\r\n    Select Case KeyCode\r\n        Case vbKeyF\r\n            If Shift = acCtrlMask Then\r\n                Me!txtSuche.SetFocus\r\n                KeyCode = 0\r\n            End If\r\n    End Select\r\nEnd Sub<\/pre>\n<p>Damit dies gelingt, m&uuml;ssen Sie &uuml;brigens noch die <b>Tastenvorschau <\/b>des Formulars auf <b>Ja <\/b>einstellen.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Die Beschreibung der technischen Eigenheiten einer halbwegs komplexen Anwendung kann schnell sehr umfangreich werden. Daf&uuml;r sehen Sie aber einmal, welche Zusammenh&auml;nge alle beachtet werden m&uuml;ssen, wenn Sie einmal ein paar aufeinander aufbauende Formulare programmieren. <\/p>\n<p>Und dabei haben wir noch nicht einmal alle Aspekte bedacht beziehungsweise nicht alle Funktionen der Anwendung beschrieben.<\/p>\n<p>Deshalb k&uuml;mmern wir uns in weiteren Beitr&auml;gen in kommenden Ausgaben von Access im Unternehmen noch um Themen wie etwa die Validierung der Formulare, das Erstellen der Anschreiben an die Kunden und auch um weitere technische Eigenheiten. So programmieren wir sowohl f&uuml;r die neueren Access-Versionen ein Ribbon als auch f&uuml;r &auml;ltere Versionen eine Men&uuml;leiste, mit welcher der Benutzer die enthaltenen Funktionen schnell aufrufen kann.<\/p>\n<p>Haben Sie weitere Ideen f&uuml;r Erweiterungen Lassen Sie uns unter <b>info@access-im-unternehmen.de <\/b>wissen, welche W&uuml;nsche Sie noch haben.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>KA_BE.mdb<\/p>\n<p>KVA_2007.accdb<\/p>\n<p>KVA_2010.accdb<\/p>\n<p>Readme.txt<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{9D954302-5D1F-4D2B-A516-32E6CDF0DFD1}\/aiu_857.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Beitrag Kunden, Vertr&auml;ge und Anschreiben verwalten lernen Sie eine komplette Anwendung kennen. Der vorliegende Beitrag beschreibt die Technik, die sich hinter dieser Anwendung verbirgt &#8211; angefangen mit dem Datenmodell &uuml;ber die Abfragen, Formulare und Berichte bis hin zu den verwendeten VBA-Prozeduren. Spezielle Themen werden in weiteren Beitr&auml;gen vertieft, auf die wir an geeigneter Stelle verweisen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662012,66052012,44000025],"tags":[],"class_list":["post-55000857","post","type-post","status-publish","format-standard","hentry","category-662012","category-66052012","category-VBA_und_Programmiertechniken"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Programmierung der KVA - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Programmierung der KVA\" \/>\n<meta property=\"og:description\" content=\"Im Beitrag Kunden, Vertr&auml;ge und Anschreiben verwalten lernen Sie eine komplette Anwendung kennen. Der vorliegende Beitrag beschreibt die Technik, die sich hinter dieser Anwendung verbirgt - angefangen mit dem Datenmodell &uuml;ber die Abfragen, Formulare und Berichte bis hin zu den verwendeten VBA-Prozeduren. Spezielle Themen werden in weiteren Beitr&auml;gen vertieft, auf die wir an geeigneter Stelle verweisen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T21:48:54+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg05.met.vgwort.de\/na\/3d578ac87dc8432cac84f9efba2f7df5\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"38\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Programmierung der KVA\",\"datePublished\":\"2020-05-22T21:48:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/\"},\"wordCount\":6379,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/3d578ac87dc8432cac84f9efba2f7df5\",\"articleSection\":[\"2012\",\"5\\\/2012\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/\",\"name\":\"Programmierung der KVA - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/3d578ac87dc8432cac84f9efba2f7df5\",\"datePublished\":\"2020-05-22T21:48:54+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/3d578ac87dc8432cac84f9efba2f7df5\",\"contentUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/3d578ac87dc8432cac84f9efba2f7df5\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Programmierung_der_KVA\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Programmierung der KVA\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Programmierung der KVA - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/","og_locale":"de_DE","og_type":"article","og_title":"Programmierung der KVA","og_description":"Im Beitrag Kunden, Vertr&auml;ge und Anschreiben verwalten lernen Sie eine komplette Anwendung kennen. Der vorliegende Beitrag beschreibt die Technik, die sich hinter dieser Anwendung verbirgt - angefangen mit dem Datenmodell &uuml;ber die Abfragen, Formulare und Berichte bis hin zu den verwendeten VBA-Prozeduren. Spezielle Themen werden in weiteren Beitr&auml;gen vertieft, auf die wir an geeigneter Stelle verweisen.","og_url":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T21:48:54+00:00","og_image":[{"url":"http:\/\/vg05.met.vgwort.de\/na\/3d578ac87dc8432cac84f9efba2f7df5","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"38\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Programmierung der KVA","datePublished":"2020-05-22T21:48:54+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/"},"wordCount":6379,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/3d578ac87dc8432cac84f9efba2f7df5","articleSection":["2012","5\/2012","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/","url":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/","name":"Programmierung der KVA - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/3d578ac87dc8432cac84f9efba2f7df5","datePublished":"2020-05-22T21:48:54+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#primaryimage","url":"http:\/\/vg05.met.vgwort.de\/na\/3d578ac87dc8432cac84f9efba2f7df5","contentUrl":"http:\/\/vg05.met.vgwort.de\/na\/3d578ac87dc8432cac84f9efba2f7df5"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Programmierung_der_KVA\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Programmierung der KVA"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000857","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55000857"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000857\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000857"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000857"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000857"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}