如何在 qt for windows 中使用 QAxObject 创建 docx 和 doc 文件?



我想使用QAxObject创建一个新的 docx 文件。 如何创建一个新的docdocx文件,以及如何在 Windowsqt中使用QAxObject编写文本。我尝试了这段代码,但我找不到答案,因为它打开了现有文件,但我想创建一个新文件并使用QAxObject.

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()");

SO中已经有一些问题的答案,建议将QAxObjectdynamicCall()一起使用用于MS Office自动化。这是可以做到的,而且会奏效,但我认为有一种更好、更有趣的方法可以做到这一点。

我的建议是导入每个 Office 应用程序附带的 COM 类型库,生成一个C++对象模型。这有两个优点:类似于C#和 VB.NET 中流行的互操作方法,甚至这些语言的示例也可以用作我们自己的Qt项目的模型。当然,您可以在Qt Creator中享受类和成员名称的自动完成功能。我已经提到乐趣了吗?

这与 ActiveQt 示例中包含的 Outlook 应用程序的 Qutlook 示例非常相似。该文档只不过是在应用程序的 .pro 文件中添加TYPELIBS变量。翻译由 Qt bin 目录中的dumpcpp.exe实用程序执行。这是一个导入 MS Word 对象模型的简单命令行程序项目:

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
}

若要发现其他类型的库的 GUID,可以使用oleview.exe实用工具。

QMake 创建一个源文件MSWORD.cpp和一个标头MSWORD.h,您可以将其包含在自己的类中,以访问生成的对象模型。此示例从头开始生成一个 Word 文档,并以两种格式保存它:

#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;
}

如您所见,代码非常可读,代价是包含一大块代码。您#include生成的标头MSWORD.h,程序将创建一个新文档,用两行文本填充其内容,并将此文档保存两次:第一次是现代 DOCX 格式,然后是与 Word 97/2003 兼容的 DOC 格式。

完整的项目可以在此 GitHub 存储库中找到。

#if defined(Q_OS_WIN)
else if (mod == "DOCX" || mod == "DOC") {
QTemporaryDir tempDir;
QString text_filename;
QString     outFile;
QString     allMessage;
else if (mod == "DOCX") {
if(tempDir.isValid()){
const QString tempFile = tempDir.path() + "/docxTemplate.docx";
if(QFile::copy(":/docxTemplate.docx",tempFile)){
text_filename = tempFile;
} else {
qDebug()<< "cannot locate docxTemplate.docx";
}
}
else {
qDebug()<< "cannot access filesystem";
}
QString     outFile(pathDirectory+"/"+filename+".docx");
}
else if (mod == "DOC") {
if(tempDir.isValid()){
const QString tempFile = tempDir.path() + "/docTemplate.doc";
if(QFile::copy(":/docTemplate.doc",tempFile)){
text_filename = tempFile;
} else {
qDebug()<< "cannot locate docTemplate.doc";
}
}
else {
qDebug()<< "cannot access filesystem";
}
QString     outFile(pathDirectory+"/"+filename+".doc");
}
QString     inFile(text_filename);
QAxObject   axObject("Word.Application");
QAxObject   *documents = axObject.querySubObject("Documents");
QAxObject   *document = documents->querySubObject("Open(const QString&, bool)", inFile, true);
document->dynamicCall("SaveAs(const QString&)", outFile);
document->dynamicCall("Close()");
axObject.dynamicCall("Quit()");
QAxObject   axObjectNew("Word.Application");
QAxObject   *documentsNew = axObjectNew.querySubObject("Documents");
QAxObject   *documentNew = documentsNew->querySubObject("Open(const QString&, bool)", outFile, true);
QAxObject   *selection = axObjectNew.querySubObject("Selection");
selection->dynamicCall("TypeText(QString)",allMessage);
documentNew->dynamicCall("Close()");
axObjectNew.dynamicCall("Quit()");
}
#endif

最新更新