【问题标题】:How to create docx and doc file with QAxObject in qt for windows?如何在 qt for windows 中使用 QAxObject 创建 docx 和 doc 文件?
【发布时间】:2020-01-15 08:49:37
【问题描述】:

我想使用QAxObject 创建一个新的 docx 文件。如何创建一个新的 docdocx 文件并在 Windows 的 qt 中使用 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()");

【问题讨论】:

  • 您需要澄清您的问题并展示您自己已经尝试过的内容。因为有很多可能的答案,还有很多工作要做。不要写你正在做某事,展示你已经做过的事情并提出更详细的问题。
  • 我想使用 QAxObjectin 创建一个新的 docx 文件。在我发布的链接中,它会打开一个现有文件。
  • 请更新您的问题以获取所有必要信息。如果您要推动每个人访问外部链接,则不受欢迎。第二点,stackoverflow 不是免费编码服务,您需要自行调查您的问题并向社区展示汇总结果。
  • 我更新了我的问题。
  • @DmitrySazonov:我完全理解这个问题:How to use ActiveQt to create a word document from scratch?,而不是打开/阅读现有文档。我找不到单个模板/示例/ 在 SO 或任何其他回答该问题的论坛上的教程,并在此处投票表明其他一些人希望回答这个问题。请重新打开!

标签: c++ qt docx doc


【解决方案1】:

SO 中已经有一些answers 对类似这样的问题提出建议使用QAxObjectdynamicCall() 进行MS Office 自动化。这可以做到,而且会奏效,但我认为有更好、更有趣的方法来做到这一点。

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

这与 ActiveQt 示例中包含的 Outlook 应用程序的Qutlook Example 非常相似。 documentation 并没有比在应用程序的 .pro 文件中添加 TYPELIBS 变量更多。翻译由 Qt bin 目录中的dumpcpp.exe utility 执行。这是一个导入 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 兼容的 DOC 格式/2003.

完整的项目可以在这个GitHub repository找到。

【讨论】:

  • 谢谢你的回答,但你能告诉我如何使用 QAxObject 并发送一个例子吗?
  • 对不起,我一点也不喜欢受苦。
【解决方案2】:
#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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 2016-09-13
    • 1970-01-01
    相关资源
    最近更新 更多