“
阅读本文大概需要6分钟
日常开发软件可能会遇到这类小众需求,导出数据到Word、Excel以及PDF文件,如果你使用C++编程语言,那么可以选择的方案不是很多,恰好最近刚好有这部分需求,整理下这段时间踩过的坑,方便后人
读写Word日常开发的软件使用最多的应该是导出数据到Word文档中,目前可以用的方案有这几种
没有十全十美的方案,任何方案都存在优点和缺点,下面来详细看下这几种方案的优缺点以及适用场景
XML模板替换“原理:事先编辑好一份Word模板,需要替换内容的地方预留好位置,然后使用特殊字段进行标记,后面使用代码进行全量替换即可完成
优点代码量相对较少、导出速度快跨平台,支持多个系统,系统不安装office也能导出;支持图片以及固定格式导出;缺点导出格式固定,可扩展性不强,如果需求变化导出格式变了,那么模板也要跟着改变;一种格式对应一份模板,如果导出格式较多,需要准备的模板文件较多,这样比较繁琐;需要Word以上版本;举个栗子我们先编辑一份Word模板文档,内容大概如下所示:
将该文档另存为WordXML文档XML-Template.xml读取文档内容进行变量替换QFilefile("XML-Template.xml");if(!file.open(QIODevice::ReadOnly)){qDebug()"openxxmlfilefail."file.errorString();return0;}QByteArraybaContent=file.readAll();file.close();QStringstrAllContent=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("合格"));QFilenewFile("export.doc");if(!newFile.open(QIODevice::WriteOnly)){qDebug()"fileopenfail."newFile.errorString();;return0;}newFile.write(strAllContent.toLocal8Bit());newFile.close();保存替换后的内容,写入文件
可以看出来这种方式比较繁琐,重点是编辑固定的模板格式,而且编辑好后保存成XML格式后还需要继续调整,这种XML格式标签很多,不小心就修改错了,导致导出的文档打不开
这种方式适合模板内容不太复杂,内容较少的情况下使用
COM组件方式“原理:采用MicroSoft公开的接口进行通讯,进行读写时会打开一个`Word进程来交互
COM技术概述
Qt为我们提供了专门进行交互的类和接口,使用QtActiveX框架就可以很好的完成交互工作
优点实现简单,快速上手;缺点导出写入速度慢,因为相当于打开word文档操作;仅Windows平台可用,其它平台失效;需要程序运行的电脑安装officeword,否则调用失败举个栗子使用时需要引入对应的模块,在pro文件引入模块
QT*=axcontainer
打开文档写入内容
QAxObject*pWordWidget=new(std::nothrow)QAxObject;boolbResult=pWordWidget-setControl("word.Application");if(!bResult){returnfalse;}//设置是否显示pWordWidget-setProperty("Visible",false);QAxObject*pAllDocuments=pWordWidget-querySubObject("Documents");if(nullptr==pAllDocuments){returnfalse;}//新建一个空白文档pAllDocuments-dynamicCall("Add(void)");//获取激活的文档并使用QAxObject*pActiveDocument=pAllDocuments-querySubObject("ActiveDocument");if(nullptr==pActiveDocument){returnfalse;}//插入字符串QAxObject*pSelectObj=pWordWidget-querySubObject("Selection");if(nullptr!=pSelectObj){pSelectObj-dynamicCall("TypeText(constQString)","