C++(Qt) 和 Word、Excel、PDF 交互總結(jié)

閱讀本文大概需要 6 分鐘
日常開(kāi)發(fā)軟件可能會(huì)遇到這類(lèi)小眾需求,導(dǎo)出數(shù)據(jù)到 Word
、Excel
以及 PDF
文件,如果你使用 C++
編程語(yǔ)言,那么可以選擇的方案不是很多,恰好最近剛好有這部分需求,整理下這段時(shí)間踩過(guò)的坑,方便后人
讀寫(xiě) Word
日常開(kāi)發(fā)的軟件使用最多的應(yīng)該是導(dǎo)出數(shù)據(jù)到 Word
文檔中,目前可以用的方案有這幾種

沒(méi)有十全十美的方案,任何方案都存在優(yōu)點(diǎn)和缺點(diǎn),下面來(lái)詳細(xì)看下這幾種方案的優(yōu)缺點(diǎn)以及適用場(chǎng)景
XML 模板替換
“原理:事先編輯好一份
Word
模板,需要替換內(nèi)容的 地方預(yù)留好位置,然后使用特殊字段進(jìn)行標(biāo)記,后面使用代碼進(jìn)行全量替換即可完成
優(yōu)點(diǎn)
代碼量相對(duì)較少、導(dǎo)出速度快
跨平臺(tái),支持多個(gè)系統(tǒng),系統(tǒng)不安裝 office 也能導(dǎo)出;
支持圖片以及固定格式導(dǎo)出;
缺點(diǎn)
導(dǎo)出格式固定,可擴(kuò)展性不強(qiáng),如果需求變化導(dǎo)出格式變了,那么模板也要跟著改變;
一種格式對(duì)應(yīng)一份模板,如果導(dǎo)出格式較多,需要準(zhǔn)備的模板文件較多,這樣比較繁瑣;
需要
Word
2003 以上版本;
舉個(gè)栗子
我們先編輯一份 Word
模板文檔,內(nèi)容大概如下所示:

將該文檔另存為
Word XML
文檔XML-Template.xml
讀取文檔內(nèi)容進(jìn)行變量替換
保存替換后的內(nèi)容,寫(xiě)入文件

可以看出來(lái)這種方式比較繁瑣,重點(diǎn)是編輯固定的模板格式,而且編輯好后保存成XML
格式后還需要繼續(xù)調(diào)整,這種 XML
格式標(biāo)簽很多,不小心就修改錯(cuò)了,導(dǎo)致導(dǎo)出的文檔打不開(kāi)
這種方式適合模板內(nèi)容不太復(fù)雜,內(nèi)容較少的情況下使用
COM 組件方式
“原理:采用
Micro soft
公開(kāi)的接口進(jìn)行通訊,進(jìn)行讀寫(xiě)時(shí)會(huì)打開(kāi)一個(gè) `Word進(jìn)程來(lái)交互
COM 技術(shù)概述
Qt 為我們提供了專(zhuān)門(mén)進(jìn)行交互的類(lèi)和接口,使用
Qt ActiveX`框架就可以很好的完成交互工作
優(yōu)點(diǎn)
實(shí)現(xiàn)簡(jiǎn)單,快速上手;
缺點(diǎn)
導(dǎo)出寫(xiě)入速度慢,因?yàn)橄喈?dāng)于打開(kāi) word 文檔操作;
僅
Windows
平臺(tái)可用,其它平臺(tái)失效;需要程序運(yùn)行的電腦安裝 office word,否則調(diào)用失敗
舉個(gè)栗子
使用時(shí)需要引入對(duì)應(yīng)的模塊,在 pro
文件引入模塊
打開(kāi)文檔寫(xiě)入內(nèi)容
可以看出來(lái)使用起來(lái)不難,對(duì)于新手友好一點(diǎn),很多寫(xiě)入操作方法比較繁瑣,需要自己重新封裝一套接口
這種方案比較適合那些排版比較復(fù)雜,圖片、文字、表格混排的場(chǎng)景下,而且內(nèi)容都是動(dòng)態(tài)變化的,可以很好的實(shí)現(xiàn)定制化
當(dāng)然了它的缺點(diǎn)也不少,也有一些坑,有時(shí)候莫名其妙會(huì)失敗,還有就是比如你電腦安裝的
Word
沒(méi)有激活,那么每次啟動(dòng)會(huì)彈激活窗口還有就是這種方式要求所有的路徑必須是本地化的,比如
D:\\Soft\test.png
使用前最好讀取注冊(cè)表判斷當(dāng)前電腦是否安裝了
Office Word
,如果沒(méi)有安裝,直接讀取操作肯定會(huì)崩潰
這種方式同樣適用于寫(xiě)入 Excel
文件,后面再說(shuō)
HTML 方式
“原理:這種方式得益于
Word
支持 HTML格式導(dǎo)出渲染顯示,那么反向也可以支持,需要我們拼接HTML
格式內(nèi)容,然后寫(xiě)入文件保存成.doc
格式
優(yōu)點(diǎn)
跨平臺(tái),不僅限于
Windows
平臺(tái),代碼可擴(kuò)展性比較好導(dǎo)出速度快、代碼可擴(kuò)展;
缺點(diǎn)
字符串拼接
HTML
容易出錯(cuò),缺失標(biāo)簽導(dǎo)出后無(wú)法顯示;插入的圖片是本地圖片文件的鏈接,導(dǎo)出的 word文檔拷貝到其它電腦圖片無(wú)法顯示
舉個(gè)栗子

這種方式難點(diǎn)在于 HTML
格式拼接,任何缺失字段都會(huì)導(dǎo)致導(dǎo)出失敗,適合小眾需求下導(dǎo)出
圖片問(wèn)題其實(shí)可以手動(dòng)進(jìn)行轉(zhuǎn)化,文檔導(dǎo)出成功后手動(dòng)拷貝內(nèi)容到新的文檔,這樣圖片就真正插入到文檔中,文檔發(fā)送給別人也不會(huì)丟失圖片了
還有一個(gè)坑就是:如果你使用 WPS
打開(kāi)導(dǎo)出的文檔,默認(rèn)顯示的是 web
視圖,需要手動(dòng)進(jìn)行調(diào)整
某些電腦分辨率變化也會(huì)導(dǎo)致生成的文檔中字體等產(chǎn)生變化
第三方開(kāi)源庫(kù)
可以使用的第三方庫(kù)幾乎沒(méi)有,網(wǎng)絡(luò)上找到的有這么幾個(gè)
OpenOffice: 兼容性差,集成調(diào)用難度大
LibOffice: 太龐大,不容易集成
DuckX:太小眾,只能進(jìn)行簡(jiǎn)單的使用
docx:小眾庫(kù)
DuckX庫(kù)docx庫(kù)
在讀寫(xiě) Word
這部分,C++
基本沒(méi)有可以使用的第三方庫(kù),不像其他語(yǔ)言Java
、C#
、Python
有很多可以選擇,這個(gè)痛苦也只有 C++
程序員能夠理解了吧
所以怎么選擇還是看自己項(xiàng)目需求吧,沒(méi)有十全十美的方案
上面說(shuō)了這么多,都是導(dǎo)出生成 Wrod
,那么下面來(lái)看看有哪些方式可以讀取顯示 Word
內(nèi)容
這種需求應(yīng)該不會(huì)很多,而且顯示難度更大一些
使用 COM
組件方式,即采用 QAxWidget
框架顯示 office
文檔內(nèi)容,本質(zhì)上就是在我們編寫(xiě)的 Qt
界面上嵌入 office
的軟件,這種方式其實(shí)和直接打開(kāi) Word
查看沒(méi)有啥區(qū)別,效果、性能上不如直接打開(kāi)更好一些
目前一般都會(huì)采用折中方案,把 Word
轉(zhuǎn)為 PDF
進(jìn)行預(yù)覽加載顯示,我們知道 PDF
渲染庫(kù)比較多,生態(tài)相對(duì)來(lái)說(shuō)要好一些,在選擇上就更廣泛些,如何使用后面部分有專(zhuān)門(mén)介紹 PDF
章節(jié)
讀寫(xiě) Excel
目前有一個(gè)支持比較好的第三方庫(kù)可以使用,整體使用基本可以滿足日常使用
QXlsx

這款開(kāi)源庫(kù)支持跨平臺(tái),Linux、Windows、Mac、IOS、Android,使用方式支持動(dòng)態(tài)庫(kù)調(diào)用和源碼直接集成,非常方便
編譯支持 qmake
和cmake
,可以根據(jù)你自己的項(xiàng)目直接集成編譯,讀寫(xiě)速度非???/p>
可以看到上手非常容易、各個(gè)函數(shù)命名也貼近 Qt Api
,是一款非常良心的開(kāi)源軟件
“PS:注意該軟件使用
MIT
許可協(xié)議,這樣對(duì)于很多個(gè)人或者公司來(lái)說(shuō)非常良心,意味著你可以無(wú)償使用、修改該項(xiàng)目,但是必須在你項(xiàng)目中也添加同樣的MIP
許可
上面也提到了,還可以使用 COM
組件的方式讀寫(xiě) Excel
,不過(guò)有了這款開(kāi)源庫(kù)基本就可以告別 COM
組件方式了
讀寫(xiě) PDF
PDF
相關(guān)開(kāi)源庫(kù)挺多的,給了 C++
程序員莫大的幫助,目前可用的主要有這些

其中 mupdf
和 poppler
屬于功能強(qiáng)大但是很難編譯的那種,需要有扎實(shí)的三方庫(kù)編譯能力,否則面對(duì) n
個(gè)依賴庫(kù)會(huì)無(wú)從下手
不過(guò)可喜的是 Github
上有兩個(gè)開(kāi)源庫(kù)可以供選擇
qpdf 庫(kù)
這個(gè)庫(kù)其實(shí)封裝了 pdf.js
庫(kù),使用 WebEngine
來(lái)執(zhí)行 JavaScript
進(jìn)而加載文件

項(xiàng)目地址
直接從本地文件加載;
支持從內(nèi)存數(shù)據(jù)直接加載渲染 PDF 內(nèi)容;
這種方式對(duì)環(huán)境有特殊要求了,如果你的項(xiàng)目使用的 Qt
版本不支持 WebEngine
,那么就無(wú)法使用
qtpdf 庫(kù)
這個(gè)庫(kù)是 Qt
官方親自操刀對(duì)第三方庫(kù)進(jìn)行了封裝,暴露的 API
和 Qt
類(lèi)似,使用起來(lái)非常舒服
Qt 官方

代碼結(jié)構(gòu)以及使用 Demo

小試牛刀
關(guān)于如何使用,官方已經(jīng)給了我們非常詳細(xì)的步驟了,直接跟著下面幾步就 OK 了
官方教程
可以看到使用了谷歌開(kāi)源的 pdfium
三方庫(kù),編譯時(shí)需要單獨(dú)更新下載這個(gè)庫(kù),因?yàn)槟承┰蚩赡苣銦o(wú)法下載,不過(guò)好在有人在 GitHub
上同步了這個(gè)倉(cāng)庫(kù)的鏡像,有條件還是建議直接下載最新穩(wěn)定版的

可正常訪問(wèn)的倉(cāng)庫(kù)地址:https://github.com/PDFium/PDFium
相關(guān)類(lèi)可以看這個(gè)文檔:https://developers.foxit.com/resources/pdf-sdk/c_api_reference_pdfium/modules.html
“最后還要注意項(xiàng)目開(kāi)源協(xié)議:pdfium 引擎開(kāi)始來(lái)自于福昕,一個(gè)中國(guó)本土的軟件公司,Google與其合作最終進(jìn)行了開(kāi)源,目前采用的是
BSD 3-Clause
協(xié)議,這種協(xié)議允許開(kāi)發(fā)者自由使用、修改源代碼,也可以修改后重新發(fā)布,允許閉源進(jìn)行商業(yè)行為,不過(guò)需要你在發(fā)布的產(chǎn)品中包含原作者代碼中的BSD
協(xié)議
總結(jié)
以上就是項(xiàng)目中常用的文檔處理方法總結(jié),當(dāng)然了肯定也還有其它方案可以實(shí)現(xiàn),畢竟條條大路通羅馬,如果你還要不錯(cuò)的方案和建議歡迎留言
PS: 以上方案和對(duì)應(yīng)的源碼編譯、使用例子會(huì)統(tǒng)一上傳到 GitHub
對(duì)應(yīng)的倉(cāng)庫(kù),方便后人使用,有需要的可以關(guān)注下
取之互聯(lián)網(wǎng)、回報(bào)互聯(lián)網(wǎng)
原創(chuàng)不易,如果覺(jué)得對(duì)你有幫助,歡迎點(diǎn)贊、在看、轉(zhuǎn)發(fā)
推薦閱讀
Qt Creator 源碼學(xué)習(xí)筆記01,初識(shí)QTC
Qt Creator 源碼學(xué)習(xí)筆記02,認(rèn)識(shí)框架結(jié)構(gòu)結(jié)構(gòu)
Qt Creator 源碼學(xué)習(xí)筆記03,大型項(xiàng)目如何管理工程
Qt Creator 源碼學(xué)習(xí)筆記04,多插件實(shí)現(xiàn)原理分析
Qt Creator 源碼學(xué)習(xí)筆記 05,菜單欄是怎么實(shí)現(xiàn)插件化的?