Web应用中难免会遇到需要将数据导出并生成excel文件的需求。同样,对于本博客中的总结,也是建立在为了完成这样的一个需求,才开始去了解其实现形式,并且顺利完成需求的开发,先将实现过程总结于此。本博文是本人的劳动成果所得,在博客园总结分享,欢迎转载。在没有作者的书面说明的情况下,必须保留本段声明。作者:itRed 邮箱:
根据自己的梳理,完成这样的需求在自己的技术范围之内比较认可的有两种方式,其一是利用第三方插件JXL实现excel文件的生成,另一种方式则是不需要第三方的插件,直接通过jsp页面的设置和action层的response跳转完成excel文件的生成。综合来讲,采用第三方插件不仅能够满足功能性需求,而且还提供函数、字体、颜色及其他方面的接口,如果直接采用jsp跳转形式,则样式会略显低调,但是其实现形式很容易理解,无需了解更多的技术层面的东西。现将两种具体的实现方式列出:
Demo 1:
首先来个简单易懂的。直接在action中将数据放到session服务器缓存中,然后再跳转到指定的jsp页面,在指定的jsp页面中设置其ContentType,这个会牵扯到http协议的response.ContentType 。不同的ContentType会影响到客户端看到的具体效果,默认的ContentType为text/html,也就是最为常见的网页格式。
新建web项目,加入struts2的相关jar包, 在默认的index.jsp页面加入一个form表单,本案例仅仅完成功能,数据在后台已经封装好,无前端交互,直接input一个提交按钮,转向action。index.jsp的源码如下:
Stringpath=request.getContextPath();StringbasePath=request.getScheme()+ "://" +request.getServerName()+ ":" +request.getServerPort()+path+ "/";%>
">
导出然后新建action名为ExcelAction,源码如下:
packagecom.red.action;importjava.io.IOException;importjava.util.HashMap;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importorg.apache.struts2.ServletActionContext;importcom.opensymphony.xwork2.ActionSupport;/*** jsp形式导出excel
*@authorRed*/
public class ExcelAction extendsActionSupport {private static final long serialVersionUID = -3673769122296267756L;protected HttpServletRequest request =ServletActionContext.getRequest();protected HttpServletResponse response =ServletActionContext.getResponse();public void getXls() throwsIOException {
StringBuffer sb= newStringBuffer();
sb.append("
用户名称 | 邮箱地址 |
Map map = new HashMap();
map.put("red1", "it_red@sina.com");
map.put("red2", "it_red@sohu.com");
map.put("red3", "it_red@163.com");for(String key : map.keySet()) {
sb.append("
").append(key).append("").append(map.get(key)).append("");}
request.getSession().setAttribute("excel", sb.toString());
response.sendRedirect(request.getContextPath()+ "/export.jsp");
}
}
然后新建一个跳转后的jsp页面,也即是处理excel文件的工具。源码如下:
response.setHeader("Content-disposition","attachment; filename=test.xls");%>
ExcelStringstr= new String(session.getAttribute("excel").toString());
out.print(str);%>
在这里导出的文档编码是根据本地电脑的编码形式进行编码的,所以,如果本地是中文则需要修改response.setContentType("application/msexcel;charset=UTF-8");中的编码,将其改为GBK或者GB18030,只要支持中文就行。
功能实现,基本效果如下:
Demo2:
第二种方式是直接通过流的形式响应客户端浏览器,通过浏览器来提供下载。只是在这个地方,将ContentType设置在了action中,而并非是在jsp页面上。
加入JXL的jar包,Action源码:
packagecom.red.action;importjava.io.IOException;importjava.io.OutputStream;importjava.util.HashMap;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjxl.Workbook;importjxl.format.UnderlineStyle;importjxl.write.Colour;importjxl.write.Label;importjxl.write.WritableCellFormat;importjxl.write.WritableFont;importjxl.write.WritableSheet;importjxl.write.WritableWorkbook;importjxl.write.WriteException;importjxl.write.biff.RowsExceededException;importorg.apache.struts2.ServletActionContext;importcom.opensymphony.xwork2.ActionSupport;/*** 第三方插件导出Excel
*@authorRed*/
public class WriteExcelAction extendsActionSupport {
HttpServletRequest request=ServletActionContext.getRequest();
HttpServletResponse response=ServletActionContext.getResponse();public void writeExcel() throwsRowsExceededException, WriteException, IOException {
OutputStream os= response.getOutputStream();//取得输出流
response.reset();//清空输出流
response.setHeader("Content-disposition", "attachment; filename=testRed.xls");//设定输出文件头
response.setContentType("application/msexcel");//定义输出类型
WritableWorkbook wbook= Workbook.createWorkbook(os); //建立excel文件
String tmptitle = "测试数据"; //标题
WritableSheet wsheet = wbook.createSheet(tmptitle, 0); //sheet名称//设置excel标题
WritableFont wfont = new WritableFont(WritableFont.ARIAL, 16, WritableFont.BOLD, false,
UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
WritableCellFormat wcfFC= newWritableCellFormat(wfont);
wcfFC.setBackground(Colour.AQUA);
wsheet.addCell(new Label(1, 0, tmptitle, wcfFC));
wfont= new jxl.write.WritableFont(WritableFont.ARIAL, 14, WritableFont.BOLD, false,
UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
wcfFC= newWritableCellFormat(wfont);//开始生成主体内容
wsheet.addCell(new Label(0, 2, "姓名"));
wsheet.addCell(new Label(1, 2, "邮箱"));//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Map map = new HashMap();
map.put("Red1", "it_red@sina.com");
map.put("Red2", "it_red@sohu.com");
map.put("Red3", "it_red@163.com");int count = 0;for(String key : map.keySet()) {
wsheet.addCell(new Label(0, count + 3, key));
wsheet.addCell(new Label(1, count + 3, map.get(key)));
count++;
}//主体内容生成结束
wbook.write(); //写入文件
wbook.close();
os.close();//关闭流
}
}
实现效果如下:
在完成以上两个Demo之后,打开其生成的excel文件,很容易看到两者的差别。其实对于究竟选择哪种形式来生成excel文件,还是需要根据实际的开发情况及应用本身来决定的。各有其特点和好处以及缺点。l另外,当你能理解以上代码时,以上代码便不仅仅只能生成excel文件了,自然而然就可以生成一些其他文件。
另附本博文中所涉及到的案例源码请点击链接
作者:itRed
博客:版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段说明,
且在文章明显位置给出原文链接,否则保留追究法律责任的权利。