{"id":55001016,"date":"2015-12-01T00:00:00","date_gmt":"2020-05-22T19:09:22","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1016"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Projektzeiterfassung_mit_Outlook_und_Access","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/","title":{"rendered":"Projektzeiterfassung mit Outlook und Access"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg09.met.vgwort.de\/na\/2e6ebc37f1dd4a84bd673898d73bbea5\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Die Erfassung von Projektzeiten ist eine Aufgabe, die man gern etwas stiefm&uuml;tterlich handhabt. Am Ende des Tages, der Woche oder auch des Monats muss man dann die f&uuml;r verschiedene Aufgaben verbrauchte Zeit aus dem Ged&auml;chtnis nachtragen. Dem wollen wir mit einer L&ouml;sung, die Outlook und Access nutzt, entgegenwirken. Damit legen Sie eine T&auml;tigkeit einer bestimmten Dauer &#8211; in diesem Fall 25 Minuten &#8211; ganz einfach per Drag and Drop in den Outlook-Kalender an. Der Rest geschieht im Hintergrund: Die T&auml;tigkeit wird samt Projekt und Aufgabe in einer Access-Datenbank gespeichert und kann anschlie&szlig;end bequem ausgewertet werden.<\/b><\/p>\n<p>Der Clou bei dieser L&ouml;sung ist, dass es wirklich nur weniger Vorbereitungen sowie einer Drag-and-Drop-Aktion bedarf, um schnell eine T&auml;tigkeit zu dokumentieren. Die grundlegende Konfiguration erfordert Outlook und Access ab der Version 2007.<\/p>\n<p>Wenn Sie Outlook &ouml;ffnen, stellen Sie zun&auml;chst die Ansicht der linken Leiste auf <b>Ordner<\/b> um (s. Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_001.png\" alt=\"Wechsel auf die Ordner-Ansicht\" width=\"350\" height=\"400,4651\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Wechsel auf die Ordner-Ansicht<\/span><\/b><\/p>\n<p>Danach erscheint links eine &uuml;bersicht der einzelnen Outlook-Elemente als Ordner &#8211; <b>Posteingang<\/b>, <b>Entw&uuml;rfe<\/b>, <b>Gesendete Elemente <\/b>und so weiter. F&uuml;r uns ist der Ordner <b>Aufgaben <\/b>interessant.<\/p>\n<p>Dort legt die L&ouml;sung aus diesem Beitrag beim Starten von Outlook automatisch einen Unterordner namens <b>Projekte <\/b>an. Mit dem Eintrag <b>Neuer Ordner&#8230; <\/b>des Kontextmen&uuml;s dieses Eintrags legen Sie einen Unterordner an, der ein neues Projekt repr&auml;sentiert (s. Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_002.png\" alt=\"Anlegen eines neuen Projekt-Ordners\" width=\"350\" height=\"370,6751\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Anlegen eines neuen Projekt-Ordners<\/span><\/b><\/p>\n<p>Zu Beispielzwecken wollen wir diesen Ordner <b>Projekt 1 <\/b>nennen.<\/p>\n<p>Ein Projekt soll eine oder mehrere Aufgaben aufnehmen. Damit Sie diese anlegen k&ouml;nnen, klicken Sie den frisch angelegten Ordner <b>Projekt 1 <\/b>an. Dies blendet die aktuell f&uuml;r diesen Aufgabenordner vorhandenen Aufgaben im Hauptbereich von Outlook ein. Hier f&uuml;gen Sie nun wie in Bild 3 die gew&uuml;nschten Aufgaben hinzu &#8211; im <b>Beispiel Aufgabe 1 <\/b>und <b>Aufgabe 2<\/b>.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_003.png\" alt=\"Hinzuf&uuml;gen von Aufgaben zu einem Projekt\" width=\"700\" height=\"297,0803\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Hinzuf&uuml;gen von Aufgaben zu einem Projekt<\/span><\/b><\/p>\n<p>Nun k&ouml;nnen wir schon zur Kalenderansicht wechseln. Dabei m&uuml;ssen Sie allerdings etwas beachten: Wenn Sie per Mausklick auf das Kalender-Icon unten links zum Kalender wechseln, verschwindet auch die Ordneransicht wieder &#8211; und die sollte angezeigt bleiben, damit wir auch w&auml;hrend der Arbeit mit dem Kalender Zugriff auf die Projektordner haben. Also nutzen Sie f&uuml;r den Wechsel zur Kalenderansicht den Eintrag <b>Kalender <\/b>aus der Ordnerliste.<\/p>\n<p>Hier pr&uuml;fen wir noch, ob der rechte Bereich die Aufgabenliste anzeigt. Ist dies nicht der Fall, k&ouml;nnen Sie dies etwa unter Outlook 2016 mit dem Ribbon-Eintrag <b>An-sicht|Lay-out|Aufgabenliste|Aufgaben <\/b>einblenden (s. Bild 4). Hier sehen Sie auch, wie Sie dann eine der Aufgaben aus der Aufgabenliste in den Kalenderbereich ziehen. Die Aufgabe wird dann als neue T&auml;tigkeit genau an der Stelle angelegt, die dem aktuellen Datum und der Uhrzeit entspricht. Fertig &#8211; f&uuml;r die n&auml;chsten 25 Minuten steht die anstehende Aufgabe nun fest und Sie k&ouml;nnen diese bearbeiten. Danach geht es auf die gleiche Weise weiter &#8211; legen Sie eine neue Aufgabe an und bearbeiten Sie diese oder bearbeiten Sie einfach eine der vorhandenen Aufgaben weiter.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_004.png\" alt=\"Einblenden der Aufgabenleiste und Hinzuf&uuml;gen von Aufgaben als T&auml;tigkeiten zum Kalender\" width=\"700\" height=\"387,6543\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Einblenden der Aufgabenleiste und Hinzuf&uuml;gen von Aufgaben als T&auml;tigkeiten zum Kalender<\/span><\/b><\/p>\n<h2>Datenbank zum Speichern der Projektzeitdaten<\/h2>\n<p>Dies war der Teil der L&ouml;sung, der sich auf die Benutzeroberfl&auml;che bezieht. Im Hintergrund geschieht noch einiges mehr: Zum Beispiel gibt es eine Access-Datenbank namens <b>Projektzeiterfassung.accdb<\/b>, welche die erfassten Daten in drei Tabelle speichert und die um Funktionen zum Auswerten der Projektzeiten erweitert werden kann.<\/p>\n<h2>Datenmodell der Datenbank<\/h2>\n<p>Das Datenmodell dieser Datenbank sieht wie in Bild 5 aus. Die Tabelle <b>tblProjekte <\/b>nimmt f&uuml;r jeden Ordner, den Sie unterhalb des Ordners Projekte anlegen, einen Datensatz auf und speichert dort die eingegebene Projektbezeichnung. Die &uuml;brigen Felder k&ouml;nnen nach Belieben genutzt werden, interessant ist lediglich noch das Feld <b>GeloeschtAm<\/b>. Dieses wird gef&uuml;llt, wenn der Benutzer den Projektordner in Outlook l&ouml;scht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_005.png\" alt=\"Datenmodell der Datenbank zur Projektzeiterfassung\" width=\"500\" height=\"237,2014\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Datenmodell der Datenbank zur Projektzeiterfassung<\/span><\/b><\/p>\n<p>Die Tabelle <b>tblAufgaben <\/b>speichert die einzelnen Aufgaben, die Sie im mittleren Bereich von Outlook hinzuf&uuml;gen, wenn Sie einen der Projektordner markiert haben. Hier finden Sie das Fremdschl&uuml;sselfeld <b>ProjektID<\/b>, das die Aufgabe einem Datensatz der Tabelle <b>tblProjekte <\/b>zuordnet. Das Feld <b>Aufgabe <\/b>ist f&uuml;r die Bezeichnung der Aufgabe wie in Outlook angegeben gedacht. Auch hier finden Sie wieder ein Feld namens <b>Geloescht-Am<\/b>, das beim L&ouml;schen des entsprechenden Elements aus Outlook mit dem aktuellen Datum und der Zeit gef&uuml;llt wird. Das Feld <b>ErledigtAm <\/b>schlie&szlig;lich wird gef&uuml;llt, wenn der Benutzer die Aufgabe in Outlook als erledigt markiert. Dies k&ouml;nnen Sie beispielsweise in der &uuml;bersichtsliste der Aufgaben erledigen (s. Bild 6). Eine andere M&ouml;glichkeit bietet der Eintrag <b>Als erledigt markieren <\/b>im Kontextmen&uuml; der Aufgabenliste in der Kalenderansicht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_006.png\" alt=\"Markieren einer Aufgabe als \"Erledigt\"\" width=\"500\" height=\"321,608\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Markieren einer Aufgabe als &#8222;Erledigt&#8220;<\/span><\/b><\/p>\n<p>Die Tabelle <b>tblTaetigkeiten <\/b>speichert schlie&szlig;lich die Aufgaben, die der Benutzer als Termine in den Kalender gezogen hat. Die Tabelle enth&auml;lt einige Felder mehr als die zuvor vorgestellten Tabellen. Beim Anlegen einer T&auml;tigkeit tr&auml;gt die L&ouml;sung die Bezeichnung der T&auml;tigkeit, die Startzeit, die Endzeit sowie den Wert des Prim&auml;rschl&uuml;sselfeldes der Aufgabe, zu deren Erledigung die T&auml;tigkeit dient, in die Tabelle ein. Au&szlig;erdem gibt es auch hier wieder ein Feld namens <b>GeloeschtAm<\/b>, welches das L&ouml;schdatum von entfernten T&auml;tigkeiten aufnimmt. Das Feld <b>KategorieID<\/b>, das Sie in der Abbildung des Datenmodells sehen, ben&ouml;tigen wir f&uuml;r eine Erweiterung der hier vorgestellten L&ouml;sung aus dem Beitrag <b>Kanban mit Outlook und Access <\/b>(<b>www.access-im-unternehmen.de\/1017<\/b>, siehe folgende Ausgabe).<\/p>\n<p>Bild 7 zeigt die drei Tabellen mit den Beispieldatens&auml;tzen, die wir weiter oben angelegt haben, in der Datenblattansicht und deutet die Verkn&uuml;pfungen der vorhandenen Datens&auml;tze durch rote Pfeile an.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_007.png\" alt=\"Tabellen der L&ouml;sung mit einigen Beispieldaten\" width=\"700\" height=\"284,4444\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Tabellen der L&ouml;sung mit einigen Beispieldaten<\/span><\/b><\/p>\n<h2>Programmierung der L&ouml;sung<\/h2>\n<p>Der Teil der L&ouml;sung, der in diesem Beitrag beschrieben wird, spielt sich VBA-technisch komplett in Outlook ab &#8211; die Access-Datenbank stellt nur die Tabellen zum Speichern der Projektzeiten bereit. In einem weiteren Beitrag namens <b>Projektzeiten auswerten <\/b>(<b>www.access-im-unternehmen.de\/1018<\/b>) zeigen wir in der folgenden Ausgabe, wie Sie die gespeicherten Daten auswerten k&ouml;nnen.<\/p>\n<p>Hier schauen wir uns nun an, wie die in Outlook erstellten Projekte, Aufgaben und T&auml;tigkeiten ihren Weg in die Tabellen der Access-Datenbank finden.<\/p>\n<h2>VBA-Editor unter Outlook &ouml;ffnen<\/h2>\n<p>Ich wei&szlig; nicht, wie es Ihnen geht, aber ich &ouml;ffne den VBA-Editor unter Access immer mit der Tastenkombination <b>Strg + G <\/b>und lande damit sofort im Direktbereich. Unter Outlook funktioniert diese nicht. Dort gelangen Sie am schnellsten &uuml;ber die Tastenkombination <b>Alt + F11 <\/b>in den VBA-Editor (dies funktioniert unter Access und den &uuml;brigen Office-Anwendungen &uuml;brigens auch).<\/p>\n<h2>Sicherheit<\/h2>\n<p>Je nachdem, wie Ihre Sicherheitseinstellungen unter Outlook aussehen, k&ouml;nnen Sie keine VBA-Prozeduren im VBA-Projekt von Outlook ausf&uuml;hren. Aber keine Sorge &#8211; dies &auml;ndern Sie ganz schnell. &ouml;ffnen Sie den Optionen-Dialog von Outlook, wechseln Sie dort zum Bereich <b>Trust Center <\/b>und klicken Sie auf <b>Einstellungen f&uuml;r das Trust Center<\/b>. Hier &uuml;bernehmen Sie die Option f&uuml;r den Bereich Makroeinstellungen wie in Bild 8.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_009.png\" alt=\"Einstellungen zum Ausf&uuml;hren von VBA-Code in Outlook\" width=\"650\" height=\"295,9497\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Einstellungen zum Ausf&uuml;hren von VBA-Code in Outlook<\/span><\/b><\/p>\n<p>Achtung: Die &auml;nderungen wirken sich erst beim n&auml;chsten Start von Outlook aus.<\/p>\n<h2>Wichtigstes Element: Ereignisse<\/h2>\n<p>Eine sehr wichtige Rolle spielen dabei die Ereignisse, die beim Anlegen von Projektordnern, Aufgaben und Terminen\/T&auml;tigkeiten ausgel&ouml;st werden. Weitere Ereignisse, die wir tracken m&uuml;ssen, sind das L&ouml;schen dieser drei Objektarten sowie das Verschieben, also das &auml;ndern der Eigenschaften von Objekte &#8211; in diesem Fall betrifft das nur die Termine\/T&auml;tigkeiten. Die T&auml;tigkeiten sollen ja, wenn der Benutzer diese auf den Kalender zieht, immer genau f&uuml;r das aktuelle Datum und die entsprechende Zeit angelegt werden. Manchmal vergisst man jedoch, eine T&auml;tigkeit vor Beginn in Outlook anzulegen und f&uuml;gt diese nachtr&auml;glich hinzu. Diese muss dann nat&uuml;rlich nach dem Anlegen noch an die der gew&uuml;nschten Zeit entsprechende Stelle verschoben werden, &uuml;blicherweise per Drag and Drop oder durch manuelles Einstellen der Zeit nach dem &ouml;ffnen des Termins per Doppelklick.<\/p>\n<p>Eine solche &auml;nderung muss ebenfalls ein Ereignis ausl&ouml;sen, damit die neuen Zeiten die beim Anlegen in der Tabelle gespeicherten Zeiten &uuml;berschreiben k&ouml;nnen. Aber auch die Projekt-ordner und die Aufgaben sind &auml;nderungen unterworfen. Diese beziehen sich jedoch nur auf die jeweilige Bezeichnung.<\/p>\n<p>Damit wir die Ereignisse der drei Objektarten durch entsprechende Ereignisprozeduren implementieren k&ouml;nnen, ben&ouml;tigen wir jeweils entsprechende Objektvariablen, die wir mit dem Schl&uuml;sselwort <b>WithEvents <\/b>deklarieren. Da nach dem &ouml;ffnen von Outlook nicht immer nur neue Projekte, Aufgaben und T&auml;tigkeiten angelegt, bearbeitet und gel&ouml;scht werden, sondern auch die bestehenden Elemente potenziell &auml;nderungen unterworfen sind, m&uuml;ssen wir f&uuml;r alle infrage kommenden Elemente Objektvariablen anlegen und diese mit den entsprechenden Ereignisprozeduren ausstatten.<\/p>\n<p>Wir ben&ouml;tigen also beim Start von Outlook zun&auml;chst eine Prozedur, die alle vorhandenen Elemente in Form von Objektvariablen referenziert. Diese Prozedur hei&szlig;t <b>Application_Startup <\/b>und landet im standardm&auml;&szlig;ig im VBA-Projekt von Outlook vorhandenen Klassenmodul <b>ThisOutlookSession<\/b> (s. Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Application_Startup()\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> Application_Startup_Err\r\n     <span style=\"color:blue;\">Dim <\/span>objProject<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">Dim <\/span>objTasks<span style=\"color:blue;\"> As <\/span>clsTasks\r\n     <span style=\"color:blue;\">Dim <\/span>lngError<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objAppointments = GetMAPINamespace.GetDefaultFolder(olFolderCalendar).Items\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objProject = GetTaskfolder.Folders(\"Projekte\")\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> Err.Number = 0<span style=\"color:blue;\"> Then<\/span>\r\n         GetTaskfolder.Folders.Add \"Projekte\", olFolderTasks\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objProjects = GetTaskfolder.Folders(\"Projekte\").Folders\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> Application_Startup_Err\r\n     <span style=\"color:blue;\">Set<\/span> objAppointmentFolder = GetMAPINamespace.GetDefaultFolder(olFolderCalendar)\r\n     <span style=\"color:blue;\">Set<\/span> colProjects = <span style=\"color:blue;\">New<\/span> Collection\r\n     For Each objProject In objProjects\r\n         <span style=\"color:blue;\">Set<\/span> objTasks = <span style=\"color:blue;\">New<\/span> clsTasks\r\n         <span style=\"color:blue;\">Set<\/span> objTasks.Tasks = objProject.Items\r\n         <span style=\"color:blue;\">Set<\/span> objTasks.Project = objProject\r\n         colProjects.Add objTasks\r\n     <span style=\"color:blue;\">Next<\/span>\r\nApplication_Startup_Exit:\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Exit Sub<\/span>\r\nApplication_Startup_Err:\r\n     <span style=\"color:blue;\">Call<\/span> Fehlerbehandlung(\"Projekt1\/ThisOutlookSession\", \"Application_Startup\", _\r\n         Erl, \"Bemerkungen: .\/.\")\r\n     GoTo Application_Startup_Exit\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Diese Prozedur wird bei Start von Outlook automatisch ausgel&ouml;st.<\/span><\/b><\/p>\n<h2>VBA-Projekt von Outlook<\/h2>\n<p>Bez&uuml;glich des VBA-Projekts von Outlook m&uuml;ssen Sie ein wenig von der Access-Denkweise abweichen: Unter Access hat ja jede Datenbankdatei ein eigenes VBA-Projekt &#8211; genau wie die Dokumente in Word oder Excel. Unter Outlook gibt es nur ein VBA-Projekt, das der Anwendung Outlook selbst zugeteilt ist.<\/p>\n<h2>Fehlerbehandlung<\/h2>\n<p>Die Prozedur enth&auml;lt eine Fehlerbehandlung, die alle Fehler in Form einer entsprechenden Meldung behandelt. Dies dient prim&auml;r dazu, die L&ouml;sung stabil zu gestalten. &uuml;blicherweise werden beispielsweise Objektvariablen bei nicht behandelten Fehlern geleert, was im Falle dieser L&ouml;sung nat&uuml;rlich katastrophal w&auml;re: Wenn der Benutzer nach einem nicht behandelten Fehler flei&szlig;ig weiter Projekte, Aufgaben und T&auml;tigkeiten bearbeitet, wird n&auml;mlich keines der mit den Objektvariablen verbundenen Ereignisse mehr ausgel&ouml;st und die Daten werden nicht in der Datenbank gespeichert.<\/p>\n<p>Die Prozedur <b>Application_Startup <\/b>stellt nun zun&auml;chst die Variable <b>objAppointments <\/b>des Typs <b>Items <\/b>auf die im Kalender-Ordner enthaltenen Elemente ein. Die entsprechende Variable deklarieren wir wie folgt im Kopf des Klassenmoduls:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>WithEvents objAppointments<span style=\"color:blue;\"> As <\/span>Outlook.Items<\/pre>\n<p>Um einen leichteren Zugriff auf die Elemente von Outlook zu schaffen, haben wir im Modul <b>mdlOutlook <\/b>ein paar Hilfsfunktionen beigef&uuml;gt. Hier kommen gleich mehrere zum Einsatz. Die erste hei&szlig;t <b>GetMAPINamespace <\/b>und liefert einen Verweis auf das MAPI-Namespace-Objekt von Outlook, &uuml;ber das wir auf alle Elemente von Outlook zugreifen k&ouml;nnen (siehe unten). Das von <b>GetMAPINamespace <\/b>gelieferte Objekt bietet die Methode <b>GetDefaultFolder<\/b>, die mit dem Parameter <b>olFolderCalendar <\/b>einen Verweis auf den Standard-Kalenderordner von Outlook holt und speichert ihn in <b>objAppointments<\/b>.<\/p>\n<p>Nun folgt ein Schritt, der dem Benutzer ein wenig Arbeit abnehmen soll: Wenn unterhalb des Aufgaben-Ordners in der Ordnerliste von Outlook noch kein Eintrag namens <b>Projekte <\/b>vorhanden ist, soll die Prozedur diesen automatisch anlegen. Dazu referenziert die Prozedur bei deaktivierter Fehlerbehandlung diesen Ordner &uuml;ber das Element <b>Projekte <\/b>der <b>Folders<\/b>-Auflistung f&uuml;r den Aufgaben-Ordner.<\/p>\n<p>Den Aufgaben-Ordner liefert ebenfalls eine unserer Hilfsfunktionen aus dem Modul <b>mdlOutlook<\/b>, n&auml;mlich <b>GetTaskfolder<\/b> (siehe unten). F&uuml;hrt dieser Zugriff auf den Ordner zu einem Fehler, ist offensichtlich, dass der Ordner noch nicht vorhanden ist. Die Prozedur verwendet dann die <b>Add<\/b>-Methode der <b>Folders<\/b>-Auflistung des mit <b>GetTaskfolder <\/b>ermittelten Aufgaben-Ordners, um den Ordner namens <b>Projekte <\/b>hinzuzuf&uuml;gen. Danach speichert sie einen Verweis auf die <b>Folders<\/b>-Auflistung dieses Ordners in der Variablen <b>objProjects<\/b>, die ebenfalls mit dem Schl&uuml;sselwort <b>WithEvents <\/b>im Kopf des Klassenmoduls deklariert wird:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>WithEvents objProjects<span style=\"color:blue;\"> As <\/span>Outlook.Folders<\/pre>\n<p>Die n&auml;chste auf diese Variable namens <b>objAppointmentFolder <\/b>f&uuml;llt die Prozedur mit einem Verweis auf den Kalender-Ordner:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>WithEvents objAppointmentFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder<\/pre>\n<p>Auch diesen erhalten wir mit der <b>GetDefaultFolder<\/b>-Methode des mit <b>Get-MAPI-Namespace <\/b>ermittelten MAPI-Namespace-Objekts.<\/p>\n<p>F&uuml;r die Implementierung weiterer Ereignisse ben&ouml;tigen wir auch noch Objekte auf Basis der Ordner, die der Benutzer unterhalb des <b>Projekte<\/b>-Ordners anlegt und die jeweils ein Projekt repr&auml;sentieren. Dies ist etwas aufwendiger, da wir jeden einzelnen Ordner referenzieren m&uuml;ssen. Dies erledigen wir mit einer Hilfsklasse, die jeweils einen Ordner aufnimmt und die dann in einer Collection namens <b>colProjects <\/b>landet. Diese deklarieren wir wie folgt im Kopf des Klassenmoduls:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>colProjects<span style=\"color:blue;\"> As <\/span>Collection<\/pre>\n<p>Die Prozedur erzeugt diese Collection neu. Dann durchl&auml;uft sie alle Ordner im Folder <b>Projekte <\/b>in einer <b>For Each<\/b>-Schleife &uuml;ber die Elemente der Auflistung <b>objProjects <\/b>und legt f&uuml;r jeden Ordner ein neues Objekt der Klasse <b>clsTasks <\/b>an. Diese weist eine Eigenschaft namens <b>Tasks <\/b>auf, die mit der <b>Items<\/b>-Auflistung des aktuellen Projekte-Ordners gef&uuml;llt wird. Der Verweis auf den aktuellen Projekt-Ordner selbst landet in der Eigenschaft <b>Project<\/b>. Schlie&szlig;lich wird das so pr&auml;parierte Objekt der Collection <b>colProjects <\/b>hinzugef&uuml;gt.<\/p>\n<p>Das waren bereits die Vorbereitungen. Nun m&uuml;ssen wir noch die zahlreichen Ereignisprozeduren implementieren, damit die in Outlook eingegebenen Projekte, Aufgaben und T&auml;tigkeiten auch in den Tabellen der Datenbank landen.<\/p>\n<h2>Die Hilfsfunktionen GetOutlook, GetMAPINamespace und GetTaskFolder<\/h2>\n<p>Die drei Hilfsfunktionen aus Listing 2 finden Sie im Standardmodul <b>mdlOutlook <\/b>im VBA-Projekt von Outlook &#8211; dort nat&uuml;rlich mit Fehlerbehandlung, die wir hier aus Platzgr&uuml;nden gek&uuml;rzt haben. Die erste Funktion liefert einen Verweis auf das <b>Outlook.Application<\/b>-Objekt. Dabei pr&uuml;ft sie, ob die lokale Variable <b>mOutlook <\/b>bereits mit einem Verweis auf das <b>Application<\/b>-Objekt gef&uuml;llt ist. Falls nicht, was eigentlich nur beim ersten Aufruf geschieht, f&uuml;llt es diese Variable damit. Die Funktion gibt dann einen Verweis auf den Inhalt von <b>mOutlook <\/b>zur&uuml;ck.<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>mOutlook<span style=\"color:blue;\"> As <\/span>Outlook.Application\r\n<span style=\"color:blue;\">Dim <\/span>mNamespace<span style=\"color:blue;\"> As <\/span>Outlook.NameSpace\r\n<span style=\"color:blue;\">Dim <\/span>mTaskFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n<span style=\"color:blue;\">Public Property Get <\/span>GetOutlook()<span style=\"color:blue;\"> As <\/span>Outlook.Application\r\n     <span style=\"color:blue;\">If <\/span>mOutlook Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> mOutlook = Application\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> GetOutlook = mOutlook\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>GetMAPINamespace()<span style=\"color:blue;\"> As <\/span>Outlook.NameSpace\r\n     <span style=\"color:blue;\">If <\/span>mNamespace Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> mNamespace = GetOutlook.GetNamespace(\"MAPI\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> GetMAPINamespace = mNamespace\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>GetTaskfolder()<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">If <\/span>mTaskFolder Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> mTaskFolder = GetMAPINamespace.GetDefaultFolder(olFolderTasks)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> GetTaskfolder = mTaskFolder\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Hilfsfunktionen f&uuml;r den einfachen Zugriff auf Outlook-Objekte<\/span><\/b><\/p>\n<p>Die Funktion <b>GetMAPINamespace <\/b>erledigt dies mit der Variablen <b>mNamespace <\/b>und nutzt dazu die <b>GetNamespace<\/b>-Methode des <b>Application<\/b>-Objekts, das es mit der Funktion <b>GetOutlook <\/b>holt.<\/p>\n<p>Fehlt noch die Funktion <b>GetTaskfolder<\/b>, die einen Verweis auf den Aufgaben-Ordner von Outlook ermittelt und zur&uuml;ckgibt. Dabei nutzt diese die beiden zuvor beschriebenen Funktionen sowie die lokale Variable <b>mTaskfolder<\/b>.<\/p>\n<h2>Die Klasse clsTasks<\/h2>\n<p>Diese Klasse haben Sie soeben bereits kennen gelernt, als wir f&uuml;r jedes <b>Folder<\/b>-Objekt eine Instanz dieser Klasse erstellt und &uuml;ber die Eigenschaften <b>Tasks <\/b>und <b>Project <\/b>jeweils einen Verweis auf die Aufgaben-Auflistung und den Projekt-Ordner &uuml;bergeben haben.<\/p>\n<p>Diese beiden Eigenschaften stellt die Klasse &uuml;ber die beiden <b>Property Set<\/b>-Prozeduren <b>Tasks <\/b>und <b>Project <\/b>bereit, die wie in Listing 3 aussehen.<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>WithEvents mTasks<span style=\"color:blue;\"> As <\/span>Outlook.Items\r\n<span style=\"color:blue;\">Private <\/span>WithEvents mProject<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n<span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Tasks(objTasks<span style=\"color:blue;\"> As <\/span>Outlook.Items)\r\n     <span style=\"color:blue;\">Set<\/span> mTasks = objTasks\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Project(objProject<span style=\"color:blue;\"> As <\/span>Outlook.Folder)\r\n     <span style=\"color:blue;\">Set<\/span> mProject = objProject\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Elemente der Klasse clsTasks<\/span><\/b><\/p>\n<p>Damit die &uuml;bergebenen Verweise in der Klasse gespeichert werden, tragen die <b>Property Set<\/b>-Prozeduren diese in die beiden Variablen <b>mTasks <\/b>und <b>mProject <\/b>ein. Beide deklarieren wir wieder mit dem Schl&uuml;sselwort <b>With-Events<\/b>, denn auch f&uuml;r diese wollen wir wieder Ereignisprozeduren anlegen. Diese stellen wir in den folgenden Abschnitten vor.<\/p>\n<h2>Auf Outlook-Aktionen reagieren und Daten in Access speichern<\/h2>\n<p>Damit h&auml;tten wir das Grundger&uuml;st erstellt. Nun folgt eine Reihe von Ereignisprozeduren, mit denen wir die Benutzer-eingaben in Outlook abfangen und die dabei anfallenden Daten in der Access-Datenbank speichern. Diese schauen wir uns in der Reihenfolge an, wie sie beim Arbeiten mit der L&ouml;sung auftreten.<\/p>\n<h2>Verweis auf die DAO-Bibliothek<\/h2>\n<p>Sp&auml;testens jetzt, wo es an das Speichern von Daten in die Tabellen der Access-Datenbank geht, ben&ouml;tigen wir f&uuml;r das VBA-Projekt von Outlook einen Verweis auf die DAO-Bibliothek beziehungsweise auf die modernere Variante, die <b>Microsoft Office x.0 Access database engine Object Library<\/b>. Diesen f&uuml;gen Sie wie in Bild 9 hinzu (VBA-Editor, Men&uuml;eintrag <b>Extras|Verweise<\/b>).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_008.png\" alt=\"Verweis auf die DAO-Bibliothek\" width=\"425\" height=\"331,4465\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Verweis auf die DAO-Bibliothek<\/span><\/b><\/p>\n<h2>Projekt hinzuf&uuml;gen<\/h2>\n<p>Die erste Ereignisprozedur wird ausgel&ouml;st, wenn der Benutzer einen neuen Unterordner zum Aufgaben-Ordner hinzuf&uuml;gt &#8211; &uuml;blicherweise &uuml;ber den entsprechenden Kontextmen&uuml;-Eintrag. Dies l&ouml;st das Ereignis <b>FolderAdd <\/b>des Objekts <b>objProjects <\/b>auf, das im Klassenmodul <b>ThisOutlookSession <\/b>deklariert ist. Dort legen Sie auch die Ereignisprozedur aus Listing 4 an.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objProjects_FolderAdd(ByVal Folder<span style=\"color:blue;\"> As <\/span>MAPIFolder)\r\n     ... ''''Fehlerbehandlung nicht abgebildet\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objTasks<span style=\"color:blue;\"> As <\/span>clsTasks\r\n     Select Case Folder.DefaultItemType\r\n         <span style=\"color:blue;\">Case <\/span>olTaskItem\r\n             strSQL = \"INSERT INTO tblProjekte(Projektbezeichnung) VALUES(''''\" & Folder.Name & \"'''')\"\r\n             CurrentDBC.Execute strSQL, dbFailOnError\r\n             <span style=\"color:blue;\">If <\/span>CurrentDBC.RecordsAffected = 1<span style=\"color:blue;\"> Then<\/span>\r\n                 Folder.Description = \"[project|\" & CurrentDBC.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0).Value & \"]\"\r\n             <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objTasks = <span style=\"color:blue;\">New<\/span> clsTasks\r\n     <span style=\"color:blue;\">Set<\/span> objTasks.Tasks = Folder.Items\r\n     <span style=\"color:blue;\">Set<\/span> objTasks.Project = Folder\r\n     colProjects.Add objTasks\r\n     ... ''''Fehlerbehandlung nicht abgebildet\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Ereignisprozedur, die beim Hinzuf&uuml;gen eines Projekt-Ordners ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Eine solche Ereignisprozedur erstellen Sie, indem Sie aus dem linken Kombinationsfeld des Codefensters den Namen des Objekts ausw&auml;hlen (hier <b>objProjects<\/b>) und aus dem rechten den Eintrag f&uuml;r die gew&uuml;nschte Ereignisprozedur (in diesem Fall <b>FolderAdd<\/b>). Dies legt dann die nackte Prozedur an. Dem Prozedurkopf k&ouml;nnen wir dann schon entnehmen, dass die Prozedur als Parameter einen Verweis auf den neu angelegten Ordner liefert (<b>Folder<\/b>). Die Prozedur pr&uuml;ft zun&auml;chst den Typ des neu angelegten Ordners. Dazu vergleicht sie in einer <b>Select Case<\/b>-Bedingung den Wert von <b>Folder.DefaultItemType <\/b>mit dem Wert der Konstanten <b>olTaskItem<\/b>. Ist diese Bedingung erf&uuml;llt, f&uuml;hrt die Prozedur die nachfolgenden Anweisungen aus. Die erste stellt eine SQL-Anweisung zusammen, welche einen neuen Datensatz in der Tabelle <b>tblProjekte <\/b>anlegt und dem Feld <b>Projektbezeichnung <\/b>den beim Anlegen angegebenen Ordnernamen zuweist. Diese f&uuml;hrt die Prozedur mit der nachfolgenden <b>Execute<\/b>-Methode eines Objekts namens <b>CurrentDBC <\/b>aus. <b>CurrentDBC <\/b>ist eine Funktion, die einen Verweis auf die Access-Datenbank <b>Projektzeiterfassung.accdb <\/b>enth&auml;lt. Die Funktion befindet sich im Modul <b>mdlGlobal<\/b> und sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Property Get <\/span>CurrentDBC()<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">If <\/span>mCurrentDB Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> mCurrentDB = DBEngine.OpenDatabase(cStrDB, <span style=\"color:blue;\">False<\/span>)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> CurrentDBC = mCurrentDB\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Wie bereits bei den Outlook-Hilfsfunktionen verwendet auch diese eine privat deklarierte Variable:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>mCurrentDB<span style=\"color:blue;\"> As <\/span>DAO.Database<\/pre>\n<p>Diese wird beim ersten Aufruf der Funktion mit einem Verweis auf die mit der <b>OpenDatabase<\/b>-Methode ge&ouml;ffnete Datenbank gef&uuml;llt und dann bei Bedarf von der Funktion zur&uuml;ckgegeben. Den Pfad der Datenbank speichern wir &uuml;brigens in der Konstanten <b>sStrDB<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Const cStrDB<span style=\"color:blue;\"> As String<\/span> = \"C:\\Projektzeiterfassung\\Projektzeiterfassung.accdb\"<\/pre>\n<p>Wenn Sie die L&ouml;sung selbst einsetzen wollen, m&uuml;ssen Sie also entweder die Datenbank an dem hier angegebenen Ort speichern oder aber den Pfad in der Konstanten <b>cStrDB <\/b>anpassen.<\/p>\n<p>Weiter in der Prozedur: Diese pr&uuml;ft mit der <b>RecordsAffected<\/b>-Eigenschaft, wie viele Datens&auml;tze von dieser Aktionsabfrage betroffen sind. Ist es genau einer, war die Aktion erfolgreich. In diesem Fall folgt nun ein sehr wichtiger Schritt: Wir weisen der Eigenschaft <b>Description <\/b>einen Ausdruck zu, der aus der Zeichenkette <b>[project|xxx] <\/b>besteht, wobei der Platzhalter <b>xxx <\/b>dem Prim&auml;rschl&uuml;sselwert des soeben angelegten Datensatzes entspricht. Den gew&uuml;nschten Prim&auml;rschl&uuml;sselwert k&ouml;nnen wir leicht ermitteln, da wir als Prim&auml;rschl&uuml;ssel einen Autowert verwenden. Die Abfrage <b>SELECT @@IDENTITY <\/b>liefert genau diesen Wert.<\/p>\n<p>Wof&uuml;r wir diesen Wert ben&ouml;tigen Weil wir ja gleich Aufgaben f&uuml;r dieses Projekt anlegen m&ouml;chten. Dann m&uuml;ssen wir ja beim Anlegen des neuen Datensatzes in der Tabelle <b>tblAufgaben <\/b>den Prim&auml;rschl&uuml;sselwert des &uuml;bergeordneten Datensatzes aus der Tabelle <b>tblProjekte <\/b>angeben, damit die Zuordnung in der Datenbank stimmt. Au&szlig;erdem kann es ja vorkommen, dass wir ein Projekt wieder aus Outlook l&ouml;schen wollen. Dann ben&ouml;tigen wir den Prim&auml;rschl&uuml;sselwert, um den entsprechenden Datensatz der Tabelle <b>tblProjekte <\/b>als gel&ouml;scht zu markieren. Den Ausdruck <b>[project|xxx] <\/b>k&ouml;nnen Sie auch im Eigenschaftsfenster des Ordners einsehen, das Sie mit dem Kontextmen&uuml;-Eintrag <b>Eigenschaften&#8230; <\/b>&ouml;ffnen (s. Bild 10).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_010.png\" alt=\"Versteckte Referenz auf den Datensatz der Tabelle tblProjekte\" width=\"425\" height=\"421,5235\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Versteckte Referenz auf den Datensatz der Tabelle tblProjekte<\/span><\/b><\/p>\n<p>F&uuml;r den neuen Ordner m&uuml;ssen wir nat&uuml;rlich auch noch ein Objekt der Klasse <b>clsTasks <\/b>anlegen &#8211; Sie erinnern sich, dass wir das in der Prozedur <b>Application_Startup <\/b>bereits f&uuml;r alle bereits vorhandenen Ordner erledigt haben. Dazu legt die Prozedur das neue Objekt an, f&uuml;llt die Eigenschaften <b>Tasks <\/b>und <b>Project <\/b>wie bereits weiter oben beschrieben und f&uuml;gt die Objektvariable <b>objTasks <\/b>zur Collection <b>colProjects <\/b>hinzu. So funktionieren dann auch die weiter unten beschriebenen Ereignisprozeduren f&uuml;r das neu angelegte <b>Folder<\/b>-Objekt.<\/p>\n<h2>Ereignisprozedur beim Umbenennen eines Projekt-Ordners<\/h2>\n<p>F&uuml;r das Objekt <b>objProjects <\/b>legen wir gleich noch eine weitere Ereignisprozedur an, und zwar f&uuml;r das Ereignis <b>FolderChange<\/b>. Dieses wird bei einer &auml;nderung der Eigenschaften des Ordners ausgel&ouml;st und sieht wie in Listing 5 aus. Die Prozedur pr&uuml;ft wieder, ob es sich tats&auml;chlich um einen Ordner zum Speichern von Aufgaben handelt. Ist das der Fall, speichert die Prozedur die Beschreibung aus der Eigenschaft <b>Description <\/b>(also einen Ausdruck wie <b>[project|xxx]<\/b>) in der Variablen <b>strDescription <\/b>zwischen. Dann ermittelt sie mit der Hilfsfunktion <b>GetID <\/b>aus dem Inhalt von <b>strDescription <\/b>den Prim&auml;rschl&uuml;sselwert, unter dem der entsprechende Datensatz in der Tabelle <b>tblProjekte <\/b>angelegt wurde, und speichert ihn in <b>lngProjectID<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objProjects_FolderChange(ByVal Folder<span style=\"color:blue;\"> As <\/span>MAPIFolder)\r\n     <span style=\"color:blue;\">Dim <\/span>strDescription<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngProjectID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     Select Case Folder.DefaultItemType\r\n         <span style=\"color:blue;\">Case <\/span>olTaskItem\r\n             strDescription = Folder.Description\r\n             lngProjectID = GetID(strDescription, \"project\")\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngProjectID = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 strSQL = \"UPDATE tblProjekte SET Projektbezeichnung = ''''\" & Folder.Name & \"'''' WHERE ProjektID = \" & lngProjectID\r\n                 CurrentDBC.Execute strSQL, dbFailOnError\r\n             <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Ereignisprozedur, die beim &auml;ndern eines Projekt-Ordners ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Ist dieser Wert nicht <b>0<\/b>, stellt die Prozedur einen SQL-Ausdruck zusammen, der das Feld <b>Projektbezeichnung <\/b>des Datensatzes mit diesem Prim&auml;rschl&uuml;sselfeld auf den ge&auml;nderten Wert einstellt und f&uuml;hrt diese mit der <b>Execute<\/b>-Methode von <b>CurrentDBC <\/b>aus.<\/p>\n<p>Die Hilfsfunktion <b>GetID<\/b> ist in Listing 6 zu finden. Sie erwartet den zu verarbeitenden String sowie das Schl&uuml;sselwort f&uuml;r den Objekttyp (also etwa <b>project<\/b>, <b>task <\/b>oder <b>action<\/b>), der im String enthalten ist. Sie ermittelt die L&auml;nge des Schl&uuml;sselworts und speichert diese in der Variablen <b>intItemTypeLen<\/b>. Dann ermittelt sie die Startposition des Ausdrucks, also etwa von <b>[project|<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetID(str<span style=\"color:blue;\"> As String<\/span>, strItemType<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intPosStart<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intPosEnde<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intItemTypeLen<span style=\"color:blue;\"> As Integer<\/span>\r\n     intItemType<span style=\"color:blue;\">Len<\/span> = <span style=\"color:blue;\">Len<\/span>(strItemType)\r\n     intPosStart = <span style=\"color:blue;\">InStr<\/span>(1, str, \"[\" & strItemType & \"|\")\r\n     <span style=\"color:blue;\">If <\/span>intPosStart &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         intPosEnde = <span style=\"color:blue;\">InStr<\/span>(intPosStart, str, \"]\")\r\n         <span style=\"color:blue;\">If <\/span>intPosEnde &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n             lngID = <span style=\"color:blue;\">Mid<\/span>(str, intPosStart + 2 + intItemTypeLen, _\r\n                 intPosEnde - intPosStart - 2 - intItemTypeLen)\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     GetID = lngID\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Hilfsfunktion zum Ermitteln von Prim&auml;rschl&uuml;sselwerten<\/span><\/b><\/p>\n<p>Es kann ja auch vorkommen, dass die Eigenschaft nicht nur aus dem von uns hinzugef&uuml;gten Ausdruck besteht &#8211; beispielsweise, weil der Benutzer noch Text davor oder dahinter hinzugef&uuml;gt hat. Danach ermittelt die Prozedur die Position der schlie&szlig;enden eckigen Klammer und speichert diese in <b>intPosEnde<\/b>. Ist <b>intPosEnde <\/b>gr&ouml;&szlig;er als <b>0<\/b>, kann die Prozedur mithilfe einiger Zeichenkettenfunktionen den Wert des Prim&auml;rschl&uuml;sselfeldes aus dem Ausdruck herauslesen.<\/p>\n<h2>L&ouml;schen eines Projekte-Ordners<\/h2>\n<p>Das L&ouml;schen eines Projekte-Ordners k&ouml;nnen wir nicht mit einem Ereignis der zuvor verwendeten Objektvariablen <b>obj-Projects <\/b>abdecken. Hier ben&ouml;tigen wir das Objekt <b>mProject<\/b>, das sich in der Klasse <b>clsTasks <\/b>befindet. Deshalb legen Sie dort auch die Ereignisprozedur aus Listing 7 an. Das Ereignis hei&szlig;t <b>BeforeFolderMove<\/b>, was sich zun&auml;chst nicht nach L&ouml;schen anh&ouml;rt. Allerdings ist L&ouml;schen das Verschieben eines Objekts in den Ordner <b>Gel&ouml;schte Objekte<\/b>, wodurch dies doch wieder Sinn ergibt.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>mProject_BeforeFolderMove(ByVal MoveTo<span style=\"color:blue;\"> As <\/span>MAPIFolder, Cancel<span style=\"color:blue;\"> As Boolean<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngProjectID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolLoeschen<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objTaskItem<span style=\"color:blue;\"> As <\/span>TaskItem\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> mProject_BeforeFolderMove_Err\r\n     <span style=\"color:blue;\">If <\/span>MoveTo.Name = GetOutlook.Session.GetDefaultFolder(olFolderDeletedItems)<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>mProject.Items.Count = 0<span style=\"color:blue;\"> Then<\/span>\r\n             bolLoeschen = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">MsgBox<\/span>(\"Dies l&ouml;scht auch alle Aufgaben dieses Projekts. Fortsetzen\", vbYesNo) = vbYes<span style=\"color:blue;\"> Then<\/span>\r\n                 bolLoeschen = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>bolLoeschen<span style=\"color:blue;\"> Then<\/span>\r\n             For i = 1 To mProject.Items.Count\r\n                 <span style=\"color:blue;\">Set<\/span> objTaskItem = mProject.Items(i)\r\n                 objTaskItem.Delete\r\n             <span style=\"color:blue;\">Next<\/span> i\r\n             lngProjectID = GetID(mProject.Description, \"project\")\r\n             strSQL = \"UPDATE tblProjekte SET GeloeschtAm = \" & ISODatum(Now) & \" WHERE ProjektID = \" & lngProjectID\r\n             CurrentDBC.Execute strSQL, dbFailOnError\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             Cancel = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Projektordner k&ouml;nnen sich nur direkt unter dem Ordner ''''Projekte'''' befinden.\", vbOKOnly Or _\r\n             vbExclamation, \"Operation nicht m&ouml;glich\"\r\n         Cancel = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Ereignisprozedur, die beim L&ouml;schen eines Projekt-Ordners ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Die Prozedur liefert dann mit dem Parameter <b>MoveTo <\/b>auch einen Verweis auf den Zielordner. Den Parameter <b>Cancel <\/b>k&ouml;nnen Sie mit <b>True <\/b>f&uuml;llen, wenn das L&ouml;schen abgebrochen werden soll. Die Prozedur pr&uuml;ft, ob der Zielordner der Ordner <b>Gel&ouml;schte Objekte <\/b>ist. Da dieser von Version zu Version auch mal <b>Gel&ouml;schte Elemente <\/b>hei&szlig;t und in anderen Sprachen ganz anders, vergleichen wir nicht mit einem festen Ordnernamen, sondern ermitteln die Bezeichnung des Standard-Ordners f&uuml;r die gel&ouml;schten Objekte. Diese erhalten wir mit der <b>GetDefaultFolder<\/b>-Funktion mit dem Parameter <b>olFolderDeletedItems<\/b>.<\/p>\n<p>Nun wollen wir sicherstellen, dass wir keinen Ordner l&ouml;schen, der bereits Elemente enth&auml;lt &#8211; zumindest nicht ohne explizite Zustimmung des Benutzers. Dazu z&auml;hlen wir mit der <b>Count<\/b>-Methode der <b>Items<\/b>-Auflistung die untergeordneten Elemente. Sind keine vorhanden, stellen wir eine Variable namens <b>bolLoeschen <\/b>auf <b>True <\/b>ein. Falls Unterelemente vorhanden sind, soll der Benutzer per Meldungsfenster angeben, ob der Ordner dennoch gel&ouml;scht werden soll. Auch in diesem Fall erh&auml;lt die Variable <b>bolLoeschen <\/b>den Wer <b>True<\/b>. Diese pr&uuml;fen wir im folgenden Schritt. Hat sie den Wert <b>True<\/b>, l&ouml;schen wir zun&auml;chst die untergeordneten Elemente, und zwar in einer <b>For&#8230;Next<\/b>-Schleife &uuml;ber die Werte von <b>1 <\/b>bis zur Anzahl der Unterelemente.<\/p>\n<p>Darin weisen wir der Variablen <b>objTaskItem <\/b>das jeweilige Aufgaben-Element zu und l&ouml;schen dieses dann mit seiner <b>Delete<\/b>-Methode. Dann ermitteln wir den Prim&auml;rschl&uuml;sselwert des zu l&ouml;schenden Elements mit der weiter oben beschriebenen Funktion <b>GetID <\/b>und f&uuml;hren eine SQL-Abfrage aus, die das Projekt in der Tabelle <b>tblProjekte <\/b>als gel&ouml;scht markiert. Dazu stellt es den Wert des Feldes <b>GeloeschtAm <\/b>auf das aktuelle Datum und die aktuelle Zeit ein. Sollte der Benutzer etwa per Drag and Drop versucht haben, den Ordner an eine andere Stelle in der Ordnerhierarchie von Outlook zu ziehen, erscheint eine Meldung, die den Benutzer darauf hinweist, dass dies nicht m&ouml;glich ist.<\/p>\n<h2>Ereignisprozedur beim Hinzuf&uuml;gen oder Verschieben einer Aufgabe<\/h2>\n<p>Aufgaben kann man nicht nur &uuml;ber den Mittelbereich von Outlook zu einem Projekte-Ordner hinzuf&uuml;gen, sondern man kann auch eine bestehende Aufgabe von einem Ordner in einen anderen Projekte-Ordner verschieben. Wann auch immer ein Aufgaben-Objekt zu einem Ordner hinzugef&uuml;gt wird, l&ouml;st dies das Ereignis <b>ItemAdd <\/b>des Objekts aus <b>mTasks <\/b>aus (s. Listing 8).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>mTasks_ItemAdd(ByVal Item<span style=\"color:blue;\"> As Object<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>strAufgabe<span style=\"color:blue;\"> As String<\/span>, strFertigstellenBis<span style=\"color:blue;\"> As String<\/span>, strErledigtAm<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objTask<span style=\"color:blue;\"> As <\/span>Outlook.TaskItem\r\n     <span style=\"color:blue;\">Dim <\/span>objProjectfolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>, lngProjectID<span style=\"color:blue;\"> As Long<\/span>, strDescription<span style=\"color:blue;\"> As String<\/span>, strAction<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strStartzeit<span style=\"color:blue;\"> As String<\/span>, strEndzeit<span style=\"color:blue;\"> As String<\/span>, lngTaskID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strStandardkategorie<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span>TypeOf Item Is Outlook.TaskItem<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objTask = Item\r\n         <span style=\"color:blue;\">If <\/span>GetID(objTask.BillingInformation, \"task\") &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         strAufgabe = objTask.Subject\r\n         <span style=\"color:blue;\">Set<\/span> objProjectfolder = objTask.Parent\r\n         strDescription = objProjectfolder.Description\r\n         lngProjectID = GetID(strDescription, \"project\")\r\n         <span style=\"color:blue;\">If <\/span>objTask.DueDate &lt; CDate(DateSerial(2100, 1, 1))<span style=\"color:blue;\"> Then<\/span>\r\n             strFertigstellenBis = SQLDatum(objTask.DueDate)\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             strFertigstellenBis = \"NULL\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>objTask.DateCompleted &lt; CDate(DateSerial(2100, 1, 1))<span style=\"color:blue;\"> Then<\/span>\r\n             strErledigtAm = SQLDatum(objTask.DateCompleted)\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             strErledigtAm = \"NULL\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         strSQL = \"INSERT INTO tblAufgaben(Aufgabe, ProjektID, FertigstellenBis, ErledigtAm) VALUES(''''\" & strAufgabe _\r\n             & \"'''', \" & lngProjectID & \", \" & strFertigstellenBis & \", \" & strErledigtAm & \")\"\r\n         CurrentDBC.Execute strSQL, dbFailOnError\r\n         <span style=\"color:blue;\">If <\/span>CurrentDBC.RecordsAffected = 1<span style=\"color:blue;\"> Then<\/span>\r\n             objTask.BillingInformation = \"[task|\" & CurrentDBC.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0).Value & \"]\"\r\n             objTask.Save\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         ThisOutlookSession.Application_Startup\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Ereignisprozedur, die beim Anlegen oder Verschieben einer Aufgabe ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Die Prozedur erh&auml;lt als Parameter einen Verweis auf das neu erstellte oder verschobene Element (<b>Item<\/b>). Sie pr&uuml;ft, ob das Element den Typ <b>Outlook.TaskItem <\/b>aufweist und referenziert es dann mit der Variablen <b>objTask<\/b>. Genau wie bei den Projekt-Ordnern soll auch f&uuml;r die Aufgaben ein Hinweis auf den Objekttyp und den Prim&auml;rschl&uuml;sselwert, unter dem der entsprechende Datensatz in der Tabelle <b>tblAufgaben <\/b>gespeichert wird, im Aufgaben-Objekt abgelegt werden. Dieses bietet kein Feld namens <b>Beschreibung<\/b>, sodass wir hier die Eigenschaft <b>Abrechnungsinfo <\/b>(unter VBA <b>BillingInformation<\/b>) nutzen. Sollte dieses bereits gef&uuml;llt sein, was geschehen kann, wenn die Aufgabe nicht neu angelegt, sondern von einem anderen Projekte-Ordner verschoben wird, soll die Prozedur beendet werden. Aber warum das &#8211; in diesem Fall sollten doch eigentlich zumindest die Informationen, welchem Projekt die Aufgabe nun zugeordnet wird, in der Datenbank gespeichert werden Nun: Das geschieht auch, allerdings in einer anderen Ereignisprozedur. Das Ereignis <b>BeforeItemMove <\/b>des Objekts <b>mProject <\/b>wird n&auml;mlich beim Verschieben eines Aufgaben-Objekts vor <b>mTasks_ItemAdd <\/b>ausgel&ouml;st, und sie speichert die entsprechenden &auml;nderungen (siehe weiter unten).<\/p>\n<p>Die aktuelle Prozedur wird also auch beim Verschieben einer Aufgabe ausgel&ouml;st, behandelt aber nur das Anlegen neuer Aufgaben. Dabei tr&auml;gt sie zun&auml;chst den Wert der Eigenschaft <b>Subject <\/b>in die Variable <b>strAufgabe <\/b>ein und ermittelt &uuml;ber die <b>Parent<\/b>-Eigenschaft einen Verweis auf das &uuml;bergeordnete <b>Folder<\/b>-Objekt. Aus diesem liest sie dann den Prim&auml;rschl&uuml;sselwert des Projekte-Ordners aus der Tabelle <b>tblProjekte <\/b>aus und speichert ihn in der Variablen <b>lngProjectID<\/b>. Ein eventuell vorhandenes Fertigstellungsdatum landet in der Variablen <b>strFertigstellenBis <\/b>(leere Datumsfelder haben in Outlook den Wert <b>1.1.4501<\/b>, daher die Pr&uuml;fung, ob das Datum vor dem 1.1.2100 liegt &#8211; in diesem Fall soll <b>strFertigstellenBis <\/b>den Wert <b>NULL <\/b>erhalten). Das Gleiche geschieht f&uuml;r ein eventuell vorhandenes Erledigungsdatum aus <b>DateCompleted<\/b>.<\/p>\n<p>Die folgenden Anweisungen setzen die zum Speichern des Datensatzes in der Tabelle <b>tblAufgaben <\/b>notwendigen Informationen in Form einer <b>INSERT INTO<\/b>-Anweisung zusammen und f&uuml;hren diese aus. Sollte auch hier genau ein Datensatz von der Aktionsabfrage betroffen sein, tr&auml;gt die Prozedur einen Wert wie <b>[task|XXX] <\/b>in die Eigenschaft <b>BillingInformation <\/b>des <b>Task<\/b>-Objekts ein. Schlie&szlig;lich speichert sie die &auml;nderung mit der <b>Save<\/b>-Methode.<\/p>\n<p>Das Ergebnis k&ouml;nnen Sie beobachten, wenn Sie die Aufgabe per Doppelklick &ouml;ffnen und mit dem Ribbon-Eintrag <b>Aufgabe|Anzeigen|Details <\/b>zur Detailansicht wechseln. Unter <b>Abrechnungsinfo<\/b> finden Sie dann den Eintrag <b>[task|XXX] <\/b>(s. Bild 11).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_011.png\" alt=\"Versteckte Referenz auf den Datensatz der Tabelle tblAufgaben\" width=\"550\" height=\"314,4152\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Versteckte Referenz auf den Datensatz der Tabelle tblAufgaben<\/span><\/b><\/p>\n<h2>Verschieben oder L&ouml;schen einer Aufgabe<\/h2>\n<p>Sowohl das L&ouml;schen als auch das Verschieben einer Aufgabe in einen anderen Ordner l&ouml;sen das Ereignis <b>BeforeItemMove <\/b>des Objekts <b>mProject <\/b>aus (s. Listing 9). Genau genommen ist das L&ouml;schen ja auch nur ein Verschieben, und zwar in den Ordner <b>Gel&ouml;schte Objekte <\/b>(kann auch anders hei&szlig;en).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>mProject_BeforeItemMove(ByVal Item<span style=\"color:blue;\"> As Object<\/span>, ByVal MoveTo<span style=\"color:blue;\"> As <\/span>MAPIFolder, Cancel<span style=\"color:blue;\"> As Boolean<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>lngProjectID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngTaskID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTask<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objTask<span style=\"color:blue;\"> As <\/span>TaskItem\r\n     <span style=\"color:blue;\">If <\/span>TypeOf Item Is Outlook.TaskItem<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objTask = Item\r\n         strTask = objTask.Subject\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(objTask.BillingInformation) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         lngTaskID = GetID(objTask.BillingInformation, \"task\")\r\n         lngProjectID = GetID(MoveTo.Description, \"project\")\r\n         <span style=\"color:blue;\">If <\/span>lngProjectID = 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Ung&uuml;ltiger Zielordner. Das Projekt ist nicht in der Datenbank gespeichert.\"\r\n             Cancel = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         Select Case MoveTo.Name\r\n             <span style=\"color:blue;\">Case <\/span>mdlOutlook.GetOutlook.Session.GetDefaultFolder(olFolderDeletedItems)\r\n                 strSQL = \"UPDATE tblAufgaben SET GeloeschtAM = \" & ISODatum(Now) & \" WHERE AufgabeID = \" & lngTaskID\r\n                 CurrentDBC.Execute strSQL\r\n             <span style=\"color:blue;\">Case Else<\/span>\r\n                 strSQL = \"UPDATE tblAufgaben SET ProjektID = \" & lngProjectID & \" WHERE AufgabeID = \" & lngTaskID\r\n                 CurrentDBC.Execute strSQL, dbFailOnError\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: Ereignisprozedur, die beim L&ouml;schen oder Verschieben einer Aufgabe ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Die Prozedur erh&auml;lt einen Verweis auf die Aufgabe (<b>item<\/b>) und einen Verweis auf den Zielordner (<b>MoveTo<\/b>) als Parameter. Mit dem R&uuml;ckgabeparameter <b>Cancel <\/b>k&ouml;nnen Sie den Vorgang abbrechen.<\/p>\n<p>Die Prozedur pr&uuml;ft, ob es sich bei dem verschobenen Element um eine Aufgabe handelt. Falls ja, speichert sie einen Verweis darauf in der Variablen <b>objTask<\/b> und ermittelt mit der Funktion <b>GetID <\/b>den Prim&auml;rschl&uuml;sselwert f&uuml;r diese Aufgabe, die ja bereits in der Tabelle <b>tblAufgaben <\/b>angelegt sein muss (<b>lngAufgabeID<\/b>). Ist <b>BillingInformation <\/b>leer, handelt es sich offenbar um eine Aufgabe, die nicht im Kontext der Projektzeiterfassung angelegt wurde und die Prozedur wird verlassen.<\/p>\n<p>Dann ermittelt die Prozedur den Prim&auml;rschl&uuml;sselwert des Zielordners aus der Tabelle <b>tblProjekte<\/b> und speichert ihn in <b>lngProjektID<\/b>. Auch hier erfolgt die Pr&uuml;fung, ob es sich um ein in der Datenbank gespeichertes Projekt handelt.<\/p>\n<p>Danach pr&uuml;ft die Prozedur, ob der Name des Zielordners mit dem Namen des Ordners f&uuml;r die gel&ouml;schten Objekte &uuml;bereinstimmt. Falls ja, markiert die Prozedur den Datensatz der Tabelle <b>tblAufgaben <\/b>mit dem Prim&auml;rschl&uuml;sselwert aus <b>lngAufgabeID <\/b>als gel&ouml;scht.<\/p>\n<p>Anderenfalls k&ouml;nnen wir davon ausgehen, dass die Aufgabe gerade in einen g&uuml;ltigen Projekte-Ordner verschoben wird. Dann tr&auml;gt die Prozedur einfach den Prim&auml;rschl&uuml;sselwert f&uuml;r den Projekt-Ordner in das Fremdschl&uuml;sselfeld <b>ProjektID <\/b>der Tabelle <b>tblAufgaben <\/b>f&uuml;r die verschobene Aufgabe ein.<\/p>\n<h2>Ereignis beim &auml;ndern einer Aufgabe<\/h2>\n<p>Wenn Sie eine Aufgabe &auml;ndern, beispielsweise indem Sie die Bezeichnung anpassen oder den Status auf &#8222;Erledigt&#8220; setzen, sollen diese &auml;nderungen ebenfalls in der Datenbank gespeichert werden. Dies erledigt die Ereignisprozedur, die durch das Ereignis <b>ItemChange <\/b>des Objekts <b>mTasks <\/b>ausgel&ouml;st wird (s. Listing 10). Die Prozedur erh&auml;lt mit dem Parameter <b>Item <\/b>einen Verweis auf das ge&auml;nderte Objekt. Nach der Pr&uuml;fung, ob es sich um ein Element des Typs <b>TaskItem<\/b> handelt, speichert die Prozedur den Verweis darauf in der Variablen <b>objTask <\/b>und die Bezeichnung aus der Eigenschaft <b>Subject <\/b>in <b>strTask<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>mTasks_ItemChange(ByVal Item<span style=\"color:blue;\"> As Object<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>lngProjectID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngTaskID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTask<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objTask<span style=\"color:blue;\"> As <\/span>TaskItem\r\n     <span style=\"color:blue;\">Dim <\/span>strComplete<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFertigstellenBis<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span>TypeOf Item Is Outlook.TaskItem<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objTask = Item\r\n         strTask = objTask.Subject\r\n         lngTaskID = GetID(objTask.BillingInformation, \"task\")\r\n         <span style=\"color:blue;\">If <\/span>lngTaskID = 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Ung&uuml;ltige Aufgabe. Die Aufgabe ist nicht in der Datenbank gespeichert.\"\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>objTask.Complete<span style=\"color:blue;\"> Then<\/span>\r\n             strComplete = \", ErledigtAm = \" & ISODatum(Now)\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             strComplete = \", ErledigtAm = NULL\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>objTask.DueDate &lt; CDate(DateSerial(2100, 1, 1))<span style=\"color:blue;\"> Then<\/span>\r\n             strFertigstellenBis = SQLDatum(objTask.DueDate)\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             strFertigstellenBis = \"NULL\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         strSQL = \"UPDATE tblAufgaben SET Aufgabe = ''''\" & strTask & \"'''', FertigstellenBis = \" & strFertigstellenBis _\r\n             & strComplete & \" WHERE AufgabeID = \" & lngTaskID\r\n         CurrentDBC.Execute strSQL, dbFailOnError\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 10: Ereignisprozedur, die beim &auml;ndern der Eigenschaften einer Aufgabe ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Liefert die Eigenschaft <b>BillingInformationen <\/b>&uuml;ber die Funktion <b>GetID <\/b>keinen Prim&auml;rschl&uuml;sselwert, endet die Prozedur mit einer entsprechenden Meldung und die &auml;nderung wird abgebrochen. Dann liest die Prozedur den Erledigt-Status der Aufgabe ein und stellt damit einen Teil der SQL-Anweisung zusammen, die sp&auml;ter den entsprechenden Datensatz zur Aufgabe in der Tabelle <b>tblAufgaben<\/b> anpasst. Gleiches gilt f&uuml;r das Fertigstellungsdatum. Die folgende SQL-Anweisung &auml;ndert die entsprechenden Felder des Datensatzes der Tabelle <b>tblAufgaben<\/b>.<\/p>\n<h2>Ereignis beim Ziehen einer Aufgabe in den Kalender<\/h2>\n<p>Wenn der Benutzer aus einer Aufgabe eine T&auml;tigkeit erstellt, indem er diese aus der Aufgabenliste in den Kalender zieht, soll ein neuer Datensatz in der Tabelle <b>tblTaetigkeiten <\/b>angelegt werden. Dies erledigt die Prozedur aus Listing 11, die durch das Ereignis <b>ItemAdd<\/b> des Objekts <b>objAppointments <\/b>ausgel&ouml;st wird. Die Prozedur erh&auml;lt einen Verweis auf das <b>Item<\/b>-Objekt, das neu hinzugef&uuml;gt wurde. Die Prozedur pr&uuml;ft, ob es sich um ein <b>Appoint-ment-Item<\/b>-Element handelt, und stellt dann die Variable <b>objAppointment <\/b>auf dieses Element ein. Nun m&uuml;ssen wir anhand des neu erstellten <b>AppointmentItem<\/b>-Elements den Prim&auml;rschl&uuml;sselwert der Aufgabe ermitteln, aus welcher der Termin erstellt wurde. Das ist nun nicht ganz so einfach, denn die Aufgabe wurde uns ja nicht als Parameter &uuml;bergeben. Aber kein Problem: Wenn wir den neuen Termin einmal per Doppelklick &ouml;ffnen, sehen wir, dass die Basisinformationen zu der Aufgabe im Inhalt des Termins eingetragen wurden (s. Bild 12).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_06\/pic_1016_012.png\" alt=\"Der Hinweis auf die urspr&uuml;ngliche Aufgabe, aus der ein Termin wurde, findet sich im Inhalt des Termins.\" width=\"425\" height=\"445,2011\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Der Hinweis auf die urspr&uuml;ngliche Aufgabe, aus der ein Termin wurde, findet sich im Inhalt des Termins.<\/span><\/b><\/p>\n<p>Den Prim&auml;rschl&uuml;sselwert aus dem Ausdruck <b>[task|XXX] <\/b>liest die Prozedur dann mit der Funktion <b>GetID<\/b> aus und speichert diesen in <b>lngTaskID<\/b>. Danach legt die Prozedur einen neuen Datensatz in der Tabelle <b>tblTaetigkeiten <\/b>an und tr&auml;gt dort erstmal die aktuellen Eigenschaften des <b>AppointmentItem<\/b>-Elements ein. Das hei&szlig;t, dass dort beispielsweise die Zeit und das Datum der Kalenderposition landen, auf welche der Benutzer die Aufgabe gezogen hat. Erst wenn der Datensatz erfolgreich angelegt wurde, nimmt die Prozedur weitere &auml;nderungen an der T&auml;tigkeit vor. Zum Beispiel tr&auml;gt sie f&uuml;r die Eigenschaft <b>BillingInformation <\/b>einen Ausdruck wie <b>[action|XXX] <\/b>ein, wobei <b>XXX <\/b>wieder dem Prim&auml;rschl&uuml;sselwert des korrespondierenden Datensatzes entspricht. Der Startzeitpunkt wird f&uuml;r die Eigenschaft <b>Start <\/b>auf die aktuelle Zeit festgelegt (<b>Now<\/b>), das Ende auf den Zeitpunkt 25 Minuten sp&auml;ter (dies k&ouml;nnen Sie &auml;ndern, wenn Sie andere Intervalle ben&ouml;tigen). Es soll keine Erinnerung verwendet werden (<b>ReminderSet = False<\/b>). Als Kategorie tragen wir <b>aiuTermin <\/b>ein, um gegebenenfalls einmal alle auf diese Weise angelegten Elemente &uuml;ber die Kategorie referenzieren zu k&ouml;nnen.<\/p>\n<p>Schlie&szlig;lich speichern wir den Termin mit der <b>Save<\/b>-Methode. Dadurch springt ein neu angelegter Termin, egal, wohin im Kalender wir ihn gezogen haben, immer an den aktuellen Zeitpunkt.<\/p>\n<p>Nun haben wir allerdings die Eigenschaften des Termins ge&auml;ndert, aber die &auml;nderungen nicht in die Datenbank &uuml;bertragen. Dabei ist es doch wichtig, dass wir die Zeiten ordentlich erfassen! Das ist aber auch nicht schlimm, denn wir m&uuml;ssen ja ohnehin noch ein Ereignis implementieren, das beim &auml;ndern der Eigenschaften eines Termins ausgel&ouml;st wird. Dieses wird dann nat&uuml;rlich auch ausgel&ouml;st, wenn die Prozedur <b>objAppointments_ItemAdd <\/b>den neuen Termin angelegt hat und diesen dann &auml;ndert &#8211; so schlagen wir zwei Fliegen mit einer Klappe.<\/p>\n<h2>Ereignis beim &auml;ndern eines Termins\/einer T&auml;tigkeit<\/h2>\n<p>Die Prozedur aus Listing 12 wird durch das Ereignis <b>ItemChange <\/b>des Objekts <b>objAppointments <\/b>ausgel&ouml;st. Es erh&auml;lt einen Verweis auf das ge&auml;nderte Element als Parameter. Nach der Pr&uuml;fung, ob es sich um ein <b>AppointmentItem<\/b>-Element handelt, liest die Prozedur den Prim&auml;rschl&uuml;sselwert f&uuml;r das Element aus der Eigenschaft <b>BillingInformation <\/b>ein. Damit kann sie dann bereits die SQL-Anweisung zum &uuml;bertragen der aktuellen Eigenschaften in den entsprechenden Datensatz der Tabelle <b>tblTaetigkeiten<\/b> zusammenstellen und ausf&uuml;hren.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objAppointments_ItemChange(ByVal Item<span style=\"color:blue;\"> As Object<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>objAppointment<span style=\"color:blue;\"> As <\/span>Outlook.AppointmentItem\r\n     <span style=\"color:blue;\">Dim <\/span>lngActionID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span>TypeOf Item Is Outlook.AppointmentItem<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objAppointment = Item\r\n         lngActionID = GetID(objAppointment.BillingInformation, \"action\")\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngActionID = 0<span style=\"color:blue;\"> Then<\/span>\r\n             strSQL = \"UPDATE tblTaetigkeiten SET Taetigkeit = ''''\" & <span style=\"color:blue;\">Replace<\/span>(objAppointment.Subject, \"''''\", \"''''''''\") _\r\n                 & \"'''', Startzeit = \" & ISODatum(objAppointment.Start) & \", Endzeit = \" & ISODatum(objAppointment.End) _\r\n                 & \", Beschreibung = ''''\" & <span style=\"color:blue;\">Replace<\/span>(objAppointment.Body, \"''''\", \"''''''''\") & \"'''' WHERE TaetigkeitID = \" & lngActionID\r\n             CurrentDBC.Execute strSQL, dbFailOnError\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 12: Ereignisprozedur, die beim &auml;ndern der Eigenschaften einer T&auml;tigkeit ausgel&ouml;st wird<\/span><\/b><\/p>\n<h2>Ereignis beim L&ouml;schen einer T&auml;tigkeit aus dem Kalender<\/h2>\n<p>Fehlt nur noch ein Ereignis, n&auml;mlich das f&uuml;r das L&ouml;schen einer T&auml;tigkeit. Die entsprechende Prozedur aus Listing 13 wird durch das Ereignis <b>BeforeItemMove <\/b>des Objekts <b>objAppointmentFolder <\/b>ausgel&ouml;st.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objAppointmentFolder_BeforeItemMove(ByVal Item<span style=\"color:blue;\"> As Object<\/span>, ByVal MoveTo<span style=\"color:blue;\"> As <\/span>MAPIFolder, Cancel<span style=\"color:blue;\"> As Boolean<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>lngActionID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strAction<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objItem<span style=\"color:blue;\"> As <\/span>Outlook.AppointmentItem\r\n     <span style=\"color:blue;\">If <\/span>TypeOf Item Is Outlook.AppointmentItem<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objItem = Item\r\n         strAction = objItem.Subject\r\n         lngActionID = GetID(objItem.BillingInformation, \"action\")\r\n         <span style=\"color:blue;\">If <\/span>MoveTo.Name = GetOutlook.Session.GetDefaultFolder(olFolderDeletedItems)<span style=\"color:blue;\"> Then<\/span>\r\n             strSQL = \"UPDATE tblTaetigkeiten SET GeloeschtAm = \" & ISODatum(Now) & \" WHERE TaetigkeitID = \" & lngActionID\r\n             CurrentDBC.Execute strSQL\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 13: Ereignisprozedur, die beim L&ouml;schen einer T&auml;tigkeit\/eines Termins ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Diese erh&auml;lt neben dem Verweis auf das zu l&ouml;schende Element einen weiteren Parameter mit dem Zielordner. Dieser sollte dem Ordner mit den gel&ouml;schten Objekten entsprechen.<\/p>\n<p>Nach dem Identifizieren des &uuml;bergebenen Elements als <b>AppointmentItem<\/b>, der Ermittlung des Prim&auml;rschl&uuml;sselwertes f&uuml;r diesen Termin aus der Eigenschaft <b>BillingInformation<\/b> und der Pr&uuml;fung des Zielverzeichnisses stellt die Prozedur eine SQL-Anweisung zusammen, die den Wert des Feldes <b>GeloeschtAm <\/b>auf den aktuellen Zeitpunkt einstellt und f&uuml;hrt diese aus.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Damit haben wir alle Ereignisse implementiert, die beim Anlegen, Bearbeiten und L&ouml;schen von Projektordnern, Aufgaben und Terminen behandelt werden m&uuml;ssen, um die &auml;nderungen jeweils in den drei Tabellen <b>tblProjekte<\/b>, <b>tblAufgaben <\/b>und <b>tblTaetigkeiten <\/b>zu pflegen.<\/p>\n<p>Damit ist sichergestellt, dass die in Outlook gepflegten Projektzeitdaten auch in der Datenbank landen und dort weiterverarbeitet werden k&ouml;nnen &#8211; beispielsweise, um f&uuml;r einen bestimmten Zeitraum die erfassten Arbeitszeiten f&uuml;r ein bestimmtes Projekt zu erfassen und in Rechnung zu stellen.<\/p>\n<p>Wie dies gelingt, zeigt ein weiterer Beitrag namens <b>Projektzeiten auswerten <\/b>(<b>www.access-im-unternehmen.de\/1018<\/b>) in der folgenden Ausgabe. Au&szlig;erdem wollen wir die Projektzeiterfassung noch ein wenig aufpeppen. Dazu f&uuml;gen wir der Aufgabenliste noch einige Kategorien hinzu, in die wie die Aufgaben einteilen k&ouml;nnen. Diese Kategorien beschreiben den jeweiligen Bearbeitungsstand einer Aufgabe und sollen beispielsweise helfen, nicht zu viele Aufgaben gleichzeitig zu bearbeiten. Dies finden Sie im Beitrag <b>Kanban mit Outlook und Access <\/b>(<b>www.access-im-unternehmen.de\/1017<\/b>) &#8211; ebenfalls in der folgenden Ausgabe.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>clsTasks.cls<\/p>\n<p>mdlGlobal.bas<\/p>\n<p>mdlOutlook.bas<\/p>\n<p>Projektzeiterfassung.accdb<\/p>\n<p>ThisOutlookSession.cls<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/BAE50A0F-3FBD-466B-9B2A-5279F17B3DAF\/aiu_1016.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die Erfassung von Projektzeiten ist eine Aufgabe, die man gern etwas stiefm&uuml;tterlich handhabt. Am Ende des Tages, der Woche oder auch des Monats muss man dann die f&uuml;r verschiedene Aufgaben verbrauchte Zeit aus dem Ged&auml;chtnis nachtragen. Dem wollen wir mit einer L&ouml;sung, die Outlook und Access nutzt, entgegenwirken. Damit legen Sie eine T&auml;tigkeit einer bestimmten Dauer &#8211; in diesem Fall 25 Minuten &#8211; ganz einfach per Drag and Drop in den Outlook-Kalender an. Der Rest geschieht im Hintergrund: Die T&auml;tigkeit wird samt Projekt und Aufgabe in einer Access-Datenbank gespeichert und kann anschlie&szlig;end bequem ausgewertet werden.<\/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":[662015,66062015,44000027],"tags":[],"class_list":["post-55001016","post","type-post","status-publish","format-standard","hentry","category-662015","category-66062015","category-Loesungen"],"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>Projektzeiterfassung mit Outlook und Access - 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\/Projektzeiterfassung_mit_Outlook_und_Access\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Projektzeiterfassung mit Outlook und Access\" \/>\n<meta property=\"og:description\" content=\"Die Erfassung von Projektzeiten ist eine Aufgabe, die man gern etwas stiefm&uuml;tterlich handhabt. Am Ende des Tages, der Woche oder auch des Monats muss man dann die f&uuml;r verschiedene Aufgaben verbrauchte Zeit aus dem Ged&auml;chtnis nachtragen. Dem wollen wir mit einer L&ouml;sung, die Outlook und Access nutzt, entgegenwirken. Damit legen Sie eine T&auml;tigkeit einer bestimmten Dauer - in diesem Fall 25 Minuten - ganz einfach per Drag and Drop in den Outlook-Kalender an. Der Rest geschieht im Hintergrund: Die T&auml;tigkeit wird samt Projekt und Aufgabe in einer Access-Datenbank gespeichert und kann anschlie&szlig;end bequem ausgewertet werden.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T19:09:22+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg09.met.vgwort.de\/na\/2e6ebc37f1dd4a84bd673898d73bbea5\" \/>\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=\"36\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Projektzeiterfassung mit Outlook und Access\",\"datePublished\":\"2020-05-22T19:09:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/\"},\"wordCount\":6068,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/2e6ebc37f1dd4a84bd673898d73bbea5\",\"articleSection\":[\"2015\",\"6\\\/2015\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/\",\"name\":\"Projektzeiterfassung mit Outlook und Access - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/2e6ebc37f1dd4a84bd673898d73bbea5\",\"datePublished\":\"2020-05-22T19:09:22+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/2e6ebc37f1dd4a84bd673898d73bbea5\",\"contentUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/2e6ebc37f1dd4a84bd673898d73bbea5\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Projektzeiterfassung_mit_Outlook_und_Access\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Projektzeiterfassung mit Outlook und Access\"}]},{\"@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":"Projektzeiterfassung mit Outlook und Access - 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\/Projektzeiterfassung_mit_Outlook_und_Access\/","og_locale":"de_DE","og_type":"article","og_title":"Projektzeiterfassung mit Outlook und Access","og_description":"Die Erfassung von Projektzeiten ist eine Aufgabe, die man gern etwas stiefm&uuml;tterlich handhabt. Am Ende des Tages, der Woche oder auch des Monats muss man dann die f&uuml;r verschiedene Aufgaben verbrauchte Zeit aus dem Ged&auml;chtnis nachtragen. Dem wollen wir mit einer L&ouml;sung, die Outlook und Access nutzt, entgegenwirken. Damit legen Sie eine T&auml;tigkeit einer bestimmten Dauer - in diesem Fall 25 Minuten - ganz einfach per Drag and Drop in den Outlook-Kalender an. Der Rest geschieht im Hintergrund: Die T&auml;tigkeit wird samt Projekt und Aufgabe in einer Access-Datenbank gespeichert und kann anschlie&szlig;end bequem ausgewertet werden.","og_url":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T19:09:22+00:00","og_image":[{"url":"http:\/\/vg09.met.vgwort.de\/na\/2e6ebc37f1dd4a84bd673898d73bbea5","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"36\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Projektzeiterfassung mit Outlook und Access","datePublished":"2020-05-22T19:09:22+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/"},"wordCount":6068,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/2e6ebc37f1dd4a84bd673898d73bbea5","articleSection":["2015","6\/2015","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/","url":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/","name":"Projektzeiterfassung mit Outlook und Access - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/2e6ebc37f1dd4a84bd673898d73bbea5","datePublished":"2020-05-22T19:09:22+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#primaryimage","url":"http:\/\/vg09.met.vgwort.de\/na\/2e6ebc37f1dd4a84bd673898d73bbea5","contentUrl":"http:\/\/vg09.met.vgwort.de\/na\/2e6ebc37f1dd4a84bd673898d73bbea5"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Projektzeiterfassung_mit_Outlook_und_Access\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Projektzeiterfassung mit Outlook und Access"}]},{"@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\/55001016","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=55001016"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001016\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001016"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001016"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001016"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}