There are already some answers to questions like this one in SO suggesting the usage of QAxObject
with dynamicCall()
for MS Office automation. This can be done, and it will work, but I think that there is a better and more fun way to do it.
My proposal is to import the COM Type Library that comes with each Office application, generating a C++ object model. This has two advantages: is similar to the interop approach that is popular in C# and VB.NET, and even samples for those languages may be used as models for our own Qt projects. And of course, you may enjoy autocompletion in Qt Creator for classes and member names. Did I mention fun already?
This is very similar to the Qutlook Example for the Outlook application that is included among the ActiveQt samples. The documentation doesn't tell much more than adding the TYPELIBS
variable in your application's .pro file. The translation is performed by the dumpcpp.exe
utility that may be found in the Qt bin directory. This is a simple command line program project importing the MS Word object model:
QT += widgets axcontainer
CONFIG += c++11 cmdline
DUMPCPP=$$absolute_path("dumpcpp.exe", $$dirname(QMAKE_QMAKE))
TYPELIBS = $$system($$DUMPCPP -getfile {00020905-0000-0000-C000-000000000046})
isEmpty(TYPELIBS) {
message("Microsoft Word type library not found!")
REQUIRES += MSWord
} else {
SOURCES = main.cpp
}
To discover the GUID of other type libraries, you may use the oleview.exe
utility.
QMake creates a source file MSWORD.cpp
and a header MSWORD.h
that you may include in your own classes to access to the generated object model. This sample generates a Word document from scratch, and saves it in two formats:
#include <QApplication>
#include <QStandardPaths>
#include <QDir>
#include "MSWORD.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Word::Application word;
if (!word.isNull()) {
word.SetVisible(false);
Word::Documents* docs = word.Documents();
Word::Document* newDoc = docs->Add();
Word::Paragraph* p = newDoc->Content()->Paragraphs()->Add();
p->Range()->SetText("Hello Word Document from Qt!");
p->Range()->InsertParagraphAfter();
p->Range()->SetText("That's it!");
QDir outDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
QVariant fileName = outDir.absoluteFilePath("wordaut.docx");
QVariant format = Word::wdFormatXMLDocument;
newDoc->SaveAs2(fileName, format);
QVariant fileName2 = outDir.absoluteFilePath("wordaut2.doc");
QVariant format2 = Word::wdFormatDocument;
newDoc->SaveAs2(fileName2, format2);
newDoc->Close();
word.Quit();
}
return 0;
}
As you can see, the code is quite readable, at the price of including a big chunk of code. You #include
the generated header MSWORD.h
, and the program creates a new document, populates its contents with two text lines, and saves this document twice: first in the modern DOCX format, and then in the DOC format compatible with Word 97/2003.
The complete project can be found in this GitHub repository.