前言: 要做一个wod导出,java有很多实现方式,比如iText,POI,FreeMarker,Jacob等等,由于之前公司使用的一直是提供的封装好的报告服务,直接调用,就从来没有仔细想过没有了公司的报告服务怎么做,最要命的是总是认为一个干了多年的程序员还好意思问word导出怎么写,会招来很多的鄙视,事实是那些觉着不屑一提的大神口若悬河的跟你说某些技术的时候,他们真的连word导出也写不出来,他们的大放厥词的技术只适合用来面试,不行你可以试试。
总结: 对于使用word模板导出,通过对几种方式的总结,发现POI是勉强不错的方式,但是网上千篇一律的 创建一个模板然后保存成xml,然后修改内容,(或者再保存为ftl格式文件)。我就想强强的问一句用模板的意义是什么呢?
使用模板的本意就是要让客户可以直接修改模板的内容、文字样式等,如果还要修改xml内容,各种文件格式保存,这么傻逼的模板方式还有意义吗?,或者提供了doc的模板后,导出后word打不开,真是服!
方案:下面提供本人亲测 两种POI方式的 word导出。
环境:准备jar包,本案例使用的是poi3.7 版本
1,使用模板方式:模板见附件。
1),新建一个word文档,命名detail.docx,定义几个 变量 如图: 注意几个变量最好 先在记事本上写好,然后粘过来,因为word底层编译成xml的时候很不友好,容易将你写的东西分割,无语。
2),敲代码吧。
1,使用模板的方式。
package com.trs.om.screenshow.hotnewsshow.struts2; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import org.apache.poi.POIXMLDocument; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import com.trs.om.util.HTMLUtil; /** * poi模板方式导出word * @author zhaozuofa * 2016年4月15日 下午3:43:40 * */ public class ExportWordPOI { public static void searchAndReplace(String srcPath, String title,Map<String, String> map) { try { OPCPackage pack = POIXMLDocument.openPackage(srcPath); XWPFDocument doc = new XWPFDocument(pack); List<XWPFParagraph> paragraphs = doc.getParagraphs(); String content = ""; for (XWPFParagraph tmp : paragraphs) { List<XWPFRun> runs = tmp.getRuns(); for (XWPFRun r : runs) { for (Entry<String, String> e : map.entrySet()) { if (r.getText(0).trim().equals(e.getKey())) { //处理字段内容中的 换行,网上各种bb,就是不解决问题什么 (char)11啊,\r啊 自己试验的实验的时候都扯淡 //解决原理是:根据内容中要换行的依据进行分割成数组或集合,在通过 poi提供的换行方法分别写入。 if(r.getText(0).trim().equals("${content}")){ content =map.get(r.getText(0).trim()); r.setText("",0); String strsf[] = content.split("\r\n"); for(int i = 0;i<strsf.length;i++){ if(StringUtils.isNotEmpty(strsf[i])){ String textContent = strsf[i].replaceAll(" ", ""); r.setText("\n"+textContent); r.addCarriageReturn(); } } }else{ r.setText("\n"+map.get(r.getText(0).trim()),0); } } } } } String wname = HTMLUtil.replaceBlank(title)+".docx"; wname = new String(wname.getBytes("gb2312"), "iso8859-1");//格式化文件中文名称,解决乱码 //1, web项目时,浏览器点击导出时,弹出下载框 /* HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("application/msword; charset=utf-8"); response.setHeader("Content-Disposition","attachment;filename="+wname); response.setCharacterEncoding("utf-8"); OutputStream outfa = response.getOutputStream();*/ //2,java项目直接保存在指定硬盘中,路径可以通过参数传递,本例直接写死,懂得道理就可以。 OutputStream outfa = new FileOutputStream("D:\\word\\newLine2.doc"); doc.write(outfa); outfa.flush(); outfa.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { ExportWordPOI pt = new ExportWordPOI(); //模板文件路径 String str = "d:\\word\\detail.docx"; // String str = ServletActionContext.getServletContext().getRealPath("/WEB-INF/detail/detail.docx");//这样可以获取项目下的枯井 HashMap<String,String> map = new HashMap<String,String>(); map.put("${topdata}", "2016-04-17,环球网"); map.put("${title}", "我是测试标题"); map.put("${content}", "我是一条测试的内容数据"); pt.searchAndReplace(str, "测试", map); } }
2,快速导出,不使用模板的方式,可参看:http://blog.csdn.net/w8700569/article/details/7288149
package com.trs.om.screenshow.hotnewsshow.struts2; import java.io.FileOutputStream; import org.apache.poi.xwpf.usermodel.Borders; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.TextAlignment; import org.apache.poi.xwpf.usermodel.UnderlinePatterns; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; public class Test { public static void main(String[] args) throws Exception { XWPFDocument doc = new XWPFDocument(); XWPFParagraph p1 = doc.createParagraph(); p1.setAlignment(ParagraphAlignment.CENTER);//文字对齐方式 /*p1.setBorderBottom(Borders.DOUBLE); p1.setBorderTop(Borders.DOUBLE); p1.setBorderRight(Borders.DOUBLE); p1.setBorderLeft(Borders.DOUBLE); p1.setBorderBetween(Borders.SINGLE);*/ p1.setVerticalAlignment(TextAlignment.TOP); XWPFRun r1 = p1.createRun(); r1.setText("我是第一条测试数据"); r1.setBold(true);//是否加粗 r1.setFontFamily("宋体");//字体类型 r1.setFontSize(16);//字体大小 r1.setUnderline(UnderlinePatterns.DOT_DOT_DASH);//字体是否有下划线 r1.addBreak();//换行 r1.setTextPosition(400);//上下两行文字之间间隔 XWPFParagraph p2 = doc.createParagraph(); p2.setAlignment(ParagraphAlignment.RIGHT); //BORDERS p2.setBorderBottom(Borders.DOUBLE); p2.setBorderTop(Borders.DOUBLE); p2.setBorderRight(Borders.DOUBLE); p2.setBorderLeft(Borders.DOUBLE); p2.setBorderBetween(Borders.SINGLE); XWPFRun r2 = p2.createRun(); r2.setText("我是第二条测试数据"); r2.setStrike(true); r2.setFontSize(20); FileOutputStream out = new FileOutputStream("d:\\word\\test.docx"); doc.write(out); out.close(); } }