OLE-Automation mit ClassiX®
- Eine fremde Anwendung programmieren
- COM-Objekte in ClassiX®
- Collections und Objekte
- Events
- Arrays
- Konstanten
- Optionale Parameter
- Performance
- Anhang
ClassiX® bietet die Möglichkeit, über OLE-Automation externe Anwendungen zu steuern und zu programmieren. Im Folgenden werden speziell die Office Produkte von Microsoft betrachtet. Wer schon einmal Visual Basic programmiert hat, wird auch keine Schwierigkeiten haben, dies in InstantView® zu tun. Wichtigstes Hilfsmittel ist der von den Microsoft Anwendungen angebotene Objektkatalog. Ihn erreicht man innerhalb der Anwendung nach drücken von Alt+F11 unter ‚Ansicht’ > ‚Objektkatalog’. Er listet in dem linken Fenster alle Klassen und Enumerationen der gewählten Anwendung. Wenn man eine anklickt, zeigt er im rechten Fenster die enthaltenen Methoden, Attribute und Events sowie unten eine kurze Syntaxerläuterung mit Beschreibung. Per Kontextmenu erreicht man auch die ausführliche Hilfe.
Eine fremde Anwendung programmieren
Die Herangehensweise zur Programmierung einer fremden Anwendung beinhaltet als erstes das Verstehen dieser Anwendung. Dies geht am besten, in dem man versucht, das Objektmodell der Anwendung zu verstehen. Hierbei hilft der Objektkatalog oder Literatur, wie z.B. 1. sowie das Internet, siehe 2. Informationen zur VB Programmierung von Office 2000 findet man unter 3.
Abb. 1 Der Objektkatalog von Microsoft Word im VB(A)-Editor
Um mit der Programmierung zu beginnen, muss man den Namen einer Ausgangsklasse in Erfahrung bringen. Alle Office Anwendungen bieten die Klasse ‚Application’ an, welche zur Programmierung der Anwendung selbst dient. Dazu gibt es dann noch Klassen für die entsprechenden Dokumente, z.B. Word.Document oder Excel.Sheet. Alle diese Klassenname kann man auch in der Windows Registry unter dem Schlüssel ‚HKEY_CLASSES_ROOT’ nachgucken, hier sind alle im System registrierten Anwendungen und Dateitypen aufgelistet. Alle direkt zugänglichen Klassen von Word findet man z.B. unter Word.*, wobei der Stern für den Klassennamen steht. Um z. B. ein Word-Dokument zu programmieren, steht die Klasse Word.Document zur Verfügung. Wenn hinter dem Klassennamen noch eine Zahl steht, dann bezeichnet diese die Version, wobei der Eintrag ohne Zahl immer für die aktuellste Version steht.
COM-Objekte in ClassiX®
Mit diesen Informationen kann nun mit der Programmierung begonnen werden. Da alle COM-Objekte in ClassiX® vom Typ CX_COM_OBJECT sind, wird zuerst ein neues Objekt vom Typ CX_COM_OBJECT erstellt. Dieses bietet die Methode CreateFromProgID an, welche die Verbindung mit der Anwendung herstellt. Als Parameter bekommt die Methode den Namen der gewünschten Klasse übergeben.
Beispiel:
CreateTransObject(CX_COM_OBJECT) -> doc
"Word.Document" doc Call(CreateFromProgID)
Der entsprechende Code in VB:
Dim doc As Word.Document
Set doc = CreateObject("Word.Document")
Nun repräsentiert das Objekt doc die Klasse Word.Document. Alle Datenfelder und Methoden dieser Klasse können nun benutzt werden. Um eine Methode zu verwenden werden die Parameter auf den Stack gelegt und dann mit Call() die entsprechende Methode aufgerufen:
Beispiel:
Der entsprechende Code in VB:
doc.Compare("C:\Beispiel.doc")Die Werte der Datenfelder werden auf ähnliche Art und Weise gesetzt und ausgelesen. Jeder Datenfeldname wird auf zwei Methoden umgesetzt, einmal mit ‚Put’ und einmal mit ‚Get’ vor dem Datenfeldname. Dieses kann man nun wie jede andere Methode aufrufen:
Beispiel:
doc Call(GetPassword)
Der entsprechende Code in VB:
doc.Password = "geheim"
doc.Password
Hier wird das Datenfeld ‚Password’ erst mal mit ‚PutPassword’ gesetzt und gleich darauf wieder mit ‚GetPassword’ ausgelesen. Auf dem Stack befindet sich jetzt der String „geheim“.
Collections und Objekte
Wenn eine Methode oder ein Datenfeld ein Objekt zurückliefert, dann ist dieses immer vom Typ CX_COM_OBJECT, repräsentiert aber das entsprechende VB Objekt und kann genauso wie jedes normale ClassiX® Objekt verwendet werden.
Falls eine Collection zurückgeliefert wird, dann kann diese auch wie eine Collection unter ClassiX® verwendet werden. Die ‚Iterate’ Anweisung stellt hier das Äquivalent zur ‚For Each ... Next’-Schleife in VB dar.
Beispiel:
1 100 doc Call(Range) Call(Rows)
Iterate
{
Call(GetAlignment) -> Foo
}
Entsprechend in VB:
Dim Foo As Byte
For Each thisRow In doc.Range(1,100).Rows
Foo = ThisRow.Alignment
Next
Diese Anweisungen sind auf jedem Fall einer normalen Schleife mit manuellem Hochzählen eines Index vorzuziehen, da sie kleiner und wesentlich besser zu lesen sind.
Events
Events, welche von der externen Anwendung angeboten werden, können bisher nur in ClassiX® ActiveX-Controls verwendet werden, in normaler OLE-Automation noch nicht.
Arrays
Arrays werden von der ClassiX® COM-Schnittstelle noch nicht unterstüzt. Das bedeutet, dass sowohl aus ClassiX® heraus keine Arrays an Methoden der COM-Objekte übergeben werden können also auch keine Methoden der COM-Objekte aufgerufen werden können, wenn diese Arrays zurückgeben.
Konstanten
Wenn ein Attribut oder eine Methode laut Dokumentation oder Objekt-Explorer eine Konstante zurückliefert, dann kann diese nicht in der Form übernommen werden, da es in InstantView® keine Konstanten gibt. Stattdessen muss der Integer-Wert der Konstanten in InstantView® verwendet werden. Der Wert wird z.B. im Objekt-Explorer angezeigt. Der Lesbarkeit halber kann man den Wert einer Variable zuweisen, die den Namen der Konstanten bekommt, jedoch muss man dann aufpassen, dass diese Variable natürlich veränderbar ist.
Beispiel:
Liefert den Typ des Dokuments (Dokument, Vorlage, ...) als Enum WdDocumentType. In VB ist dies eine Konstante, in InstantView® liegt jetzt ein Integer Wert auf dem Stack den man einer Variable zuweisen kann.
Zum Setzten eines Attributs wird genauso vorgegangen, im Objektkatalog lässt sich der Wert der gewünschten Konstante in Erfahrung bringen und dieser wird dann einfach wie jedes andere Attribut auch, gesetzt.
Beispiel:
und in VB:
doc.Range(1, 100).Case = wdUpperCase
Hier werden im gewählten Bereich (die ersten 100 Zeichen) die Buchstaben auf Großbuchstaben umgesetzt.
Optionale Parameter
Ein weiterer Unterschied zwischen VB und InstantView® besteht in der Handhabung von Funktions-Parametern. Während VB optionale Parameter unterstützt, welche man nach Belieben weglassen kann, können in InstantView® nur die letzten optionalen Parameter weggelassen werden. Dabei muss darauf geachtet werden, dass nicht aus Versehen auf dem Stack alte Werte liegen, die als Parameter interpretiert werden könnten.
Obwohl die Methode SaveAs diverse Parameter versteht, funktioniert diese InstantView® Anweisung, da der Dateiname der erste erwartete Parameter ist. Hier sollte man jetzt aber darauf achten, dass der Stack leer ist, weil eventuell vorhandene Elemente auf dem Stack als die weiteren Parameter interpretiert werden könnten und man entweder unerwartete Ergebnisse oder eine Fehlermeldung aufgrund eines falschen Typ erhält. Folgende VB Anweisung ist in InstantView® nicht möglich:
Hier bekommt SaveAs neben dem Dateinamen noch ein Passwort, welches zum öffnen des Dokuments benötigt wird. Um diese Anweisung in InstantView® zu realisieren müsste man für alle weggelassenen Parameter die Default-Werte mit übergeben:
Die 0 steht hier für das Speicher Format, welches standardmäßig das Microsoft Word Format ist. Der FALSE Parameter ist der Default-Wert für die Einstellung, ob das Dokument für Kommentare gesperrt sein soll.
Performance
Zum Schluss noch einige Hinweise zur Performance. Jeder Aufruf einer Methode oder setzen bzw. holen eines Attributs kostet Zeit. Dadurch kann längeres Navigieren von einem Objekt zum anderen ziemlich lange dauern. Wenn von dem Zielobjekt aus jetzt zwei Aufrufe gemacht werden sollen, dann ist es wesentlich effizienter, das Objekt einmal in einer Variable zwischenzuspeichern, als jedes Mal wieder von der Ausgangsklasse aus komplett hinzunavigieren.
3 1 100 doc Call(Range) Call(Next) Call(Select)
Ist nicht so effizient wie
Var(next)
3 1 100 doc Call(Range) Call(Next) -> next
next Call(Copy)
next Call(Select)
Dies gilt in VB genauso wie in InstantView®.
Des weiteren sind Variablenzugriffe immer schneller als ein Zugriffsausdruck auf ein Attribut oder eine Methode eines Objektes. Dies macht sich insbesondere in Schleifen bemerkbar, weshalb man hier auf Zugriffsausdrücke verzichten sollte und stattdessen lieber einmal vor der Schleife den Rückgabewert des Zugriffsausdruckes einer Variable zuweisen sollte.
Anhang
Abbildung von VB Typen auf ClassiX®:
Byte, Integer, Long: | Integer |
Single, Double: | CX_NUMERIC |
Currency: | CX_VALUE |
String: | String |
Variant: | Der entsprechende Fix-Typ |
Boolean: | CX_BOOLEAN |
Date: | CX_DATE/CX_TIME/CX_DATETIME |
Object: | CX_COM_OBJECT |
Array: | Wird von ClassiX® noch nicht unterstüzt |
Literatur:
1
Microsoft Office 97 Visual Basic Programmer’s Guide, Microsoft Press, 1997
2
http://www.microsoft.com/technet/treeview/default.asp?ur
3
http://msdn.microsoft.com/library/default.asp?ur