How to read and write docx files in Qt



  • I tried implementing this:

    QFile filein("E:\\QT\\build-untitled-Desktop_Qt_5_7_0_MSVC2015_64bit-Debug\\abc.docx");
        QFile fileout("E:\\QT\\build-untitled-Desktop_Qt_5_7_0_MSVC2015_64bit-Debug\\abc - Copy.docx");
        if(!fileout.open(QFile::WriteOnly | QFile::Text)){
            QMessageBox::warning(this,"title","Out Not Open");
        }
        if(!filein.open(QFile::ReadOnly | QFile::Text)){
            QMessageBox::warning(this,"title","In Not Open");
        }
        QTextStream in(&filein);
        QTextStream out(&fileout);
        QString text = in.readAll();
        out << text;
        filein.flush();
        fileout.flush();
        filein.close();
        fileout.close();
    

    I opened the fileout and it says that the file has been corrupted.
    Is there any other way to read and write docx files in Qt ?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    You are trying to read a binary file as text and then write that text again and it will be again read as binary. That wont work.

    If you just want to copy the file, why not use one of QFile::copy overloads ?



  • @SGaist Actually I'm copying multiple files and put it into one. Is there any way I can do that ?


  • Moderators

    @Dante-Pham You want to combine multiple docx files into one? It is not possible with Qt. It will for sure not work if you just append them, even not in binary mode. You either need a library which understands docx format or you need to write docx parser by yourself.



  • @jsulm Do you know any other platform like Qt that can read and write multiple docx files like what i mentioned ?


  • Moderators

    @Dante-Pham No I don't. Maybe Microsoft provides something? It is their format. And you can take a look at LibreOffice - it can read/write docx.



  • docx is a zip file so you can understand how your method cannot possibly work.
    There is currently no free library in C++ that lets you handle it (a few commercial ones claim to be able to but I never tested them).
    The LibreOffice/OpenOffice code to handle MS office files is too linked to the application to be used easily.
    There's a .Net library that lets you handle them: https://github.com/WordDocX/DocX so you can use it with C++/CLI if you are ok being tied to .Net



  • @VRonin Would you mind telling me exactly how to use this ? I'm not very familiar with .NET.


  • Qt Champions 2016

    @Dante-Pham
    Hi. Even with DocX you will need to understand the actual structure of the document and
    merge it by hand adding text to the target doc.
    There is no tool i have ever seen that can BINARY merge word docs. (only in very old times)
    Also note that DocX only goes to word 2007. Not newer. ( or docs not updated)
    But DocX seems very high level.

    I have never used .NET from c++. Im sure its pretty easy in Visual Studio but cant confirm.

    Can I ask why you want to merge them ?
    Also is it a requirement that your app can do it when no Office installed?



  • @mrjj Basically I'm trying to make a program that can copy lots of small documents and put it into just one file. It's like you have multiple questions and you merge them into just one test.
    Office should always be installed with this program ( except for when it has already been installed )


  • Qt Champions 2016

    Ok. i see.
    Would it be option to do it via pdf or must end result be a doc?

    I did something the same with
    https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
    (the free command line version)
    so made small VBA macro that printed/saved the docs to pdf and then just
    ran tool on it. and got perfect pdf from it.



  • @mrjj Input and Output should be .doc or .docx so that it will be easier for users to modify the files. Changing .doc to .pdf and vice versa is good but doesn't help very much because the core features I intend to implement will, in most cases, involve in working with .doc and .docx


  • Qt Champions 2016

    @Dante-Pham
    Ok. well DocX or something like it seems the way to go then.

    There is also the option of a pure VBA project. But the widgets you
    get there is not as advanced as Qt versions but the merging of docs would
    be easy.



  • @mrjj After doing some research I think DocX may just work. However, I have never had any exprience dealing with .dll files, let alone using it in Qt. Do you have any suggestions on how to use it ?



  • Hallo, I think to understand the binary docx structrue is a very hard stuff.
    Much more easy it would be to use the AcxtiveX interface for word.
    Code something like this:

    Open Doc1, select all text, copy to clipboard, close Doc1
    open Doc2, set cursor to the end of the document, paste text, save doc2.

    The AciteveX interface of Qt is very good and I have much experiences with it. I use it for Excel (fill Tables) and for Access (open Report an export to PDF.

    You can hide the office windows by this task, so that the user sees nothing of you tasks.


  • Qt Champions 2016

    @Dante-Pham
    Hi.
    Using a DLL involves loading it and resolve symbols.
    Meaning to be able to run functions from it.
    You also need a .h file. (didnt see any?)
    You should also get a copy of visual studio as .NET is best/easy/to used from that IDE.
    Then you shall google calling a .net DLL from C++ as there might be other things to look out for.

    Maybe @VRonin knows a easier way to use the .DLL in Qt.

    Update:
    Its available via Nuget
    so it should be easy to install and try the samples directly in VS.
    Then try to mix with Qt.

    Update 2:
    Using VBA, this short code can merge all docs from a folder.

    Sub MergeDocs()
        Dim rng As Range
        Dim MainDoc As Document
        Dim strFile As String, strFolder As String
        Dim Count As Long
        With Application.FileDialog(msoFileDialogFolderPicker)
            .Title = "Pick folder"
            .AllowMultiSelect = False
            If .Show Then
                strFolder = .SelectedItems(1) & Application.PathSeparator
            Else
                Exit Sub
            End If
        End With
        Set MainDoc = Documents.Add
        strFile = Dir$(strFolder & "*.docx") ' can change to .doc
        Count = 0
        Do Until strFile = ""
            Count = Count + 1
            Set rng = MainDoc.Range
            With rng
                .Collapse 0
                If Count > 1 Then
                    .InsertBreak 2
                    .End = MainDoc.Range.End
                    .Collapse 0
                End If
                .InsertFile strFolder & strFile
            End With
            strFile = Dir$()
        Loop
        MsgBox ("Files are merged")
    lbl_Exit:
        Exit Sub
    End Sub
    

    Credits to gmaxey.
    http://www.vbaexpress.com/forum/showthread.php?51797-Macro-to-merge-mulitple-word-doc-into-one-word-doc



  • For what you need to do I'd point you to http://stackoverflow.com/questions/18351829/merge-multiple-word-documents-into-one-open-xml/18352219#18352219

    Using .Net dlls in visual studio is extremely easy, just open the project property and add a reference to the .dll, then right click on the .cpp file you need to use the library in, go into properties and activate /clr in the "Common Language RunTime Support" field under general. Now you can use C++/CLI in it which is quite close to C#



  • @Andy314 I am using ActiveX but i have no idea what functions are used to do what you describe. Would you mind giving me some examples ? How do I copy and paste ? How to hide the window ?



  • @mrjj
    _ DocX only has a .DLL file and a documentation (.chm file) which is very unfinished. Lots of explainations in there are missing. After a while I found myself lost and my code messed up. I tried emailing the guy and he hasn't replied to me yet. Still, I did try adding library into Qt but it only takes .lib files. I found a documentation which show me how to add .dll files but it still didn't work after numerous tries
    _ I don't think Nuget and VBA are going to work for me because I don't know anything about them, which makes it difficult for me to modify and make tweaks to them ( which i am definitely going to ). Still, I have to do more research on them. I will be back very soon


  • Qt Champions 2016

    @Dante-Pham said in How to read and write docx files in Qt:

    Nuget

    That is just a system to easy get a lib for Visual Studio.
    Click and Play , so to speak :)



  • Ok so thanks to @VRonin , I found this https://youtu.be/qOfiiYP2JTI?t=2m11s , in which is pretty much what I'm looking for ! The only problem is I don't know C# . Is there any way we can do that in Qt in C++ ??


  • Qt Champions 2016

    @Dante-Pham
    Well if you know c++ then C# is pretty easy.
    https://msdn.microsoft.com/en-us/library/yyaad03b(v=vs.90).aspx

    I think you can do it almost same way with Visual Studio and c++ but of course the syntax will be
    different.



  • @mrjj Ok I got 5 more days to finish this ... And I have never used visual studio.


  • Qt Champions 2016

    @Dante-Pham
    oh. that might be a bit tight then.
    Im not sure what he use in the video . maybe this ?
    http://www.aspose.com/api/net/words/aspose.words/documentbuilder



  • @Dante-Pham said in How to read and write docx files in Qt:

    Is there any way we can do that in Qt in C++ ??

    As mentioned above you'll need to use a dialec of C++ called C++/CLI.
    You can download visual studio from https://www.visualstudio.com/vs/community/ you can find a crash course in the dialect here: https://www.codeproject.com/articles/19354/quick-c-cli-learn-c-cli-in-less-than-minutes
    Given the name googling it is a nightmare you are better off just googling stuff in C# and either translate it (it's not that hard) or if you go on msdn the examples are often available in C#, VB.Net and more importantly C++/CLI (see for example https://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp)

    @Dante-Pham said in How to read and write docx files in Qt:

    DocX only has a .DLL file and a documentation

    That's all you need, you use #using <DocX.dll> to include it in the source file (that needs to be compiled with the /clr option )

    Here you can find a small example of a qmake project using this paradigm



  • @Dante-Pham

    Why not use QAxObject for MS ActiveX?
    This is the solution you want to use like this:

    QString     outFile("C:/test.docx");
    QString     inFile1("C:/test1.docx");
    QString     inFile2("C:/test2.docx");
    QAxObject   axObject("Word.Application");
    QAxObject   *documents = axObject.querySubObject("Documents");
    QAxObject   *document = documents->querySubObject("Open(const QString&, bool)", inFile1, true);
    QAxObject   *selection = axObject.querySubObject("Selection");
    
    selection->dynamicCall("EndKey(QVariant&)", 6); // WdUnits::wdStory=6
    selection->dynamicCall("InsertBreak(QVariant&)", 7); // WdBreakType::wdPageBreak=7
    selection->dynamicCall("InsertFile(QString&)", inFile2);
    
    document->dynamicCall("SaveAs(const QString&)", outFile);
    document->dynamicCall("Close()");
    axObject.dynamicCall("Quit()");
    
    

    You need a validation check for all pointers!



  • @Devopia53 said in How to read and write docx files in Qt:

    Why not use QAxObject for MS ActiveX

    The main point is that to use activeX you need MS Word installed, if you use an independent library you do not


  • Qt Champions 2016

    Hi
    In posters use case, there will always be word as the users
    will create the input in that application.
    However, @VRonin explanation on how to mix .NET with Qt in Visual studio does
    sound awfully easy and would most likely be the most straightforward as DocX seems
    very high level.
    Time is short however and he never used VS before so might be slightly uphill to get going. :)



  • Just to be clear, MS Word will always be installed along with this app ( if it's not already installed )
    Currently I'm using QAxObject, however, I can't find the functions that i need (most importantly copying, pasting and adding customizable-style-strings) anywhere. Having this will probably solve the whole problem.
    Using Visual Studio to me is very overwhelming. I lost quite a few times using it. I'm familiar with Dev C++ and CodeBlock and they are quite simple.



  • @Devopia53 I'm not sure what youre trying to implement there. I tested it out and the three files didnt change at all. If you know how to copy, paste from one docx to another, add strings using QAxWidget, that would be awesome



  • @Dante-Pham

    The example I provided is simply merging Document1(inFile1) and Document2(inFile2) to create Document3(outFile).

    For more information, check out Microsoft's site.



  • One last thing
    Let's say i have to create a .docx file that has 50 questions and it should look like this:
    Header
    Questions 1: { insert docx to this area }
    Questions 2: { insert docx to this area }
    ...
    Questions 50: { insert docx to this area }
    Footer
    I implemented this code:

        QAxObject   axObject("Word.Application");
        QAxObject   *documents = axObject.querySubObject("Documents");
        QAxObject   *document = documents->querySubObject("Open(const QString&, bool)", Header, true); 
        QAxObject   *selection = axObject.querySubObject("Selection");
        selection->dynamicCall("EndKey(QVarient&)", 6); // WdStoryType::wdStory=6
    for(int i=1; i<=50; i++)
    {
        selection->dynamicCall("InsertFile(QString&)", Questioner); // A .docx file that i created. It's written "Question:" inside of it.
        selection->dynamicCall("InsertFile(QString&)", Question[i]); // Array of .docx files that i created. Works fine.
    }
        selection->dynamicCall("InsertFile(QString&)", Footer); 
        document->dynamicCall("SaveAs(const QString&)", Name);
        document->dynamicCall("Close()");
        axObject.dynamicCall("Quit()");
    

    And it came out like this
    Header
    Questions:
    { insert docx to this area }
    Questions:
    { insert docx to this area }
    ...
    Questions:
    { insert docx to this area }
    Footer
    .
    Is there a way to just insert "Question" + " " char(i+48) + ": ": to the start of every questions that i make ? Additionally, as you can see my output, after every "Question:" it just goes down one line ( i do understand that it's because i insert the file, but i dont know how to fix it ) and i dont want that.



  • Hello @Dante-Pham,
    I have no Qt-Code for Word, in the moment - this was for an other projekt in CPP-Builder for what I had a WrapperClass, but for Access and Excel I made my own tools.

    Obj ist the "Excel.Application" QAxObject*
    void setVisible(bool on=true)
    {
    Obj->setProperty("Visible", on);
    }
    I think for the Wordapp it is the same.
    You can generate html-Documentation for a QAxObject
    QString s = Obj->generateDocumentation();
    Here you get a least the function and property names, and an idea what the do. How the really work is detective searching work in the internet. The most matches you get if you look for VBA-Code (Visual-Basic for Application).


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.