这篇文章主要讲述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
2177

被折叠的 条评论
为什么被折叠?



