日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

FreeMarker生成复杂word(包含图片,表格)

發布時間:2024/3/13 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FreeMarker生成复杂word(包含图片,表格) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Web項目中生成Word文檔的操作屢見不鮮,基于Java的解決方案也是很多的,包括使用JacobApache POIJava2WordiText等各種方式,其實在從Office 2003開始,就可以將Office文檔轉換成XML文件,這樣只要將需要填入的內容放上${}占位符,就可以使用像FreeMarker這樣的模板引擎將出現占位符的地方替換成真實數據,這種方式較之其他的方案要更為簡單。這個功能就是由XML+FreeMarker來實現的,Word從2003開始支持XML格式,大致的步驟:用office2003或者以上的版本編輯好word的樣式,然后另存為xml,將xml翻譯為FreeMarker模板,最后用java來解析FreeMarker模板并輸出Doc。使用Freemarker其實就只準備模板和數據

制作resume.ftl模板

首先用office【版本要2003以上,以下的不支持xml格式】編輯文檔的樣式,將需要動態填充的內容使用Freemarker標簽替換,將Word文檔另存為XML格式(注意是另存為,不是直接改擴展名)?建議用Editplus、Notepad++、Sublime等工具打開查看一下,因為有的時候你寫的占位符可能會被拆開,這樣Freemarker就無法處理了。



打開XML文件看看,如果剛才你寫的${qno}、${title}等被xml文件給拆散了,修改一下XML文件就OK了


修改過后另存為resume.ftl模板文件,如下所示:


接下來修改圖片,搜索w:binData 或者 png可以快速定位圖片的位置,圖片已經是0-F的字符串了,換成一個占位符,在將要插入Word文檔的圖片對象轉換成BASE64編碼的字符串,用該字符串替換掉占位符就可以了,示意圖如下所示:

接下來就可以編碼啦:

服務的代碼:

@RequestMapping(value = "/demo/word", method = RequestMethod.POST)public void word(@RequestParam(value = "image", required = false) MultipartFile image, ModelMap model, HttpServletRequest req, HttpServletResponse resp) throws IOException {req.setCharacterEncoding("utf-8");Map<String, Object> map = null;Enumeration<String> paramNames = req.getParameterNames();// 通過循環將表單參數放入鍵值對映射中 /*while (paramNames.hasMoreElements()) {String key = paramNames.nextElement();String value = req.getParameter(key);map.put(key, value);}*/InputStream in = image.getInputStream();String reportImage = WordGenerator.getImageString(in);String jsonStr = "{\"exam\": [{\"ecnt\": 4,\"eid\": \"25\",\"options\": [{\"choice\": \"3\",\"option\": \"男\",\"rowratio\": \"75.00%\"}, {\"choice\": \"1\",\"option\": \"女\",\"rowratio\": \"25.00%\"}],\"qno\": \"3\",\"title\": \"你的性別是\",\"types\": \"單選題\"}]}";JSONObject jsonObject = JSONObject.parseObject(jsonStr);List exams = jsonObject.getJSONArray("exam");List<Map<String, Object>> arrayList = new ArrayList<Map<String, Object>>();for (int i = 0; i < exams.size(); i++) {map = new HashMap<String, Object>();JSONObject exam = (JSONObject) exams.get(i);map.put("ecnt", exam.get("ecnt"));map.put("eid", exam.get("eid"));map.put("qno", exam.get("qno"));map.put("title", exam.get("title"));map.put("types", exam.get("types"));map.put("reportImage", reportImage);List<Map<String, String>> options = (List) exam.getJSONArray("options");List<Map<String, Object>> optionList = new ArrayList<Map<String, Object>>();for (Map tempMap : options) {Map optionMap = new HashMap<String, Object>();optionMap.put("choice", tempMap.get("choice"));optionMap.put("option", tempMap.get("option"));optionMap.put("rowratio", tempMap.get("rowratio"));optionList.add(optionMap);}map.put("options", optionList);arrayList.add(map);}// 提示:在調用工具類生成Word文檔之前應當檢查所有字段是否完整 // 否則Freemarker的模板殷勤在處理時可能會因為找不到值而報錯 這里暫時忽略這個步驟了 File file = null;InputStream fin = null;OutputStream out = null;try {// 調用工具類WordGenerator的createDoc方法生成Word文檔 Map root = new HashMap<String, Object>();root.put("questTitle", "測試word導出");root.put("exams", arrayList);file = WordGenerator.createDoc(root, "resume");fin = new FileInputStream(file);resp.setCharacterEncoding("utf-8");resp.setContentType("application/ms-word;charset=utf-8");// 設置瀏覽器以下載的方式處理該文件默認名為resume.doc resp.addHeader("Content-Disposition", "attachment;filename=resume.doc");out = resp.getOutputStream();// 寫出流信息/* while ((len = fs.read()) != -1) {os.write(len);}*/byte[] buffer = new byte[512]; // 緩沖區 int bytesToRead = -1;// 通過循環將讀入的Word文件的內容輸出到瀏覽器中 while ((bytesToRead = fin.read(buffer)) != -1) {out.write(buffer, 0, bytesToRead);}} finally {if (fin != null) {fin.close();}if (out != null) {out.close();}if (file != null) {file.delete(); // 刪除臨時文件 }}} 工具類的代碼:

package cn.comm.util;import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.HashMap; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import sun.misc.BASE64Encoder;public class WordGenerator {private static Configuration configuration = null;private static Map<String, Template> allTemplates = null;static {configuration = new Configuration();configuration.setDefaultEncoding("utf-8");configuration.setClassForTemplateLoading(WordGenerator.class, "/cn/comm/ftl");allTemplates = new HashMap<>(); // Java 7 鉆石語法 try {allTemplates.put("resume", configuration.getTemplate("resume.ftl"));} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);}}private WordGenerator() {throw new AssertionError();}public static File createDoc(Map<?, ?> dataMap, String type) {String name = "temp" + (int) (Math.random() * 100000) + ".doc";File f = new File(name);Template t = allTemplates.get(type);try {// 這個地方不能使用FileWriter因為需要指定編碼類型否則生成的Word文檔會因為有無法識別的編碼而無法打開 Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");t.process(dataMap, w);w.flush();w.close();} catch (Exception ex) {ex.printStackTrace();throw new RuntimeException(ex);}return f;}//將圖片轉換成BASE64字符串public static String getImageString(InputStream in) throws IOException {//InputStream in = null; byte[] data = null;try {// in = new FileInputStream(filename); data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {throw e;} finally {if (in != null)in.close();}BASE64Encoder encoder = new BASE64Encoder();return data != null ? encoder.encode(data) : "";}} jsp代碼:

<%@ page pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Document</title> <style type="text/css"> * { font-family: "微軟雅黑"; } .textField { border:none; border-bottom: 1px solid gray; text-align: center; } #file { border:1px solid black; width: 80%; margin:0 auto; } h1 input{ font-size:72px; } td textarea { font-size: 14px; } .key { width:125px; font-size:20px; } </style> </head> <body> <form action="/mybase/demo/word" method="post" enctype="multipart/form-data"> <div id="file" align="center"> <h1><input type="text" name="title" class="textField" value="測試word導出"/></h1> <hr/> <table> <tr> <td colspan="4"> <input type="file" name="image" /> </td> </tr> </table> </div> <div align="center" style="margin-top:15px;"> <input type="submit" value="保存Word文檔" /> </div> </form> </body> </html> 注意:這里使用的BASE64Encoder類在sun.misc包下,rt.jar中有這個類,但是卻無法直接使用,需要修改訪問權限,在Eclipse中可以這樣修改。

在項目上點右鍵選擇Properties菜單項進入如下圖所示的界面:


這樣設置后就可以使用BASE64Encoder類了,在項目中調用getImageString 方法指定要插入的圖片的完整文件名(帶路徑的文件名),該方法返回的字符串就是將圖片處理成BASE64編碼后的字符串。

到這里就可以導出一個復雜的帶表格,圖片的wors文檔啦。導出來就是這樣的,如下圖:





總結

以上是生活随笔為你收集整理的FreeMarker生成复杂word(包含图片,表格)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。