Qt/C++操作word文档

这篇文章主要讲述Qt/C++基于Word的xml模板方式操作word文档。具体操作见文末。

在 Qt/C++ 中操作 Word 文档并不是直接支持的功能,因为 Qt 本身并没有专门的库来处理 Microsoft Word 文档格式(如 .docx)。不过,有几种常见的方式可以在 Qt/C++ 中实现对 Word 文档的操作:

1. 使用 QAxObject 操作 Word(仅限 Windows 平台)

在 Windows 平台上,Qt 可以通过 QAxObject 来使用 Microsoft Office 的 COM 接口进行操作。通过这种方式,你可以自动化 Word 来打开、编辑、保存文档等。

代码示例:使用 QAxObject 打开并编辑 Word 文档
#include <QAxObject>
#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    // 创建Word应用程序对象
    QAxObject* word = new QAxObject("Word.Application");
    word->setProperty("Visible", false); // 隐藏Word应用程序界面

    // 打开Word文档
    QAxObject* documents = word->querySubObject("Documents");
    QAxObject* document = documents->querySubObject("Open(const QString&)", "C:/path/to/your/document.docx");

    if (!document) {
        qDebug() << "Failed to open the Word document!";
        return -1;
    }

    // 获取文档内容并修改
    QAxObject* selection = word->querySubObject("Selection");
    selection->dynamicCall("TypeText(const QString&)", "This is added text by Qt.");

    // 保存文档
    document->dynamicCall("SaveAs(const QString&)", "C:/path/to/your/modified_document.docx");

    // 关闭文档和Word应用程序
    document->dynamicCall("Close()");
    word->dynamicCall("Quit()");

    delete word;

    return a.exec();
}
优点:
  • 可以使用 COM 完整操作 Word 功能,包括编辑文档、插入图片、保存等。
  • 支持 .docx.doc 文件格式。
缺点:
  • 仅限 Windows 平台,因为 COM 是 Windows 专有技术。
  • 需要安装 Microsoft Word 才能工作。
  • 编写代码相对复杂,因为涉及到大量的 COM 操作。

2. 使用外部库(跨平台)

如果需要跨平台操作 Word 文档,或者不想依赖于 Windows 和 Microsoft Word,可以使用一些第三方库。这些库通常支持 .docx 格式(Word 2007+ 的 XML 格式)。

常用的库有:
2.1. libopc:操作 Office Open XML 格式的库
  • 简介libopc 是一个专门用于处理 Open Packaging Conventions (OPC) 文件格式的 C 库,docx 文件使用 OPC 进行存储。你可以使用它来读取和修改 Word 文件的内容(包括文本、图像等)。
  • 优点:跨平台、轻量。
  • 缺点:需要对 OPC 和 .docx 的 XML 结构有一定了解。
2.2. Aspose.Words for C++:跨平台的商业库
  • 简介:Aspose 提供的 Aspose.Words for C++ 库支持跨平台操作 Word 文件。你可以进行文本、图像、表格的添加、修改和删除。
  • 优点:功能强大,支持所有 Word 文档功能。
  • 缺点:这是一个商业库,需要购买许可证。

示例代码(Aspose.Words):

#include <Aspose.Words.Cpp/Document.h>
#include <Aspose.Words.Cpp/DocumentBuilder.h>
#include <system/string.h>

using namespace Aspose::Words;

int main() {
    System::SharedPtr<Document> doc = System::MakeObject<Document>(u"path/to/document.docx");
    System::SharedPtr<DocumentBuilder> builder = System::MakeObject<DocumentBuilder>(doc);
    
    // 在文档中插入文本
    builder->Writeln(u"Hello from Aspose.Words for C++!");

    // 保存文档
    doc->Save(u"path/to/output.docx");

    return 0;
}
2.3. POCO Project:支持 Open XML 格式的库

POCO 是一个 C++ 开发框架,支持文件系统、网络和 XML 操作。它支持处理 docx 文件(因为它们实际上是 ZIP 压缩包,包含 XML 文件和其他资源)。

2.4. Apache POI(针对 C++ 项目可以通过 JNI 调用)
  • 简介Apache POI 是 Java 库,但可以通过 C++ 和 Java JNI 的交互来使用它来操作 Word 文档。
  • 优点:功能全面,免费。
  • 缺点:需要使用 JNI,并且是基于 Java 的库。

3.  XML模板标签替换

优点
1、代码量相对较少、导出速度快
2、跨平台,支持多个系统,系统不安装 office 也能导出;
3、支持图片以及固定格式导出;
缺点
1、导出格式固定,可扩展性不强,如果需求变化导出格式变了,那么模板也要跟着改变;
2、一种格式对应一份模板,如果导出格式较多,需要准备的模板文件较多,这样比较繁琐;
3、需要 Word 2003 以上版本;

下面演示普通文本替换、图片替换。

使用方法

   1、做好一份word模板,另存为word xml格式。

        

                

                

        

如上图:$VALUE0、1、2、3、4、5是事先预留的占位符。
/word/media/image1.jpeg、/word/media/image2.jpeg是事先插入的两张图片,图片会被以二进制的方法进行写入到xml中,“...”是图片Base64编码数据。

采用qt读取文件并替换预留的占位符,通过唯一标识符替换图片Base64编码数据。代码如下

            // 1. 打开 XML 格式的 Word 模板
            QString templatePath = "/test-1.xml"; // Word 另存为 XML 格式的文件路径
            QFile file(templatePath);
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                qDebug() << "Failed to open the template file:" << file.errorString();
            }

            // 2. 读取 XML 文件内容
            QTextStream in(&file);
            in.setCodec("UTF-8"); // 确保正确处理 UTF-8 编码
            QString xmlContent = in.readAll();
            file.close();

            xmlContent.replace("$VALUE0", "1");
            xmlContent.replace("$VALUE1", QString::fromLocal8Bit("张三"));
            xmlContent.replace("$VALUE2", QString::fromLocal8Bit("不合格"));
            xmlContent.replace("$VALUE3", "2");
            xmlContent.replace("$VALUE4", QString::fromLocal8Bit("王五"));
            xmlContent.replace("$VALUE5", QString::fromLocal8Bit("合格"));

            // 3. 加载图片并转为 Base64 编码
            QMap<QString, QString> imageMap;
            QString imagePath1 = "test1.png";
            QString imagePath2 = "test2.png";
            //将第一张图片编码为Base64
            QImage image1;
            if (image1.load(imagePath1)) {
                QByteArray ba1;
                QBuffer buffer1(&ba1);
                image1.save(&buffer1, "PNG");
                QString base64Image1 = ba1.toBase64();
                imageMap["/word/media/image1.jpeg"] = base64Image1; //保存Base64数据,键为图片路径
            }

            //将第二张图片编码为Base64
            QImage image2;
            if (image2.load(imagePath2)) {
                QByteArray ba2;
                QBuffer buffer2(&ba2);
                image2.save(&buffer2, "PNG");
                QString base64Image2 = ba2.toBase64();
                imageMap["/word/media/image2.jpeg"] = base64Image2; //保存Base64数据,键为图片路径
            }

            QString binaryDataStart  = "<pkg:binaryData>";
            QString binaryDataEnd  = "</pkg:binaryData>";

            QMapIterator<QString, QString> it(imageMap);
            while (it.hasNext()) {
                it.next();
                QString imagePath = it.key();   // "/word/media/image1.jpeg" 或 "/word/media/image2.jpeg"
                QString newBase64 = it.value(); // 新的base64数据

                // 找到匹配图片路径的<pkg:part>标签
                QString nameTag = QString("pkg:name=\"%1\"").arg(imagePath);
                int nameIndex = 0;

                // 查找该图片路径在xmlContent中的位置
                if ((nameIndex = xmlContent.indexOf(nameTag)) != -1) {
                    // 找到该图片的 <pkg:binaryData> 标签
                    int startIndex = xmlContent.indexOf(binaryDataStart , nameIndex);
                    int endIndex = xmlContent.indexOf(binaryDataEnd , startIndex);

                    if (startIndex != -1 && endIndex != -1) {
                        startIndex += binaryDataStart.length();

                        // 提取旧的Base64数据
                        QString oldBase64 = xmlContent.mid(startIndex, endIndex - startIndex);

                        // 将旧Base64替换为新Base64
                        xmlContent.replace(oldBase64, newBase64);
                    } else {
                        qDebug() << "Could not find <pkg:binaryData> tags for image path:" << imagePath;
                    }
                }
            }

            // 5. 保存修改后的 XML 内容到新文件
            QString outputPath = "output.xml"; // 另存为的文件路径
            QFile outFile(outputPath);
            if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
                qDebug() << "Failed to open the output file:" << outFile.errorString();
            }
            QTextStream out(&outFile);
            out.setCodec("UTF-8");
            out << xmlContent;
            outFile.close();

替换后的xml

替换后的xml文件以word的方式打开


             

          
参考链接:https://blog.csdn.net/qq_16758589/article/details/137920602

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值