COM-Bibliothek: Word-Dokument öffnen (IDispatch-Interface)



  • Hallo,

    ich möchte ein bestehendes Word-Dokument öffnen und reinschreiben.

    Ein neues Dokument zu erstellen und dort reinzuschreiben, klappt auch soweit. Möchte ich jedoch ein vorhandenes Dokument öffnen, kann ich leider nicht reinschreiben. Mir sind die Funktionen, die dafür nötig sind, nicht ganz klar.

    Mein Code zur Initialisierung der Word-Komponente.

    //Instanz von Word gestartet, Pointer pAppInt zum IUnknown-Interface von Word (Zugriff auf Funktionen möglich)
       m_officeInstance = ::CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (void**) &m_punknownapp);
    
       //IUnknown-Pointer punknownapp wird auf Dispatch-Pointer pdispapp umgelegt
       m_officeInstance = m_punknownapp->QueryInterface(IID_IDispatch, (void**)&m_pdispapp);
       // --- Zugriff auf das Application Objekt herstellen ---
       //IDispatch* für Dokumenteneigenschaften
       m_szFunction = OLESTR("Documents");
       //Mappen der Argumente des Application Objekts für Invoke
       m_officeInstance = m_pdispapp->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_Docs);
       //Zugriff zu den Methoden herstellen
       m_officeInstance = m_pdispapp->Invoke(m_dispid_Docs, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dpNoArgs, &m_vResult, NULL, NULL);
       //Dokumenteneigenschaften von Invoke über vResult übernehmen
       m_pdispdocs = m_vResult.pdispVal;
    

    Nun versuche ich, auf ein bestehendes Dokument mit "Open" zuzugreifen und mit "TypeText" was reinzuschreiben. Sichern möchte ich es mit "SaveAs", was aber leider nicht klappt.

    Hier der Code dazu:

    //--- lokale Variablen ---
       QString eigeneDateien;
       QString fileNameLoad;
       VARIANT vFileName;
       //DISPPARAMS dpFileOpen;
       DISPPARAMS dpNoArgs = {NULL, NULL, 0, 0};
       BSTR bstr_FileName;
       //testweise mal rausgenommen
       //BSTR bstr_PassWord;
       //nur für Schreibtest
       BSTR bstr_Eingabe;
       VARIANT vArgsTypeText[1];
       DISPPARAMS dpTypeText;
       BSTR bstr_EmptyString;
    
       //TO DO: noch buggy, stürzt ab nach geöffnetem Dokument
       //eigene Dateien: Dateipfad des aktuellen Benutzers
       eigeneDateien = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
       fileNameLoad = QFileDialog::getOpenFileName(0, tr("Dateiname wählen"), eigeneDateien, tr("Dokumente (*.doc)"));
       if (fileNameLoad.length() > 0) {
          bstr_FileName = RSQStringToBSTR(fileNameLoad);
          vFileName.vt = VT_BSTR;
          vFileName.bstrVal = ::SysAllocString(bstr_FileName);
          DISPPARAMS dpFileOpen = {&vFileName, NULL, 1, 0};
          //dpFileOpen.rgvarg = vFileName;
          //dpFileOpen.cNamedArgs = 0;
    
          //--- Zugriff auf Document Objekt herstellen ---
          m_szFunction = OLESTR("Open");
          //Mappen der Argumente des Dokumenten Objekts für Invoke
          m_officeInstance = m_pdispdocs->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_DocsAdd);
          //Zugriff zu den Methoden herstellen
          m_officeInstance = m_pdispdocs->Invoke(m_dispid_DocsAdd, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dpFileOpen, &m_vResult, NULL, NULL);
          m_pdispsel = m_vResult.pdispVal;
    
          //Dokumenteneigenschaften
          m_szFunction = OLESTR("Item");
          m_officeInstance = m_pdispdocs->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_Sel);
          m_officeInstance = m_pdispdocs->Invoke(m_dispid_Sel, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dpFileOpen, &m_vResult, NULL, NULL);
          //m_pdispactivedoc = m_vResult.pdispVal;
    
          //--- Zugriff auf Selection Objekt herstellen ---
          m_szFunction = OLESTR("Selection");
          //Mappen der Argumente des Selection Objekts für Invoke
          m_officeInstance = m_pdispapp->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_Sel);
          //Zugriff zu den Methoden herstellen
          m_officeInstance = m_pdispapp->Invoke(m_dispid_Sel, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dpFileOpen, &m_vResult, NULL, NULL);
          //Argumente von Invoke über m_vResult übernehmen
          //m_pdispactivedoc = m_vResult.pdispVal;
    
          //Aktives Dokument ansteuern
          m_szFunction = OLESTR("ActiveDocument");
          m_officeInstance = m_pdispapp->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_ActiveDoc);
          m_officeInstance = m_pdispapp->Invoke(m_dispid_ActiveDoc, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dpFileOpen, &m_vResult, NULL, NULL);
          m_pdispactivedoc = m_vResult.pdispVal;
    
          //--- Test: Schreiben ins geöffnete Dokument ---
          //DISP_IDs on TypeText und TypeParagraph,
          m_szFunction = OLESTR("TypeText");
          m_officeInstance = m_pdispsel->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_TypeText);
          m_szFunction = OLESTR("TypeParagraph");
          m_officeInstance = m_pdispsel->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_TextPara);
          //TypeTextMethode hat ein Argument - mit VARIANT-Datentyp festlegen
          bstr_Eingabe = SysAllocString(OLESTR("Dokument geladen"));
          vArgsTypeText[0].vt = VT_BSTR;
          vArgsTypeText[0].bstrVal = bstr_Eingabe;
          dpTypeText.cArgs = 1;
          dpTypeText.rgvarg = vArgsTypeText;
          dpTypeText.cNamedArgs = 0;
          bstr_EmptyString = ::SysAllocString(OLESTR(""));
    
          //Texteingabe
          m_officeInstance = m_pdispsel->Invoke(m_dispid_TypeText, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dpTypeText, NULL, NULL, NULL);
          //--- Test Ende ---
    
          //DISPPARAMS erstellen, damit Word-Dokument erstellt werden kann
          VARIANT vArgsSaveAs[11];
          DISPPARAMS dpSaveAs;
          VARIANT vFalse;
          dpSaveAs.cArgs = 11;
          dpSaveAs.cNamedArgs = 0;
          dpSaveAs.rgvarg = vArgsSaveAs;
    
          vFalse.vt = VT_BOOL;
          vFalse.boolVal = FALSE;
    
          //Testdoc
          //String-Conversion
          bstr_Eingabe = RSQStringToBSTR(fileNameLoad);
          //Dateiname
          vArgsSaveAs[10].vt = VT_BSTR;
          vArgsSaveAs[10].bstrVal = bstr_Eingabe;
          //Dateiformat
          vArgsSaveAs[9].vt = VT_I4;
          vArgsSaveAs[9].lVal = 0;
          //keine Kommentare
          vArgsSaveAs[8] = vFalse;
          //evtl. Passwort
          vArgsSaveAs[7].vt = VT_BSTR;
          vArgsSaveAs[7].bstrVal = bstr_EmptyString;
          //zu "Recent Files dazufügen"
          vArgsSaveAs[6].vt = VT_BOOL;
          vArgsSaveAs[6].boolVal = TRUE;
          vArgsSaveAs[5].vt = VT_BSTR;
          //Passwort schreiben
          vArgsSaveAs[5].bstrVal = bstr_EmptyString;
          //ReadOnly
          vArgsSaveAs[4] = vFalse;
          //TrueTypeFormats embedding
          vArgsSaveAs[3] = vFalse;
          //Picture Format
          vArgsSaveAs[2] = vFalse;
          //Save FormsData
          vArgsSaveAs[1] = vFalse;
          //Save as OCE-Letter
          vArgsSaveAs[0] = vFalse;
    
          m_szFunction = OLESTR("SaveAs");
          //Dokument sichern
          m_officeInstance = m_pdispactivedoc->GetIDsOfNames(IID_NULL, &m_szFunction, 1, LOCALE_USER_DEFAULT, &m_dispid_SaveAs);
          m_officeInstance = m_pdispactivedoc->Invoke(m_dispid_SaveAs, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dpSaveAs, &m_vResult, NULL, NULL);
    

    Für Hilfe wäre ich sehr dankbar, da ich leider auch kaum Dokumentation zur Automatisierung von Word finde, habe mich auch schon durchs MSDN gewühlt.

    Gruß,

    Tobias



  • Der Code wird etwas unübersichtlich bei Dir... verwende doch den Wrapper von MS, dann kannst Du fast 1-zu-1 vorhandene VB-Beispiele umsetzen...
    Siehe: http://blog.kalmbachnet.de/?postid=63



  • Hallo,

    vielen Dank für die Wrapper-Klasse, das war sehr hilfreich. Allerdings bekomme ich irgendwie Word noch nicht dazu, ein Dokument zu öffnen und testweise was reinzuschreiben. Word öffnet die Datei gar nicht, welche OLE-Funktion müßte ich noch aufrufen?

    Hier noch mein Code dazu:

    QString eigeneDateien;
       QString fileNameLoad;
    
       eigeneDateien = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
       fileNameLoad = QFileDialog::getOpenFileName(0, tr("Dateiname wählen"), eigeneDateien, tr("Dokumente (*.doc)"));
       BSTR bstr_fileNameLoad = RSQStringToBSTR(fileNameLoad);
    
       Invoke(pdispWord, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("Open"), TEXT("s"), bstr_fileNameLoad);
       Invoke(pdispWord, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("Insert"), TEXT("s"), (LPOLESTR)OLESTR("angefuegt"));
       Invoke(pdispWord, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("FileSaveAs"), TEXT("s"), bstr_fileNameLoad);
    

    Vielen Dank schon mal.

    Gruß,

    Tobias



  • Hallo,

    habe es gelöst, es darf nur die Funktion "FileOpen" sein, weder Item noch anderes darf darauf angewendet werden. Damit funktioniert es.

    @Jochen: Danke für den Link mit den Wrapperklassen, das ist sehr hilfreich.

    Viele Grüße,

    Tobias


Anmelden zum Antworten