freemarker根據模板導出word文件
標簽: 解決方案 java freemarker
前言
項目中都會遇到關于文件的導出,這里主要使用freemarker來根據ftl來生成word文檔,這里使用的例子中我只考慮到一些常見的情況,如果你遇到問題或是其他特殊情況,希望留下你問題和見解。
word文件導出
引入依賴
- 首先是導入freemarker的jar包
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency>
模板填充
-
然后我們在word的模板上填充上對應的參數:
上面模板中個人榮譽和工作經歷是存在多個,對應了一個list對象,在此我們先不在頁面上進行參數填充,而頭像和個人風采需要插入圖片,所以我們先默認插入一些圖片進行占位和設置其大小屬性;值得注意的是如果你需要像上圖個人風采部分動態的展示圖片的話,其圖片一定要設置為四周型環繞。 -
將word另存為xml格式:
在另存為時,提供了兩種xml格式的轉儲,請用Word XML 文檔格式進行轉儲。 -
將導出的xml文件的后綴更改為ftl,并放入項目的resources資源包的templates文件夾中
list數據的遍歷填充
- 打開該ftl文件,上面我們提到了關于個人榮譽和工作經歷都是存在多條的,所以需要用list對象來存儲,在ftl文件中就需要對list數據進行遍歷,以下是對工作經歷數據的遍歷
<#--這里的使用if標簽來對list進行判空操作--> <#if workExperienceList?? && (workExperienceList?size > 0) > <#--這里是對list進行遍歷循環,workExperience為每次被遍歷到的對象--> <#list workExperienceList as workExperience> <#--在ftl模板中,一個w:p標簽代表一個段落,這里不要直接將這份代碼粘貼過去,因為你本身的格式與我不同,導出后可能會出現的格式不一的問題--> <w:p> <w:pPr> <w:bidi w:val="0"/> <w:jc w:val="center"/> <w:rPr> <w:rFonts w:hint="default" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/> <w:sz w:val="24"/> <w:szCs w:val="24"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/> <w:sz w:val="24"/> <w:szCs w:val="24"/> <w:vertAlign w:val="baseline"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <#--在w:t標簽中填充值,通過time?string("yyyy-MM-dd")!,首先判斷time是否為空,如果不為空則對時間進行格式轉換,這里的?!其實類似于java的三目運算符 --> <w:t>${(workExperience.workStartTime?string("yyyy-MM-dd"))!}~${(workExperience.workEndTime?string("yyyy-MM-dd"))!'至今'}在${workExperience.unitName!}擔任${workExperience.title!},${workExperience.jobDescription!}</w:t> </w:r> </w:p> </#list> </#if>
插入圖片
-
首先插入圖片前我們需要知道在ftl中圖片分為三部分
- 第一部分:
在創建模板之前因為插入了幾張圖片,所以你能看到占位
<#--pkg:name中填充的是圖片在ftl模板中的位置,pkg:contentTyped代表了當前的標簽內容的類型--> <pkg:part pkg:name="/word/media/image1.jpeg" pkg:contentType="image/jpeg"> <pkg:binaryData>存放圖片的base64位編碼</pkg:binaryData> </pkg:part>
- 第二部分:
這一部分可以說是對圖片的一個申明,我們看到使用Relationship標簽對圖片進行了申明,這里只有三張圖片(其他的非圖片為了方便截圖我將其隱藏了)是因為我的模板中雖然展示了四張圖片,但是因為有兩張圖片相同,所以這里就只有三個聲明,通過Target屬性指向圖片所在的路徑,而Id則必須唯一它是連接連接第三部分的重要參數。<pkg:part pkg:name="/word/_rels/document.xml.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml"> <pkg:xmlData> <Relatiaonships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="指定ID" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="對應第一部分中pkg:name,只是去掉了/word/"/> </Relationships> </Relationships> </pkg:xmlData> </pkg:part>
- 第三部分:
該部分的xml比較長,我就只截重要的部分說明
以上就是對圖片插入的說明,如果說你只有一張圖片插入,那直接在第一部分中填充入你圖片的Base64位編碼就能實現圖片的插入,而當你需要動態的插入圖片就必須要通過循環來指定圖片
- 第一部分:
-
動態插入圖片
- 首先我將圖片都封裝為一個實體類,然后多張圖片對應一個list集合
import lombok.Data; /** * @Author HomeWellGo * @Date 2020/10/18 20:10 * @Description 圖片信息類 */ @Data public class ImgInfo { //圖片的base64位編碼 private String imgBaseCode; //圖片的路徑 private String imgUrl; //序號 private Integer imgIndex; }
- 填充圖片的base64位編碼
<#if personalStyle?? && (personalStyle?size > 0) > <#list personalStyle as style> <pkg:part pkg:name="/word/media/image${style.imgIndex}.jpeg" pkg:contentType="image/jpeg"> <pkg:binaryData> ${(style.imgBaseCode)!''} </pkg:binaryData> </pkg:part> </#list> </#if>
- 聲明圖片
<#if personalStyle?? && (personalStyle?size > 0) > <#list personalStyle as style> <Relationship Id="rId${style.imgIndex}jpg" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image${style.imgIndex}.jpeg"/> <Relationship Id="rId${style.imgIndex}jpg" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image${style.imgIndex}.jpeg"/> <Relationship Id="rId${style.imgIndex}jpg" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image${style.imgIndex}.jpeg"/> </#list> </#if>
- 指定圖片
- 首先我將圖片都封裝為一個實體類,然后多張圖片對應一個list集合
java代碼
- 代碼部分
/** * 導出word文件 * @param user 實體類 * @param path 導出的word文件路徑 * */ public static void exportWord(User user,String path){ //Configuration 用于讀取ftl文件 Configuration configuration = new Configuration(new Version("2.3.0")); configuration.setDefaultEncoding("utf-8"); configuration.setClassForTemplateLoading(ExportPdfForDocx4j.class, "/templates"); Writer out=null; try { //輸出文檔路徑及名稱 File outFile = new File(path); //以utf-8的編碼讀取ftl文件 Template template = configuration.getTemplate("/exportPDFForWord.ftl", "utf-8"); out= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240); template.process(user, out); } catch (IOException e) { e.printStackTrace(); }catch (TemplateException e1){ e1.printStackTrace(); }finally { try { if(out!=null) out.close(); } catch (IOException e) { e.printStackTrace(); } } }
/** * 獲取圖片的Base64位編碼 * */ public static String getImgBase64(String path){ InputStream in = null; byte[] data = null; try{ in = new FileInputStream(path); data = new byte[in.available()]; in.read(data); in.close(); }catch (IOException e){ e.printStackTrace(); }finally { try { if (in!=null) in.close(); } catch (IOException e) { e.printStackTrace(); } } //對字節數組Base64編碼 BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data); }
智能推薦
freemarker模板生成word文件
項目中首先引入freemarker的jar包,下載鏈接:http://download.csdn.net/download/pnljg/2736572 1、用word文檔制作好模板 ceshi.docx 2、將ceshi.docx文件另存為ceshi.xml文件 ${name}、${tel}、${address}被拆分了,用notpad++打開ceshi.xml文件,將被拆分的數據重新修改,修改完...
JAVA根據模板生成WORD文件并導出
JAVA根據模板生成WORD并導出 實現功能 一 : WORD導出效果 先看一下導出的demo文件,具體參數可手動修改 下圖為word_demo.docx導出的WORD文件 下圖為word_list.docx導出的WORD文件 二 : 編寫WORD模板 demo模板(數據替換模板中的配置參數) : word_demo.docx demo模板(導出數據列表,數據表格在文件下方自動拼接) : word...
Java Freemarker 根據模板生成Word
打開word寫word 模板 將此模板另存為 xml 關閉word用notepad++打開精工發貨通知單.xml格式化 搜索替換變量字段為${變量字段},圖片部分base64值刪掉也替換 替換后如下: 額外部分(懶得找遍歷): 如果有表格需要遍歷顯示的,找到對應需要遍歷的行,在外層用<#list ? as row ></#list>進行包圍,遍歷的行用 ${row.?}來替...
使用freemarker模板導出word文檔
最近項目中要使用到導出word這項功能,參考了許多導出的方法,發現使用freemarker模板導出word的效果最好可以保持原樣。 導入freemarker的架包 1.首先我們需要用word制作一份模板,打開word編輯我們想要的word樣式。 如圖: 2.在需要填寫的地方用變量來代替。如果有圖片需要先用圖片來填充。然后另存為xml文件,然后再把后綴名改為.ftl的格式 3.處理ftl文件,把圖片...
使用freemarker生成word模板導出
目錄 1導入jar包 2模板生成 1、新建word 2、把xml格式文件后綴改為ftl,并把ftl文件加入代碼里資源文件夾下 3代碼 4生成word展示 1導入jar包 2模板生成 1、新建word 需要注意的是把你后期想插入的值用${}代替,完事要另存為XML格式文檔 2、把xml格式文件后綴改為ftl,并把ftl文件加入代碼里資源文件夾下 注意:如果需要加入圖片的話,在文檔里復制一個圖片,然后...
猜你喜歡
使用spring boot freemarker導出word模板
使用spring boot freemarker導出word模板 遇到坑一: 導出的word里面像是 .xml文件信息,空置太保存,顯示有某個字段出錯 遇到坑二:加載不到模板 最近在項目中遇到一個功能,從數據庫中獲取數據,然后將這些數據寫入word模板中,網上也有很多資料和樣例,主要步驟大概就是創建一個word文件,word文件中需要數據庫保存的地方用占位符來寫:${} 文件創建好之后先另存為其他...
使用freemarker模板導出word文檔
1.先上模板圖 2.效果圖 步驟 鏈接:https://pan.baidu.com/s/1n204S3M-2z3slFITk6pCbw 提取碼:z3s5 1.打開word模板,給需要賦值的位置先填上數據,方便查找編寫freemarker代碼,如下圖 2.將word文件另存為xml文件 到桌面 ,然后修改jhj.xml修改后綴 改為 jhj.ftl 文件 &n...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...