前言: 要做一个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.youkuaiyun.com/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();
}
}