Lazarus und Outlook via OLE steuern

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Lazarus und Outlook via OLE steuern

Beitrag von corpsman »

Hallo Zusammen,

bei uns auf der Arbeit gibt es mehr oder weniger "suboptimale" Prozesse, wenn es darum geht den Urlaub / Gleitzeit / mobiles Arbeiten zu beantragen. Hierzu müssen wir ettliche sich widerhohlende langweilige Aufgaben in Outlook erledigen.

Also dachte ich mir bastle ich mir ein Lazarusprogram das das für mich erledigt. Einiges an Google Suche später und es stellt sich heraus, das geht ist aber sehr mühseelig (zumindest wie ich das bisher hin bekomme) und daher hier die Frage ob ihr mir einen Tipp geben könnt, wie ich das effizienter hin bekomme.

Gestartet bin ich mit:
https://forum.lazarus.freepascal.org/in ... ic=18931.0
und
https://docs.microsoft.com/de-de/office ... ntmentitem
Dann habe ich mir folgende Unit gebastelt:

Code: Alles auswählen

Unit uOutlook;

{$MODE ObjFPC}{$H+}

Interface

Uses
  Classes, SysUtils, ComObj;

(*
 * MSDN: https://docs.microsoft.com/de-de/office/vba/api/overview/outlook/object-model
 *
 *)

Const
  olMailItem = 0; // https://forum.lazarus.freepascal.org/index.php?topic=18931.0
  olAppointmentItem = 1; // Durch Try and Error ermittelt
  olContactItem = 2; // Durch Try and Error ermittelt

//  olMeeting = 0; -- Das stimmt noch nicht

Procedure DisplayOutlookItem(Item: integer); // Zum Ermillten der olMailItem , ...

Procedure NewAppointMent(Subject: String);

Procedure SendMail(CC, BCC, Subject, Body: String; Send: Boolean);

Implementation

Procedure DisplayOutlookItem(Item: integer);
Var
  Outlook: OLEVariant;
  newAppointment: OLEVariant;
Begin
  Try
    Outlook := GetActiveOleObject('Outlook.Application');
  Except
    Outlook := CreateOleObject('Outlook.Application');
  End;
  newAppointment := Outlook.CreateItem(Item);
  newAppointment.Display;

  Outlook := Unassigned;
End;

// https://docs.microsoft.com/de-de/office/vba/api/outlook.appointmentitem

Procedure NewAppointMent(Subject: String);
Var
  Outlook: OLEVariant;
  newAppointment: OLEVariant;
  tmp: variant;
Begin
  Try
    Outlook := GetActiveOleObject('Outlook.Application');
  Except
    Outlook := CreateOleObject('Outlook.Application');
  End;
  newAppointment := Outlook.CreateItem(olAppointmentItem);
  newAppointment.MeetingStatus := 1;
  tmp := Subject;
  newAppointment.Subject := tmp;

  newAppointment.Display;

  Outlook := Unassigned;
End;

// Quelle: https://forum.lazarus.freepascal.org/index.php?topic=18931.0

Procedure SendMail(CC, BCC, Subject, Body: String; Send: Boolean);
Var
  Outlook: OLEVariant;
  MailItem: variant;
  tmp: variant;
Begin
  Try
    Outlook := GetActiveOleObject('Outlook.Application');
  Except
    Outlook := CreateOleObject('Outlook.Application');
  End;
  MailItem := Outlook.CreateItem(olMailItem);
  // TODO: Wie kriegen wir das "AN" ?
  If cc <> '' Then Begin
    tmp := CC;
    MailItem.to  := tmp; // das geht net weil to ein schlüsselwort ist :(
  End;


  If cc <> '' Then Begin
    tmp := CC;
    MailItem.Cc := tmp;
  End;
  If bcc <> '' Then Begin
    tmp := BCC;
    MailItem.BCC := tmp;
  End;
  If Subject <> '' Then Begin
    tmp := Subject;
    MailItem.Subject := tmp;
  End;
  If Body <> '' Then Begin
    tmp := Body;
    MailItem.Body := tmp;
  End;
  // MailItem.HTMLBody // if you wont HTML in message body
  //  tmp := AttachEdit.Text;
  //  MailItem.Attachments.Add(tmp);
  If send Then Begin
    MailItem.Send;
  End
  Else Begin
    MailItem.Display;
  End;
  Outlook := Unassigned;
End;

End.

Wie ihr sehen könnt mache ich hier sehr viel Try and Error. Ich habe schon rausgefunden, dass ich eine Variable befor ich sie einer Eigenschaft zuweisen kann erst in eine tmp bom Typ Variant zuweisen muss. Methoden kann ich einfach so aufrufen.
Auch die Constanten sind alle via Try and Error ermittelt. Code Vervollständigung gibt es hier nicht :(

Ich habe leider nirgends eine Dokumentation dieser Constanten gefunden, habt ihr da bessere Quellen ? Ne Idee wie ich den Try and Error Process verringern kann ?

Mein Ziel ist es:
- Termine zu bearbeiten, versenden und deren Anzeige zu verändern
--
Just try it

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Lazarus und Outlook via OLE steuern

Beitrag von charlytango »

ok, ich lass mich breitschlagen.

Der Code ist etliche Jahre alt und scheinbar hab ich den aus Visual-Basic oder Access-Code adaptiert. Hässlich ist er außerdem noch und meine Kommentare sind auch noch drin. Das sind die eigentlichen Programmteile die mit Outlook kommunizieren und von anderen Funktionen benutzt werden.
Aber wenn es jemandem hilft, blamiere ich mich halt mal

Outlook ist intern ein ziemliches Chaos.. zumindest war es das vor 20 Jahren mal. Das sieht so aus als ob drei Teams Outlook entwickelt haben, die aber nciht miteinander reden durften. Denn praktisch für jede Funktion gibt es mehrere gleichlautende Funktionen die sich nur in der Parameterreihenfolge oder Benennung unterscheiden aber das gleiche tun. Hab nie verstanden warum das jemand so macht.

Have Fun
Dateianhänge
uoutlook.pas
(20.7 KiB) 168-mal heruntergeladen

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Lazarus und Outlook via OLE steuern

Beitrag von six1 »

Danke für den Code @charlytango !

...ich habe schlimmeres zusammengetippt (früher) :lol:
Gruß, Michael

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Lazarus und Outlook via OLE steuern

Beitrag von six1 »

Eine Frage habe ich zu deinem Code:
Das Startdatum eines Termines ermittelst du über den Zugriff auf Termin.Start
Mein Versuch auf ein Terminende abzufragen mittels Termin.Ende schlugen fehl.
Auch ein Versuch mit Termin.endofappt erzeugte nur eine müde Exception :)

any Idea?
Gruß, Michael

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Lazarus und Outlook via OLE steuern

Beitrag von Socke »

six1 hat geschrieben:
Di 25. Mai 2021, 10:47
Mein Versuch auf ein Terminende abzufragen mittels Termin.Ende schlugen fehl.
Auch ein Versuch mit Termin.endofappt erzeugte nur eine müde Exception :)
Sollte es nicht mit Termin.End (ohne e) funktionieren? Zumindest sagt das die Doku.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Lazarus und Outlook via OLE steuern

Beitrag von corpsman »

Das Problem ist doch das end ein schlüsselwort ist

.end := now();

geht nicht
--
Just try it

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Lazarus und Outlook via OLE steuern

Beitrag von PascalDragon »

Und genau für diese Fälle wurde das escapen von Schlüsselwörtern eingeführt:

Code: Alles auswählen

Termin.&End := Now;
FPC Compiler Entwickler

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Lazarus und Outlook via OLE steuern

Beitrag von six1 »

Super, Danke PascalDragon
Funktioniert 1a.
Gruß, Michael

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Lazarus und Outlook via OLE steuern

Beitrag von charlytango »

six1 hat geschrieben:
Di 25. Mai 2021, 09:45
Danke für den Code @charlytango !
...ich habe schlimmeres zusammengetippt (früher) :lol:
Das Teil ist auch an die 8 Jahre alt ;)
Aber es freut mich dass er dir helfen konnte.

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Lazarus und Outlook via OLE steuern

Beitrag von corpsman »

Wie geil ist das denn, da bin ich nun schon mehr wie 1,5Tage dabei, aber das kannte ich noch nicht (y). Danke das löst einiges :D

PascalDragon hat geschrieben:
Di 25. Mai 2021, 13:16
Und genau für diese Fälle wurde das escapen von Schlüsselwörtern eingeführt:

Code: Alles auswählen

Termin.&End := Now;
--
Just try it

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Lazarus und Outlook via OLE steuern

Beitrag von corpsman »

So nun hänge ich am Nächsten Problem und bin gespannt ob ihr mir da helfen könnt.

Im Urlaubskalender in den ich meinen Termin eintragen muss gibt es "Kategorieen" diese kann ich auch setzen, aber im Termin der der dann an den Kalender gesendet wird stehen sie nachher nicht, nur in meinem "Lokalen" Termin.

Blöd ist auch, das die da nicht die Default Kategorieren (Rot Gelb Rrün..) genommen haben sondern "Kalender Eigene"

Code: Alles auswählen


Procedure FreiTermin(Titel, Vertreter: String; Start, Finish: TDateTime);
Var
  Outlook: OLEVariant;
  newAppointment: OLEVariant;
  cpt: String;
  i: TVarType;
  str: String;
Begin
  str := OL_ListCategories;
  (*
  * 1. Speichern eines Termins im Lokalen Kalender und in dx7ente5
  *
  * Anzeige: Frei
  * TagesEvent: Ja
  * Datum: Date
  * Kategorie: 2/CSF
  * Teilnehmer: Ich und <kalender_Urlaub> und Vorgesetzter
  * Betreff: Titel <Nachname>
  * Ort: -
  *)
  Outlook := GetOutLook();
  newAppointment := Outlook.CreateItem(olAppointmentItem);
  newAppointment.MeetingStatus := olAppointment; // Typ Besprechung
  newAppointment.BusyStatus := olFree;
  newAppointment.AllDayEvent := True;
  newAppointment.Start := olevariant(Start);
  If start <> Finish Then Begin
    newAppointment.&End := olevariant(Finish);
  End;
  newAppointment.Categories := olevariant('2/CSF');
  newAppointment.Categories := olevariant('Grüne Kategorie');
//  newAppointment.ShowCategoriesDialog;  -- Der Dialog wird zwar gezeigt, er zeigt aber nicht die Kategorieen des Kalenders an (nur meine Lokalen)
//                                                                             Macht man das ganze von "Hand" in Outlook werden die Kategorieen des Kalenders angezeigt.
  newAppointment.Location := olevariant('-');
  newAppointment.ReminderSet := false;
  cpt := Titel + ' ';
  If Finish - Start > 1 Then Begin // Bei einem Termin am 2 Tagen ist ein Vertreter notwendig
    cpt := cpt + ' (Vertretung: ' + Vertreter + ')';
  End;
  newAppointment.Subject := olevariant(cpt);
  (*
   * 2. Versenden
   *)

  newAppointment.Display(true); // Blockend anzeigen ob alles stimmt -> Kategorie stimmt leider nicht :(
//  newAppointment.Send; -- so würde das ganze dann gesendet

  i := VarType(newAppointment.Categories);
  str := VarToStr(newAppointment.Categories); // Auslesen was Kathegorietechnisch im Termin steht
  
  (*
   * 3. Den Termin im Eigenen Kalender auf "Abwesend" stellen und Speichern (nicht im Gruppenkalender)
   *)
  newAppointment.Categories := Unassigned;
  newAppointment.BusyStatus := olAbsent;
  newAppointment.Save;
  Outlook := Unassigned; // Alles wieder frei geben
End;     
Was evtl auch helfen könnte, wenn ich den Termin in dem Kalender öffnen könnte und da mal "nachsehen" wie die Kathegorie genau heist (haben ja alle so ne GUID), nur wie öffnet man einen bestimmten Termin in einem Anderen Kalender ?
--
Just try it

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Lazarus und Outlook via OLE steuern

Beitrag von charlytango »

in meinem Source findest du function OL_CategoryExists -- da werden Categories ausgelesen und durchsucht.

Und in function OL_GetMyRootFolder werden die Root-Folder durchsucht

damit solltest du doch was anfangen können -- schau mal in einem Testprojekt ob du alle verfügbaren Kalender anzeigen kannst, um dann den einen den du suchst zu identifizieren.

Wirklich qualifiziert kann ich dir da nicht weiterhelfen weil ich Outlook schon vor Jahren verbannt habe.
Tip: versuche OL-Probleme/Anforderungen nicht mit Delphi/Lazarus zu suchen sondern mit "Visual Basic" asl Stichwort. Da gibt es sicher mehr und den Code umzusetzten ist dann recht leicht bzw gibt einen Hinweis für Tests.

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Lazarus und Outlook via OLE steuern

Beitrag von corpsman »

Ja das ist das Merkwürdige,

hab deinen Code durchgeschaut gehabt und die RootFolder funktion gibt dann ja auch eine Liste aller möglicher Verzeichnisse, diese konnte ich auch sehen. mittels .Parent zurück und "9" direkt in die Calender rein. Komischerweise habe ich im Outlook sehr viele Kalender selbst hinzugefügte und welche über "TEAM" erhalten. Aber all diese Kalender tauchen in der Liste nicht auf, nur mein eigener und irgend so ein Komischer Geburtstagskalender.

Die Kathegorieen konnte ich auch lesen aber immer nur die meines Outlooks.

Im Outlook muss ich immer zuerst den Urlaubskalender anwählen und dann von dort aus die neue "Besprechungsanfrage" starten, dann sind dort auch die Kalender Kategorieen zu sehen.

=> Mein Schluß ich muss zuerst den Kalender irgendwie via source anwählen, und dann das Appointment dort createn. Da ich aber in der GetDefaultFolder Routine keinen der Kalender "sehen" kann weis ich nicht wie ich da rein komme :(.

Den Hinweis mit Visual Basic werde ich morgen mal ausprobieren, evtl hilft mir das weiter ..


[edit]
das hier scheint in die Richtung zu gehen: https://social.msdn.microsoft.com/Forum ... outlookdev

es geht um shared calender mit dem Link: https://docs.microsoft.com/en-us/office ... aredFolder

da werde ich morgen was zum ausprobieren haben ;)

Beispiel in VBA: https://stackoverflow.com/questions/574 ... d-calendar
--
Just try it

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Lazarus und Outlook via OLE steuern

Beitrag von charlytango »

ja, diese Art von Quellen meinte ich. Da gibt es sicher noch mehr.
Und VB ist ziemlich leicht zu übersetzen und zu lesen.

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Lazarus und Outlook via OLE steuern

Beitrag von corpsman »

Jehaa, ich bin ein Stück weiter, wenn man im obigen teil den Part von Outlook bis new Appointment durch das hier ersetzt:

Code: Alles auswählen

  Outlook := GetOutLook();
  NameSpace := Outlook.GetNameSpace('MAPI');
  Recipient := NameSpace.CreateRecipient('URL zum Kalender');
  Recipient.Resolve;
  If Not Recipient.Resolved Then Begin // Konnte den Kalender nicht auflösen -> Abbruch mit Fehler
    Outlook := Unassigned; // Alles wieder frei geben
    Recipient  := Unassigned; // Alles wieder frei geben
    result := false;
    exit;
  End;
  CalendarFolder := NameSpace.GetSharedDefaultFolder(Recipient, olFolderCalendar);
  newAppointment := CalendarFolder.items.add();  
Dann kann man einen Termin im Shared Kalender erzeugen, und dort ist dann auch die Kategorie verfügbar ;)

Nun muss ich nur noch rauskriegen, wie ich den so gesendeten Termin in meinem Eigenen Kalender finden und dann Öffnen kann um ihn als "Abwesend" zu speichern ;)
--
Just try it

Antworten