[SWT] Outlook um Mail / Termin / usw. Kategorien erweitern via OLE

Bakalit

Grünschnabel
Hallo Tom

Erst mal herzlichen Dank für deine Post hier! Du bist auf weiter Flur echt der einzige der hilfreiche Infos und Anleitungen zu OLE und Outlook schreibt.

Mit deinen Beispielen habe ich es geschafft Outlook Termine aus Java zu erzeugen. Bis OL 2007(XP) geht das sogar ohne, dass Outlook läuft, ab 2010 (Win7) muss dann OL offen sein, aber es geht immer noch ohne Bestätigung.

Ich möchte nun die Termine einer Kategorie zuordnen. Das klappt auch über:

Code:
int[] CategoriePropertyDispId = appointmentItemAutomation.getIDsOfNames(new String[]{"Categories"});

appointmentItemAutomation.setProperty(CategoriePropertyDispId[0], new Variant(pColor));

Aber ich kann nur jene Kategorien setzten die OL bereits kennt. Nun ist meine Frage, ob es eine Möglichkeit gibt über OLE neue Kategorien zu erzeugen?

Und wenn ich schon am fragen bin, kennst du einen Weg Regeln in OL über OLE zu erstellen? Also so was wie: Wenn Mail von XYZ, dann mach DIES und DAS, ausser wenn ABC.

Wäre super wenn du mir hier helfen könntest.

Danke schon mal im Voraus und Grüsse

Tobi
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

hier mal ein kleines Beispiel, wie man mittels SWT / OLE Automation Outlook um weitere Kategorien erweitern kann. Getestet habe ich das Beispiel mit Outlook 2010.
Im Beispiel verwende ich einen ganz einfachen VBA Property-Path Expression-Evaluator , den ich auf ein absolutes Minimum an Funktionalität beschränkt habe.

Btw. solche OLE Automationen wären viel einfacher, wenn man mittels SWT / OLE VBA Makros generieren / ausführen könnte, dann würde ein simples:
Visual Basic:
Option Explicit
Function add_appointment_category(CategoryName As String) As Integer
    Dim cat As Outlook.Category

        
    For Each cat In ThisOutlookSession.Session.Categories
        If Trim(UCase(cat.Name)) = Trim(UCase(CategoryName)) Then
            'OlCategoryColor
            ' http://msdn.microsoft.com/en-us/library/office/ff864208.aspx
            add_appointment_category = -1
            Exit Function
        End If
    Next cat
    
    
    ThisOutlookSession.Session.Categories.Add (CategoryName) ' ... color ... shortcut key
    
    add_appointment_category = 0
End Function

Sub test()
    MsgBox add_appointment_category("test123")
End Sub
reichen...

Java:
package de.tutorials.training.swt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

class Demo {
  private static final String REGEX_QUOTED_STRING_ARGUMENT = "^'.*'$";
  private static final String REGEX_EXTRACT_FUNCTION_ARGUMENTS = ".*\\((.*)\\).*";


  void run() {
    Display display = new Display();
    Shell shell = new Shell(display);
    OleFrame frm = new OleFrame(shell, SWT.NONE);
    OleClientSite site = new OleClientSite(frm, SWT.NONE, "Outlook.Application");
    site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
    OleAutomation auto = new OleAutomation(site);

    addNewOutlookCategory(auto, "test1234");

    while (!display.readAndDispatch()) {
      display.sleep();
    }

    shell.dispose();
  }


  private void addNewOutlookCategory(OleAutomation auto, String newCategoryName) {
    Variant categories = evalPropertyPathExpression(auto, "GetNamespace('MAPI').Categories");
    if (!isCategoryNameAlreadyTaken(newCategoryName, categories)) {
      Variant result = evalPropertyPathExpression(categories.getAutomation(), "Add('" + newCategoryName + "')"); // ...color,
                                                                                                                 // shortcut
                                                                                                                 // keys...
      System.out.println("Added new category: " + newCategoryName + " -> " + result);
    } else {
      System.err.println("Could not create category:" + newCategoryName + " name is already taken!");
    }
  }


  private boolean isCategoryNameAlreadyTaken(String newCategoryName, Variant categories) {
    boolean categoryNameAlreadyTaken = false;
    Variant categoriesCount = evalPropertyPathExpression(categories.getAutomation(), "Count");
    for (int i = 0; i < categoriesCount.getInt(); i++) {
      Variant category = evalPropertyPathExpression(categories.getAutomation(), "Item(" + (i + 1) + ")");
      Variant categoryName = evalPropertyPathExpression(category.getAutomation(), "Name");
      categoryNameAlreadyTaken = categoryName.getString().trim().toUpperCase()
        .equals(newCategoryName.trim().toUpperCase());
      if (categoryNameAlreadyTaken) {
        break;
      }
    }
    return categoryNameAlreadyTaken;
  }


  private Variant evalPropertyPathExpression(OleAutomation auto, String propertyPath) {
    Variant result = null;
    OleAutomation currentAuto = auto;

    String[] propertyPathElements = propertyPath.split("\\.");
    for (int i = 0; i < propertyPathElements.length; i++) {
      String propertyPathElement = propertyPathElements[i];

      if (isFunctionExpression(propertyPathElement)) {
        result = evalFunctionExpression(currentAuto, propertyPathElement);
      } else {
        result = evalPropertyExpression(currentAuto, propertyPathElement);
      }

      if (result != null && result.getType() == OLE.VT_DISPATCH) {
        currentAuto = result.getAutomation();
      }
    }

    return result;
  }


  private Variant evalPropertyExpression(OleAutomation currentAuto, String propertyPathElement) {
    String propertyName = propertyPathElement;
    int propertyId = getIdForName(currentAuto, propertyName);
    Variant result = currentAuto.getProperty(propertyId);
    return result;
  }


  private Variant evalFunctionExpression(OleAutomation currentAuto, String propertyPathElement) {
    String propertyName = propertyPathElement.substring(0, propertyPathElement.indexOf('('));
    int propertyId = getIdForName(currentAuto, propertyName);
    String argsString = propertyPathElement.replaceAll(REGEX_EXTRACT_FUNCTION_ARGUMENTS, "$1");
    Object[] args = convertArgsStringToObjectArgs(argsString);
    Variant[] varArgs = convertObjectArgsToVariantArgs(args);
    Variant result = currentAuto.invoke(propertyId, varArgs);
    return result;
  }


  private Object[] convertArgsStringToObjectArgs(String argsString) {
    String[] argsStrings = argsString.split(",");
    Object[] args = null;
    if (argsStrings.length > 0) {
      args = new Object[argsStrings.length];
      for (int a = 0; a < argsStrings.length; a++) {
        String argValue = argsStrings[a].trim();
        if (argValue.matches(REGEX_QUOTED_STRING_ARGUMENT)) {
          args[a] = argValue.substring(1, argValue.length() - 1);
        } else {
          args[a] = Integer.valueOf(argValue);
        }
      }
    }
    return args;
  }


  private Variant[] convertObjectArgsToVariantArgs(Object[] args) {
    Variant[] varArgs = new Variant[args.length];
    for (int v = 0; v < varArgs.length; v++) {
      varArgs[v] = args[v] instanceof String ? new Variant((String) args[v]) : new Variant((Integer) args[v]);
    }
    return varArgs;
  }


  private boolean isFunctionExpression(String propertyPathElement) {
    return propertyPathElement.matches(".*\\(.*\\).*");
  }


  int getIdForName(OleAutomation auto, String name) {
    int[] ids = auto.getIDsOfNames(new String[] { name });
    return ids[0];
  }
}


public class AddOutlookAppointmentCategoriesViaOLEExample {
  public static void main(String[] args) {
    new Demo().run();
  }
}

Gruß Tom
 

Bakalit

Grünschnabel
Hallo Tom

Vielen Dank für deine Hilfe.

Das Erstellen der Kategorien funktioniert bestens. Allerdings habe ich nicht herausgefunden (oder kapiert) wie ich die Farbe setzten kann. Outlook erstellt eine neue Kategorie mit dem gewünschten Namen und vergibt irgendeine Farbe. Alles was ich bisher versucht habe hat entweder eine Exception bei
Code:
int getIdForName(OleAutomation auto, String name) {
    int[] ids = auto.getIDsOfNames(new String[] { name });
    return ids[0];
  }
geworfen oder eine neue Kategorie mit der Farbe als Name erstellt :suspekt:. Die Farbe selbst wurde wieder durch OL vergeben.

Kannst du mir ein Beispiel geben wie ich den Namen und die Farbe setzten kann?

Besten Dank und Gruss
Tobi
 

Bakalit

Grünschnabel
Hallo zusammen

Brauche mal wieder Hilfe. Das erstellen der Kategorien in Outlook 07/10 hat bestens geklappt. Mit XP und Win7 (32bit) kein Problem. Nun hab ich ne Kiste mit Win7 64Bit und da geht nix mehr. Die Exception sagt, dass auf einer 64Bit VM keine 32Bit Klassen geladen werden können. Darauf hin hab ich die aktuelle Version von SWT (64Bit) swt-4.3-win32-win32-x86_64 geladen importiert. Dann kam aber folgender Fehler bei dem ich einfach nicht weiter komme:

Java:
org.eclipse.swt.SWTException: Failed to create Ole Client. result = -2147221164
    at org.eclipse.swt.ole.win32.OLE.error(Unknown Source)
    at org.eclipse.swt.ole.win32.OleClientSite.<init>(Unknown Source)
    at Outlook_Category.CategoryHandler.addNewOutlookCategories(CategoryHandler.java:34)
    at TourCatalogue.TourCatalogue.setCategories(TourCatalogue.java:160)
    at TourCatalogue.TourCatalogue.<init>(TourCatalogue.java:70)
    at tp_001_prototype.GUI.TourSync.<init>(TourSync.java:451)
    at tp_001_prototype.Main.main(Main.java:52)
Exception in thread "main" java.lang.NullPointerException
    at tp_001_prototype.GUI.TourSync.saveLogToFile(TourSync.java:601)
    at tp_001_prototype.GUI.TourSync.<init>(TourSync.java:510)
    at tp_001_prototype.Main.main(Main.java:52)

Mit Nachforschung bin ich dann darauf gestossen, dass der Fehler -2147221164 darauf hindeutet, dass sich die Klassen nicht richtig registriert haben.

Weiss da jemand weiter?

Hier noch der Code der den Fehler wirft:

Java:
package Outlook_Category;
 
import java.io.Serializable;
import java.util.ArrayList;
 
import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.ole.win32.COM;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
 
/**
*
* @author Administrator
*/
public class CategoryHandler implements Serializable{
 
  private static final String REGEX_QUOTED_STRING_ARGUMENT = "^'.*'$";
  private static final String REGEX_EXTRACT_FUNCTION_ARGUMENTS = ".*\\((.*)\\).*";
  private int mStatus;
 
  public CategoryHandler() {
  }
 
  public void addNewOutlookCategories(ArrayList<Category> pCategories) {
 
    Display display = new Display();
    Shell shell = new Shell(display);
    OleFrame frm = new OleFrame(shell, SWT.NONE);
    OleClientSite site = new OleClientSite(frm, SWT.NONE, "Outlook.Application.14");
    site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
    OleAutomation auto = new OleAutomation(site);

Vieleicht sollte ich noch erwähnen, dass meine SW auf mehreren Geschäftsrechner läuft (die eben allen durch 64Bit Maschinen ersetzt wurden) und daher bin ich, was zusätzliche SW angeht, sehr eingeschränkt. Allerdings ist REGEDIT offen (wer versteht schon die Philosophie von unsere IT-Security??).

Besten Dank schon mal im Voraus.
 
Zuletzt bearbeitet: