阅读本文大概需要 6 分钟

日常开发软件可能会遇到这类小众需求,导出数据到 WordExcel 以及 PDF文件,如果你使用 C++ 编程语言,那么可以选择的方案不是很多,恰好最近刚好有这部分需求,整理下这段时间踩过的坑,方便后人

PS: 目前采用一种通用的、跨平台的方案来代替下面的方便,可能会更好一些,详细可以看下面这篇文章

C++/Qt workd 跨平台、通用

读写 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++ 基本没有可以使用的第三方库,不像其他语言JavaC#Python有很多可以选择,这个痛苦也只有 C++ 程序员能够理解了吧

所以怎么选择还是看自己项目需求吧,没有十全十美的方案


上面说了这么多,都是导出生成 Wrod,那么下面来看看有那些方式可以读取显示 Word内容

这种需求应该不会很多,而且显示难度更大一些

使用 COM组件方式,即采用 QAxWidget框架显示 office 文档内容,本质上就是在我们编写的 Qt 界面上嵌入 office 的软件,这种方式其实和直接打开 Word查看没有啥区别,效果、性能上不如直接打开更好一些

目前一般都会采用折中方案,把 Word 转为 PDF 进行预览加载显示,我们知道 PDF 渲染库比较多,生态相对来说要好一些,在选择上就更广泛些,如何使用后面部分有专门介绍 PDF章节

读写 Excel

目前有一个支持比较好的第三方库可以使用,整体使用基本可以满足日常使用

QXlsx

这款开源库支持跨平台,Linux、Windows、Mac、IOS、Android,使用方式支持动态库调用和源码直接集成,非常方便

编译支持 qmakecmake,可以根据你自己的项目直接集成编译,读写速度非常快

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++ 程序员莫大的帮助,目前可用的主要有这些

其中 mupdfpoppler 属于功能强大但是很难编译的那种,需要有扎实的三方库编译能力,否则面对 n 个依赖库会无从下手

不过可喜的是 Github 上有两个开源库可以供选择

qpdf 库

这个库其实封装了 pdf.js库,使用 WebEngine来执行 JavaScript进而加载文件

项目地址

  • 直接从本地文件加载;
  • 支持从内存数据直接加载渲染 PDF 内容;

这种方式对环境有特殊要求了,如果你的项目使用的 Qt 版本不支持 WebEngine,那么就无法使用

qtpdf 库

这个库是 Qt 官方亲自操刀对第三方库进行了封装,暴露的 APIQt 类似,使用起来非常舒服

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/resources/pdf-sdk/c_api_reference_pdfium/modules.html

最后还要注意项目开源协议:pdfium引擎开始来自于福昕,一个中国本土的软件公司,Google与其合作最终进行了开源,目前采用的是 BSD 3-Clause 协议,这种协议允许开发者自由使用、修改源代码,也可以修改后重新发布,允许闭源进行商业行为,不过需要你在发布的产品中包含原作者代码中的 BSD 协议

总结

以上就是项目中常用的文档处理方法总结,当然了肯定也还有其它方案可以实现,毕竟条条大路通罗马,如果你还要不错的方案和建议欢迎留言

PS: 以上方案和对应的源码编译、使用例子会统一上传到 GitHub对应的仓库,方便后人使用,有需要的可以关注下

取之互联网、回报互联网

推荐阅读

  • Qt Creator 源码学习笔记01,初识QTC
  • Qt Creator 源码学习笔记02,认识框架结构结构
  • Qt Creator 源码学习笔记03,大型项目如何管理工程
  • Qt Creator 源码学习笔记04,多插件实现原理分析
  • Qt Creator 源码学习笔记 05,菜单栏是怎么实现插件化的?

C++(Qt) 和 Word、Excel、PDF 交互总结相关推荐

  1. txt doc rtf html,JAVA读取WORD,EXCEL,PDF,TXT,RTF,HTML文件文本内容的方法示例.docx

    JAVA读取WORD,EXCEL,PDF,TXT,RTF,HTML文件文本内容的方法示例 JAVA读取WORD,EXCEL,PDF,TXT,RTF,HTML文件文本内容的方法示例??2012-06-2 ...

  2. Web方式预览Office/Word/Excel/pdf文件解决方案

    Web方式预览Office/Word/Excel/pdf文件解决方案 参考文章: (1)Web方式预览Office/Word/Excel/pdf文件解决方案 (2)https://www.cnblog ...

  3. java全文检索word中的内容_搜索引擎时对WORD,EXCEL,PDF,POWERPOINT文件全文检索的总结...

    搜索引擎时对WORD,EXCEL,PDF,POWERPOINT文件全文检索的总结 (2012-02-12 16:31:59) 标签: pdf文档 幻灯片 pdf文件 全文检索 控件 it JAVA读取 ...

  4. 在线查看word,excel,pdf文件解决

    眼看着项目要结束,提出新的需求(-_-!!习惯成自然了)需要支持在线查看word,excel,pdf文件,网页中嵌套word的时候,不让word文档占据整个网页,页面内还要有审批等功能,第一感觉想到控 ...

  5. office 文档 在线预览功能实现(word,excel,pdf,ppt等多种格式)——使用https://view.xdocin.com/view 提示文档过期——基础积累

    web实现office文档在线预览功能--基础积累 最近遇到一个需求,就是要实现多种文档链接的在线预览,最简单的方式就是通过window.open(url地址)的方式来实现. 但是如果要求是在一个弹窗 ...

  6. 前端在线预览word,excel,pdf

    前端在线预览word,excel,pdf 预览Word 预览pdf 预览Excel 预览Word 微软的在线预览功能,可以预览word.ppt.Excel.PDF 局限: 需要外网能访问文件,如果是只 ...

  7. java操作word/excel/pdf等文件技术方案

    最近项目中遇到很多对word/excel/pdf等文件的操作,解决方案有好多,开源免费有:利用openoffice组件(需要安装openoffice软件),poi,itext等.也有收费的服务:asp ...

  8. java xpdf 转换成html_java将Word/Excel/PDF文件转换成HTML整理

    项目开发过程中,需求涉及到了各种文档转换为HTML或者网页易显示格式,现在将实现方式整理如下: 一.使用Jacob转换Word,Excel为HTML "JACOB一个Java-COM中间件. ...

  9. Java处理Word, Excel, PDF文档的4种开源系统的代码例子

    原文: http://blog.csdn.net/wzwfly/article/details/1645046   很多人用java进行文档操作时经常会遇到一个问题,就是如何获得word,excel, ...

  10. 使用PageOffice实现文档(word,excel,pdf)在线预览编辑

    最近发现一款不错的插件的PageOffice,地址是:http://www.zhuozhengsoft.com/Technical/ 他可以实现word,excel.pdf在线预览以及在线编辑.虽然商 ...

最新文章

  1. h2 java tcpip_windows下创建h2集群,及java集成详细步骤
  2. Windows 64位下安装Redis超详细教程
  3. 外推主要发布平台(JM)
  4. python小括号( )与中括号 [ ]
  5. 深度学习花书-3.8 期望、方差与协方差
  6. 论文笔记_S2D.73_ICCV2021_单目深度估计的可解释深度网络研究
  7. learn words by steps 8 英语单词
  8. OPNET出错集锦:)
  9. Fabric0.6 与1.0
  10. 使用python批量解压7z格式压缩包
  11. sql大全超详细【转】
  12. 布兰迪斯大学计算机科学专业,美国布兰迪斯大学计算机科学博士专业介绍
  13. 前缀树TrieNode
  14. 跨平台第三方平台登录和单点登录
  15. selenium接管浏览器并配置代理
  16. Introduction1.1:模糊投影几何学
  17. pipconda 搜索包|查看可安装包版本
  18. 穷人家的孩子刘强东又投资了一家AI芯片公司
  19. HJ212-2017 记录
  20. SELinux avc权限--audit2allow

热门文章

  1. 惠普惠特曼:联想收买IBM效劳器将令惠普获益
  2. Java开发真的这么赚钱?连做金融的忍不住转行了
  3. 大数据知识梳理(Hadoop、HDFS)(整理中。。。)
  4. java中6与3等于几_Java(六)
  5. 北斗GPS天线使用中注意的问题
  6. FFmpeg和RTMP结合编译
  7. 读书笔记(八)--多平台IoT
  8. 阿里虚拟主机真的坑!
  9. 网站 服务器 ftp地址,ftp服务器地址 登录ftp服务器的方式
  10. 初学者入门:软件测试从零开始