共计 5759 个字符,预计需要花费 15 分钟才能阅读完成。
浏览本文大略须要 6 分钟
日常开发软件可能会遇到这类小众需要,导出数据到 Word
、Excel
以及 PDF
文件,如果你应用 C++
编程语言,那么能够抉择的计划不是很多,恰好最近刚好有这部分需要,整顿下这段时间踩过的坑,不便前人
读写 Word
日常开发的软件应用最多的应该是导出数据到 Word
文档中,目前能够用的计划有这几种
没有美中不足的计划,任何计划都存在长处和毛病,上面来具体看下这几种计划的优缺点以及实用场景
XML 模板替换
原理:当时编辑好一份
Word
模板,须要替换内容的
中央预留好地位,而后应用非凡字段进行标记,前面应用代码进行全量替换即可实现
长处
- 代码量绝对较少、导出速度快
- 跨平台,反对多个零碎,零碎不装置 office 也能导出;
- 反对图片以及固定格局导出;
毛病
- 导出格局固定,可扩展性不强,如果需要变动导出格局变了,那么模板也要跟着扭转;
- 一种格局对应一份模板,如果导出格局较多,须要筹备的模板文件较多,这样比拟繁琐;
- 须要
Word
2003 以上版本;
举个栗子
咱们先编辑一份 Word
模板文档,内容大略如下所示:
- 将该文档另存为
Word XML
文档XML-Template.xml
- 读取文档内容进行变量替换
QFile file("XML-Template.xml");
if (!file.open(QIODevice::ReadOnly))
{qDebug() << "open xxml file fail." << file.errorString();
return 0;
}
QByteArray baContent = file.readAll();
file.close();
QString strAllContent = QString::fromLocal8Bit(baContent);
strAllContent.replace("$VALUE0", "1");
strAllContent.replace("$VALUE1", QString::fromLocal8Bit("法外狂徒张三"));
strAllContent.replace("$VALUE2", QString::fromLocal8Bit("考试不合格"));
strAllContent.replace("$VALUE3", "2");
strAllContent.replace("$VALUE4", QString::fromLocal8Bit("李四"));
strAllContent.replace("$VALUE5", QString::fromLocal8Bit("合格"));
QFile newFile("export.doc");
if (!newFile.open(QIODevice::WriteOnly))
{qDebug() << "file open fail." << newFile.errorString();;
return 0;
}
newFile.write(strAllContent.toLocal8Bit());
newFile.close();
- 保留替换后的内容, 写入文件
能够看进去这种形式比拟繁琐,重点是编辑固定的模板格局,而且编辑好后保留成 XML
格局后还须要持续调整,这种 XML
格局标签很多,不小心就批改错了,导致导出的文档打不开
这种形式适宜模板内容不太简单,内容较少的状况下应用
COM 组件形式
原理:采纳
Micro Soft
公开的接口进行通信,进行读写时会关上一个 `Word 过程来交互
COM 技术概述
Qt
为咱们提供了专门进行交互的类和接口,应用 Qt ActiveX
框架就能够很好的实现交互工作
长处
- 实现简略,疾速上手;
毛病
- 导出写入速度慢,因为相当于关上 word 文档操作;
- 仅
Windows
平台可用,其它平台生效; - 须要程序运行的电脑装置 office word,否则调用失败
举个栗子
应用时须要引入对应的模块,在 pro
文件引入模块
QT *= axcontainer
打开文档写入内容
QAxObject *pWordWidget = new(std::nothrow) QAxObject;
bool bResult = pWordWidget->setControl("word.Application");
if (!bResult)
{return false;}
// 设置是否显示
pWordWidget->setProperty("Visible", false);
QAxObject *pAllDocuments = pWordWidget->querySubObject("Documents");
if(nullptr == pAllDocuments)
{return false;}
// 新建一个空白文档
pAllDocuments->dynamicCall("Add (void)");
// 获取激活的文档并应用
QAxObject *pActiveDocument = pAllDocuments->querySubObject("ActiveDocument");
if(nullptr == pActiveDocument)
{return false;}
// 插入字符串
QAxObject *pSelectObj = pWordWidget->querySubObject("Selection");
if (nullptr != pSelectObj)
{pSelectObj->dynamicCall("TypeText(const QString&)", "公众号:devstone");
}
……
能够看进去应用起来不难,对于老手敌对一点,很多写入操作方法比拟繁琐,须要本人从新封装一套接口
- 这种计划比拟适宜那些排版比较复杂,图片、文字、表格混排的场景下,而且内容都是动态变化的,能够很好的实现定制化
- 当然了它的毛病也不少,也有一些坑,有时候莫名其妙会失败,还有就是比方你电脑装置的
Word
没有激活,那么每次启动会弹激活窗口 - 还有就是这种形式要求所有的门路必须是本地化的,比方
D:\\Soft\test.png
- 应用前最好读取注册表判断以后电脑是否装置了
Office Word
,如果没有装置,间接读取操作必定会解体
这种形式同样实用于写入 Excel
文件,前面再说
HTML 形式
原理:这种形式得益于
Word
反对 HTML 格局导出渲染显示,那么反向也能够反对,须要咱们拼接HTML
格局内容,而后写入文件保留成.doc
格局
长处
- 跨平台,不仅限于
Windows
平台,代码可扩展性比拟好 - 导出速度快、代码可扩大;
毛病
- 字符串拼接
HTML
容易出错,缺失标签导出后无奈显示; - 插入的图片是本地图片文件的链接,导出的 word 文档拷贝到其它电脑图片无奈显示
举个栗子
QString HTML2Word::getHtmlContent()
{
QString strHtml = "";
strHtml += "<html>";
strHtml += "<head>";
strHtml += "<title> 测试生成 word 文档 </title>";
strHtml += "<head>";
strHtml += "<body style=\"bgcolor:yellow\">";
strHtml += "<h1 style=\"background-color:red\"> 测试 qt 实现生成 word 文档 </h1>";
strHtml += "<hr>";
strHtml += "<p> 这里是插入图片 <img src=\"D:\\title.jpg"alt=\"picture\"width=\"100\"height=\"100\"></p>";
strHtml += "</hr>";
strHtml += "</body>";
strHtml += "</html>";
return strHtml;
}
// 保留写入文件
QFile file("D:/htmp2Word.doc");
if (!file.open(QIODevice::WriteOnly))
{return false;}
QTextStream out(&file);
out << getHtmlContent();
file.close();
这种形式难点在于 HTML
格局拼接,任何缺失字段都会导致导出失败,适宜小众需要下导出
图片问题其实能够手动进行转化,文档导出胜利后手动拷贝内容到新的文档,这样图片就真正插入到文档中,文档发送给他人也不会失落图片了
还有一个坑就是:如果你应用 WPS
关上导出的文档,默认显示的是 web
视图,须要手动进行调整
某些电脑分辨率变动也会导致生成的文档中字体等产生变动
第三方开源库
能够应用的第三方库简直没有,网络上找到的有这么几个
- OpenOffice: 兼容性差,集成调用难度大
- LibOffice: 太宏大,不容易集成
- DuckX:太小众,只能简略的应用
- docx:小众库
DuckX 库
docx 库
在读写 Word
这部分,C++
根本没有能够应用的第三方库,不像其余语言 Java
、C#
、Python
有很多能够抉择,这个苦楚也只有 C++
程序员可能了解了吧
所以怎么抉择还是看本人我的项目需要吧,没有美中不足的计划
下面说了这么多,都是导出生成 Wrod
,那么上面来看看有那些形式能够读取显示 Word
内容
这种需要应该不会很多,而且显示难度更大一些
应用 COM
组件形式,即采纳 QAxWidget
框架显示 `
office 文档内容,实质上就是在咱们编写的
Qt 界面上嵌入
office 的软件,这种形式其实和间接关上
Word` 查看没有啥区别,成果、性能上不如间接关上更好一些
目前个别都会采纳折中计划,把 Word
转为 PDF
进行预览加载显示,咱们晓得 PDF
渲染库比拟多,生态相对来说要好一些,在抉择上就更宽泛些,如何应用前面局部有专门介绍 PDF
章节
读写 Excel
目前有一个反对比拟好的第三方库能够应用,整体应用根本能够满足日常应用
QXlsx
这款开源库反对跨平台,Linux、Windows、Mac、IOS、Android,应用形式反对动静库调用和源码间接集成,十分不便
编译反对 qmake
和cmake
,能够依据你本人的我的项目间接集成编译,读写速度十分快
QXlsx::Document xlsx;
// 设置一些款式
QXlsx::Format titleFormat;
titleFormat.setBorderStyle(QXlsx::Format::BorderThin); // 边框款式
titleFormat.setRowHeight(1,1,30); // 设置行高
titleFormat.setHorizontalAlignment(QXlsx::Format::AlignHCenter); // 设置对齐形式
// 插入文本
xlsx.write(1,1, "微信公众号:devstone", titleFormat);
// 合并单元格
xlsx.mergeCells(QXlsx::CellRange(2,1,4,4), titleFormat);
// 导出保留
xlsx.saveAs("D:/xlsx_export.xlsx");
// 增加工作表
xlsx.addSheet("devstone");
能够看到上手非常容易、各个函数命名也贴近 Qt Api
,是一款十分良心的开源软件
PS: 留神该软件应用
MIT
许可协定,这样对于很多集体或者公司来说十分良心,意味着你能够无偿应用、批改该我的项目,然而必须在你我的项目中也增加同样的MIP
许可
下面也提到了,还能够应用 COM
组件的形式读写 Excel
,不过有了这款开源库根本就能够辞别 COM
组件形式了
读写 PDF
PDF
相干开源库挺多的,给了 C++
程序员莫大的帮忙,目前可用的次要有这些
其中 mupdf
和 poppler
属于功能强大然而很难编译的那种,须要有扎实的三方库编译能力,否则面对 n
个依赖库会无从下手
不过可喜的是 Github
上有两个开源库能够供选择
qpdf 库
这个库其实封装了 pdf.js
库,应用 WebEngine
来执行 JavaScript
进而加载文件
我的项目地址
- 间接从本地文件加载;
- 反对从内存数据间接加载渲染 PDF 内容;
这种形式对环境有特殊要求了,如果你的我的项目应用的 Qt
版本不反对 WebEngine
,那么就无奈应用
qtpdf 库
这个库是 Qt
官网亲自操刀对第三方库进行了封装,裸露的 API
和 Qt
相似,应用起来十分难受
Qt 官网
代码构造以及应用 Demo
小试牛刀
对于如何应用,官网曾经给了咱们十分具体的步骤了,间接跟着上面几步就 OK 了
官网教程
git clone git://code.qt.io/qt-labs/qtpdf
cd qtpdf
git submodule update --init --recursive
qmake
make
cd examples/pdf/pdfviewer
qmake
make
./pdfviewer /path/to/my/file.pdf
能够看到应用了谷歌开源的 pdfium
三方库,编译时须要独自更新下载这个库,因为某些起因可能你无奈下载,不过好在有人在 GitHub
上同步了这个仓库的镜像,有条件还是倡议间接下载最新稳定版的
可失常拜访的仓库地址:https://github.com/PDFium/PDFium
相干类能够看这个文档:https://developers.foxit.com/…
最初还要留神我的项目开源协定:pdfium 引擎开始来自于福昕,一个中国外乡的软件公司,Google 与其单干最终进行了开源,目前采纳的是
BSD 3-Clause
协定, 这种协定容许开发者自在应用、批改源代码,也能够批改后从新公布,容许闭源进行商业行为,不过须要你在公布的产品中蕴含原作者代码中的BSD
协定
总结
以上就是我的项目中罕用的文档解决办法总结,当然了必定也还有其它计划能够实现,毕竟条条大路通罗马,如果你还要不错的计划和倡议欢送留言
PS: 以上计划和对应的源码编译、应用例子会对立上传到 GitHub
对应的仓库,不便前人应用
取之互联网、回报互联网
原创不易,如果感觉对你有帮忙,欢送点赞、在看、转发
举荐浏览
- Qt Creator 源码学习笔记 01,初识 QTC
- Qt Creator 源码学习笔记 02,意识框架结构构造
- Qt Creator 源码学习笔记 03,大型项目如何治理工程
- Qt Creator 源码学习笔记 04,多插件实现原理剖析
- Qt Creator 源码学习笔记 05,菜单栏是怎么实现插件化的?