[gelöst] OpenOffice COM-Ansteuerung (API?)
-
Hallo,
ich schreibe an einem Programm, welches mir Daten über COM/OLE-Ansteuerung von MS Word bzw. OpenOffice im DOC- bzw. ODF-Format ausgeben soll.
Als Wrapper-Klasse für die COM-Ansteuerung verwende ich die von Jochen Kalmbach ( http://blog.kalmbachnet.de/?postid=63 ).Jedoch gibt die OpenOffice-API für C++ geschweige denn für COM-Ansteuerung wenig Hilfen, wie man von Interface zu Interface bzw. zu Methoden kommt bzw. setzt. Ich habe hier in einem Blog ( http://pn.org/wordpress/?p=18 ) zwar ein paar Grundfunktionen (Öffnen, Speichern,...) gefunden, aber mir ist nicht klar, wie man nach dem Aufrufen der Interfaces auf die Methoden kommt.
Z.B. bekommt man die Writer-Komponente von OpenOffice durch Aufrufen von "createInstance" mit dem Parameter "com.sun.star.frame.Frame". Nach der API von OpenOffice bekomme ich das Modul "frame" ( http://api.openoffice.org/docs/common/ref/com/sun/star/frame/module-ix.html )
Aber wo finde ich dann in der API den darauffolgenden Aufruf für "loadComponentFromURL", ohne explizit das Interface XComponentLoader aufzurufen, was in der COM-Ansteuerung nach diesem Beispiel nicht nötig ist?Und wie bekomme ich nach dem Aufruf von "loadComponentfromURL" die Methode "getText". Nach der API muß ich auch wieder über Interfaces gehen?
Gibt es da irgendwie eine allgemeine Anleitung, wie man sich am besten durch die API "hangelt"? Denn mit den Java-Bsp. oder der direkten UNO-Ansteuerung kann ich da nicht viel anfangen.
Vielen Dank für eure Hilfe.
Gruß,
Tobias
-
Ich verwende folgendes Konstrukt:
IDispatch* TOpenOffice::DispatchMethod(IDispatch* disp, OLECHAR* funcname, DISPPARAMS dispparams, int* okay) { if (!disp || !funcname) { if (okay) *okay = 0; return NULL; } DISPID id_func; disp->GetIDsOfNames(IID_NULL, &funcname, 1, LOCALE_USER_DEFAULT, &id_func); VARIANT result; VariantInit(&result); IDispatch* ret_value = NULL; // Rückgabewert if (disp->Invoke(id_func, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, &result, NULL, 0) == S_OK) { if (okay) *okay = 1; ret_value = result.pdispVal; } else { // Fehler if (okay) *okay = 0; VariantClear(&result); // bei Fehler wird result nicht mehr benötigt } return ret_value; }Wird z.B. folgendermaßen verwendet:
IDispatch* TOpenOffice::GetBookmarks(IDispatch* document) { // holt eine Referenz auf Bookmarks des Dokumentes DISPPARAMS dispparams = {NULL, NULL, 0, 0}; return DispatchMethod(document, L"getBookmarks", dispparams, 0); }Das ist zwar mit wxWidgets geschrieben, funktioniert aber analog auch mit BCB. Vielleicht kannst Du ja damit etwas anfangen.
Rob'
-
Wenn es keine vernünftige Doku gibt, kannst Du versuchen mit OleView.exe (sollte im VS dabei sein), Dir die TLB anzuschauen... dann siehst Du alle Funktionen...
-
BTW: Das COM Interface von Open Office ist eine einzige Katastrophe. Ich habe noch nie ein größeres Chaos gesehen...
-
Hallo,
vielen Dank erst mal für die Hilfe.
Ja, das stimmt, sehr übersichtlich ist die COM-Schnittstelle wirklich nicht, zumal oft nicht ersichtlich ist, welches Interface bei einem Funktionsaufruf zurückkommt.
Jedenfalls habe ich noch Schwierigkeiten mit der Funktion "storeAsURL". Wenn ich sie ausführe, bekomme ich nur die Meldung beim Aufruf von Invoke(...) "In der Anwendung ist ein Fehler aufgetreten, möchten Sie fortfahren?".
Dann setzt die Anwendung fort, beim Beenden von OpenOffice erscheint jedoch die Fehlermeldung R6025: "Pure virtual Function Call". Ist mein Aufruf für storeAsURL evtl. falsch?Hier ist der Aufruf der Funktion. "GetIDsOfNames(...)" funktioniert, "Invoke(...)" jedoch nicht:
VARIANT vdocName; VARIANT vresult; vdocName.vt = VT_BSTR; //vdocName.bstrVal = SysAllocString(RSCom::RSQStringToBSTR(convertToOOURL(docname))); vdocName.bstrVal = SysAllocString(L"file:///C:/Documents/blabla.odt"); VARIANT vstoreParam[1]; VariantInit(&vstoreParam[0]); vstoreParam[0].vt = VT_ARRAY | VT_VARIANT; vstoreParam[0].parray = NULL; if (FAILED(RSCom::Invoke(m_ooDoc, DISPATCH_METHOD, &vresult, NULL, NULL, OLESTR("storeAsURL"), TEXT("vv"), vdocName, vstoreParam))) { return false; }Der Pointer m_ooDoc ist vom Typ LPDISPATCH und wird folgendermaßen aufgerufen:
if (FAILED(RSCom::Invoke(m_ooFrame, DISPATCH_METHOD, &vresult, NULL, NULL, OLESTR("loadComponentfromURL"), TEXT("vvvv"), vfileName, vhowOpen, vsearchWindow, vloadParam[0]))) { return false; } m_ooDoc = V_DISPATCH(&vresult); m_ooDoc->AddRef();Gelöst: versehentlich wurde ein Array statt eines VARIANT übergeben. Jetzt funktioniert es soweit.
Und als zweites: Wo sehe ich in der API, welches Interface mir "LoadComponentFromURL" zurückgibt? Ist es nur ein Interface XComponent oder schon ein XTextDocument? Die Automatisierungsbeispiele, die ich gesehen habe, waren ganz anders aufgebaut, als man es aus der API rauslesen würde.
Vielen Dank schon mal für eure Hilfe.