Wie wir im Beitrag “Benutzerdefinierte Felder in Outlook” gezeigt haben, können Sie beispielsweise einem Outlook-Termin weitere Seiten mit benutzerdefinierten Steuerelementen hinzufügen. Wie nicht anders zu erwarten, lassen sich diese Elemente auch programmieren. Ein Einsatzzweck ist, die benutzerdefinierten Steuer-elemente beziehungsweise die dahinter stehenden Felder vorab mit Standardwerten zu füllen – beispielsweise das Feld “Mitarbeiter” mit dem Namen des aktuellen Mitarbeiters.
Ereignisse von Terminen und Steuerelementen
Uns als Access-Entwickler interessiert neben den Objekten und Eigenschaften auch, welche Ereignisse die Objekte auslösen, mit denen wir arbeiten. Und natürlich lösen auch Outlook-Termine Ereignisse aus und auch die durch den Entwickler hinzugefügten Steuer-elemente.
Schauen wir in den Objektkatalog, finden wir allein für das AppointmentItem-Objekt, um das es hier im Wesentlichen geht, einige Ereignisse (siehe Bild 1).
Bild 1: Ereignisse des AppointmentItem-Elements im Objektkatalog
Um ein AppointmentItem, in diesem Beitrag auch Termin genannt, so zu programmieren, dass wir die hier aufgeführten Ereignisse implementieren, benötigen wir eine andere Herangehensweise als beispielsweise bei der Programmierung eines Access-Formulars oder seiner Steuer-elemente.
Dort brauchen wir nur explizit die gewünschten Ereignisse in das jeweilige Klassenmodul zu schreiben und für die Ereigniseigenschaft den Wert [Ereignisprozedur] zu hinterlegen. Unter Outlook sieht das etwas anders aus – wie genau, schauen wir uns nun im Detail an.
Ereignisse beim Bearbeiten
Als Erstes schauen wir uns an, wie wir Ereignisse abfangen können, die beim Bearbeiten eines Termins ausgelöst werden. Dazu brauchen wir eine Instanz des Termins. Wie kommen wir an diese heran Dazu gehen wir den Weg über das sogenannte Inspector-Element. Inspector ist das Fenster, in dem ein Outlook-Objekt – wie in diesem Fall ein Termin – angezeigt wird. Über das Inspector-Objekt können wir schließlich auf den enthaltenen Termin zugreifen, wenn der Benutzer diesen geöffnet hat.
Neu geöffneten Inspector referenzieren
Um auf ein frisch geöffnetes Termin-Objekt zugreifen zu können, benötigen wir das Inspector-Objekt. Dieses erhalten wir über die Inspectors-Auflistung. Dazu deklarieren wir eine Objektvariable wie die folgende im Klassenmodul ThisOutlookSession des VBA-Projekts von Outlook:
Private WithEvents objInspectors As Inspectors
Wir verwenden das Schlüsselwort WithEvents, um die Ereignisse dieses Objekts implementieren zu können. Die Inspectors-Auflistung hat nur eine Ereigniseigenschaft, die wir implementieren können, indem wir im linken Kombinationsfeld im VBA-Fenster des Moduls ThisOutlookSession den Eintrag objInspectors auswählen. Im rechten Kombinationsfeld wird dann automatisch das einzige Ereignis ausgewählt und im VBA-Fenster die Ereignisprozedur objInspectors_NewInspector angelegt (siehe Bild 2). Diese Prozedur sieht zunächst wie folgt aus:
Bild 2: Anlegen des Ereignisses für die Inspectors-Auflistung
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector) End Sub
Diese Ereignisprozedur wird im aktuellen Zustand des Moduls niemals ausgelöst, denn die Objektvariable objInspectors wurde noch nicht gefüllt. Das holen wir nun nach, indem wir ihr in der Ereignisprozedur Application_Startup die Auflistung zuweisen:
Private Sub Application_Startup() Set objInspectors = Outlook.Application.Inspectors End Sub
Die Prozedur Application_Startup wird bei jedem Start von Outlook aufgerufen. Sie können nun Outlook neu starten, um diese Prozedur auszulösen, oder Sie rufen diese einfach durch Platzieren der Einfügemarke in der Prozedur und Betätigen der Taste F5 auf. Setzen Sie außerdem einen Haltepunkt in die Prozedur objInspectors_New-Inspector. Wenn Sie nun zum Anwendungsfenster von Outlook wechseln und durch einen Doppelklick in den Kalender einen neuen Termin öffnen, wird die Prozedur objInspectors_NewInspector ausgelöst und stoppt am Haltepunkt.
Neues Inspector-Fenster referenzieren
Damit kommen wir zum nächsten Schritt: Der Parameter Inspector der Prozedur objInspectors_NewInspector liefert einen Verweis auf das neue Inspector-Fenster. Dieses können wir nun wiederum mit einer Objektvariablen referenzieren, um seine Ereignisse implementieren zu können. Dazu fügen wir dem Modul ThisOutlookSession die folgende Objektvariable hinzu, wiederum mit dem Schlüsselwort WithEvents ausgestattet:
Private WithEvents objInspector As Inspector
Wenn wir das neue Objekt im linken Kombinationsfeld des VBA-Fensters auswählen, finden wir im rechten Kombinationsfeld alle dafür zur Verfügung stehenden Ereignisse vor – zum Beispiel eines, das beim Wechseln der Seite ausgelöst wird (siehe Bild 3). Um dieses auszuprobieren, stellen wir in der Ereignisprozedur objInspectors_NewInspector die Objektvariable objInspector auf das mit dem Parameter Inspector gelieferte Objekt ein:
Bild 3: Ereignisse eines Outlook-Inspectors
Private Sub objInspectors_NewInspector( ByVal Inspector As Inspector) Set objInspector = Inspector End Sub
Dann implementieren wir das Ereignis PageChange der neuen Objektvariablen und geben darin den Wert des Parameters ActivePageName aus:
Private Sub objInspector_PageChange( ActivePageName As String) Debug.Print "Aktuelle Seite: " & ActivePageName End Sub
Damit können wir nun zwischen den Seiten Termin und Terminplanung hin- und herwechseln und erhalten jeweils den Titel der aktiven Seite im Direktbereich. Wenn Sie, wie im Beitrag Benutzerdefinierte Felder in Outlook (www.access-im-unternehmen.de/1221) beschrieben, bereits eine weitere Seite namens Termindetails angelegt haben, können Sie auch diese aufrufen und den jeweiligen Namen ausgeben.
Unterscheidung zwischen verschiedenen Inspector-Objekten
Wir haben nun bewusst immer Termin-Einträge im Inspector-Objekt geöffnet. Aber auch beim Öffnen von E-Mails oder Kontakten wird das Ereignis objInspectors_NewInspector ausgelöst. Wenn wir nun nicht mehr nur mit objInspector das geöffnete Inspector-Objekt referenzieren wollen, sondern auch mit einer weiteren Objektvariablen namens objAppointmentItem den im Inspector enthaltenen Termin, kann es zu Problemen kommen – beispielsweise, wenn wir gar keinen Termin-Inspector geöffnet haben.
In diesem Fall müssen wir also zuvor prüfen, ob überhaupt ein Inspector mit einem Termin geöffnet wurde.
Dazu deklarieren wir wieder eine Objektvariable mit dem Schlüsselwort WithEvents für das AppointmentItem-Objekt im neu geöffneten Inspector:
Private WithEvents objAppointmentItem As AppointmentItem
Dann erweitern wir die Prozedur objInspectors_NewInspector so, dass wir den Typ des enthaltenen Elements prüfen und nur im Falle eines Appointments einen Verweis auf das Element in die Variable objAppointmentItem schreiben:
Private Sub objInspectors_NewInspector( ByVal Inspector As Inspector) Set objInspector = Inspector Select Case Inspector.CurrentItem.Class Case olAppointment Set objAppointmentItem = Inspector.CurrentItem End Select End Sub
Interessant sind zum Beispiel die beiden Ereignisse PropertyChange und CustomPropertyChange, die jeweils beim Ändern von eingebauten und benutzerdefinierten Ereignissen ausgelöst werden. Das Ereignis PropertyChange können Sie so implementieren:
Private Sub objAppointmentItem_PropertyChange( ByVal Name As String) Debug.Print "Eigenschaft geändert: " & Name End Sub
Hier können wir leider nicht über die Properties-Auflistung auf die Eigenschaft mit dem geänderten Wert zugreifen, denn diese Auflistung gibt es schlicht nicht. Sie könnten aber per Select Case auf die Änderung bestimmter Eigenschaften reagieren, die für den Anwendungsfall interessant sind. Im Beispiel aus Listing 1 geben wir die Werte für die Eigenschaften Subject und Start aus, wenn diese geändert wurden.
Private Sub objAppointmentItem_PropertyChange(ByVal Name As String) Select Case Name Case "Subject" Debug.Print "Die Eigenschaft '" & Name & "' wurde geändert." Debug.Print "Neuer Wert: " & objAppointmentItem.Subject Case "Start" Debug.Print "Die Eigenschaft '" & Name & "' wurde geändert." Debug.Print "Neuer Wert: " & objAppointmentItem.Start End Select Debug.Print "Eigenschaft geändert: " & Name End Sub
Listing 1: Ereignisprozedur beim Ändern einer eingebauten Eigenschaft