最近項目中需要根據模板生成word文檔,模板文件也是word文檔。當時思考一下想用POI API來做,但是覺得用起來相對復雜。后來又找了一種方式,使用freemarker模板生成word文件,經過嘗試覺得還是相對簡單易行的。
使用freemarker模板生成word文檔主要有這么幾個步驟
1、創建word模板:因為我項目中用到的模板本身是word,所以我就直接編輯word文檔轉成freemarker(.ftl)格式的。

2、將改word文件另存為xml格式,注意使用另存為,不是直接修改擴展名。
3、將xml文件的擴展名改為ftl
4、編寫java代碼完成導出
使用到的jar:freemarker.jar (2.3.28) ,其中Configuration對象不推薦直接new Configuration(),仔細看Configuration.class文件會發現,推薦的是 Configuration(Version incompatibleImprovements) 這個構造方法,具體這個構造方法里面傳的就是Version版本類,而且版本號不能低於2.3.0
閑言碎語不再講,直接上代碼
1 public static void exportDoc() { 2 String picturePath = "D:/image.png"; 3 Map<String, Object> dataMap = new HashMap<String, Object>(); 4 dataMap.put("brand", "海爾"); 5 dataMap.put("store_name", "海爾天津"); 6 dataMap.put("user_name", "小明"); 7 8 //經過編碼后的圖片路徑 9 String image = getWatermarkImage(picturePath); 10 dataMap.put("image", image); 11 12 //Configuration用於讀取ftl文件 13 Configuration configuration = new Configuration(new Version("2.3.0")); 14 configuration.setDefaultEncoding("utf-8"); 15 16 Writer out = null; 17 try { 18 //輸出文檔路徑及名稱 19 File outFile = new File("D:/導出優惠證明.doc"); 20 out = new BufferedWriter(new OutputStreamWriter(new 21 FileOutputStream(new File("outFile")), "utf-8"), 10240); 22 } catch (UnsupportedEncodingException e) { 23 e.printStackTrace(); 24 } catch (FileNotFoundException e) { 25 e.printStackTrace(); 26 } 27 // 加載文檔模板 28 Template template = null; 29 try { 30 //指定路徑,例如C:/a.ftl 注意:此處指定ftl文件所在目錄的路徑,而不是ftl文件的路徑 31 configuration.setDirectoryForTemplateLoading(new File("C:/")); 32 //以utf-8的編碼格式讀取文件 33 template = configuration.getTemplate("導出優惠證明.ftl", "utf-8"); 34 } catch (IOException e) { 35 e.printStackTrace(); 36 throw new RuntimeException("文件模板加載失敗!", e); 37 } 38 39 // 填充數據 40 try { 41 template.process(dataMap, out); 42 } catch (TemplateException e) { 43 e.printStackTrace(); 44 throw new RuntimeException("模板數據填充異常!", e); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 throw new RuntimeException("模板數據填充異常!", e); 48 } finally { 49 if (null != out) { 50 try { 51 out.close(); 52 } catch (IOException e) { 53 e.printStackTrace(); 54 throw new RuntimeException("文件輸出流關閉異常!", e); 55 } 56 } 57 } 58 }
因為很多時候我們根據模板生成文件需要添加水印,也就是插入圖片
1 /*** 2 * 處理圖片 3 * @param watermarkPath 圖片路徑 D:/image.png 4 * @return 5 */ 6 private String getWatermarkImage(String watermarkPath) { 7 InputStream in = null; 8 byte[] data = null; 9 try { 10 in = new FileInputStream(watermarkPath); 11 data = new byte[in.available()]; 12 in.read(data); 13 in.close(); 14 } catch (Exception e) { 15 e.printStackTrace(); 16 } 17 BASE64Encoder encoder = new BASE64Encoder(); 18 return encoder.encode(data); 19 }
注意點:
插入圖片后的word轉化為ftl模板文件(ps:水印圖片可以在word上調整到自己想要的大小,然后在執行下面的步驟)
1、先另存為xml
2、將xml擴展名改為ftl
3、打開ftl文件, 搜索w:binData 或者 png可以快速定位圖片的位置,圖片 已經編碼成0-Z的字符串了, 如下: 
5、 將上述0-Z的字符串全部刪掉,寫上${image}(變量名隨便寫,跟dataMap里的key保持一致)后保存
6、也是創建一個Map, 將數據存到map中,只不過我們要把圖片用代碼進行編碼,將其也編成0-Z的字符串,代碼請看上邊
至此一個簡單的按照模板生成word並插入圖片(水印)功能基本完成。
