最近在做一个简报导出的功能,要求导出word格式,上网找了很多资料,一开始选择了poi后来发现poi只能导出简单的word数据,后来偶然发现了通过FreeMaker模板生成word,说实话,还挺好用的!下面是我的一个demo!
第一步:制定word模板
第二步:另存为xml格式
第三步:将修改后的xml模版保存为ftl格式
2、<#list newsList as listKey>为FreeMaker的用法,迭代newsList中的数据
图片:
如果你需要在word中添加图片,那你就在第一步制作模板时,加入一张图片占位,然后打开xml文档,可以看到如下的一片base64编码后的代码:
<w:binData w:name="wordml://03000001.png" xml:space="preserve">iVBORw0…(很省略很省略)…CC</w:binData>
只要将的代码替换成例如:${image},如下:
package com.tgb.web; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import sun.misc.BASE64Encoder; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class t2 { private Configuration configuration = null; public t2() { configuration = new Configuration(); configuration.setDefaultEncoding("UTF-8"); } /** * 以下载的方式生成word,自定义路径 * @param dataMap * @param out */ public void createDoc(Map<String,Object> dataMap,Writer out) { // 设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载, // ftl文件存放路径 configuration.setClassForTemplateLoading(this.getClass(),"/config/spring"); Template t = null; try { // test.ftl为要装载的模板 t = configuration.getTemplate("yuqing_brief_template2.ftl"); t.setEncoding("utf-8"); } catch (IOException e) { e.printStackTrace(); } try { t.process(dataMap,out); } catch (TemplateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 传入数据 可直接本地生成word * @param dataMap */ public void createDoc(Map<String,Object> dataMap) { // 设置模本装置方法和路径,"/config/spring"); Template t = null; try { // test.ftl为要装载的模板 t = configuration.getTemplate("t2_img.ftl"); t.setEncoding("utf-8"); } catch (IOException e) { e.printStackTrace(); } // 输出文档路径及名称 File outFile = new File("H:/'" + Math.random()*10000 + "'t2_img.doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"utf-8")); } catch (Exception e1) { e1.printStackTrace(); } try { t.process(dataMap,out); out.close(); } catch (TemplateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * * 注意dataMap里存放的数据Key值要与模板中的参数相对应 * * @param dataMap */ private Map<String,Object> getData() { Map<String,Object> dataMap = new HashMap<String,Object>(); Map<String,Object> map1 = new HashMap<String,Object> map2 = new HashMap<String,Object>(); map1.put("title","国泰君安*公司研究*广发证券:定增完成,如虎添翼*000776*投资银行业与经纪业行业*梁静"); map1.put("content","报告类型=公司事件点评公司简称=广发证券公司代码=000776报告日期=Thu Aug 25 09:05:29 CST 2011研究员 =梁静报告标题=定增完成"); map1.put("site","上海证卷报"); String img1 = getImageStr("H:/Tulips.jpg"); map1.put("image",img1); map1.put("i",1);//标识图片 map2.put("title","[申万销售夏敬慧] 基金仓位周报----开基仓位下降1.51%"); map2.put("content","理财产品部分析师: 杨鹏(18930809297) 开基仓位有所下降:本周,开放式基金平均仓位继续下降。"); map2.put("site","上海证卷报"); String img2 = getImageStr("H:/Penguins.jpg"); map2.put("image",img2); map2.put("i",2);//标识图片 List<Map<String,Object>> newsList = new ArrayList<Map<String,Object>>(); newsList.add(map1); newsList.add(map2); dataMap.put("newsList",newsList); return dataMap; } public String getImageStr(String imgFile) { InputStream in = null; byte[] data = null; try { in = new FileInputStream(imgFile); data = new byte[in.available()]; in.read(data); in.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data); } public static void main(String[] args) { t2 word = new t2(); Map<String,Object> map = word.getData(); word.createDoc(map); } }
//控制层代码(本人用的是springmvc)
<span style="white-space:pre"> </span>@RequestMapping(value="/exportword") @ResponseBody public String exportWord(HttpServletRequest request,HttpServletResponse response) throws IOException{ response.setContentType("application/octet-stream; charset=UTF-8"); response.setHeader("content-disposition","attachment;filename=" + new SimpleDateFormat("yyyyMMddHH:mm:ss").format(new Date()) + ".doc"); Writer out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(),"utf-8"));//重点:一定要注意编码格式,漏写编码格式将导致word无法打开(xml非法字符) t2 word = new t2(); Map<String,Object> map = userService.getData(); word.createDoc(map,out); out.flush(); out.close(); return null; }OK!搞定,希望对有需要的人有用!