两种方式实现java生成Excel
Web应用中难免会遇到需要将数据导出并生成excel文件的需求。同样,对于本博客中的总结,也是建立在为了完成这样的一个需求,才开始去了解其实现形式,并且顺利完成需求的开发,先将实现过程总结于此。本博文是本人的劳动成果所得,在博客园总结分享,欢迎转载。在没有作者的书面说明的情况下,必须保留本段声明。作者:itRed 邮箱:it_red@sina.com 博客链接:http://www.cnblogs.com/itred GitHub链接:http://github.com/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的源码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>导出</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<form action="getXls_excel" method="post">
<input type="submit" value="提交" />
</form>
</body>
</html>
然后新建action名为ExcelAction,源码如下:
package com.red.action; import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /**
* jsp形式导出excel
* @author Red
*/
public class ExcelAction extends ActionSupport { private static final long serialVersionUID = -3673769122296267756L; protected HttpServletRequest request = ServletActionContext.getRequest();
protected HttpServletResponse response = ServletActionContext.getResponse(); public void getXls() throws IOException {
StringBuffer sb = new StringBuffer();
sb.append("<table><tr><td>用户名称</td><td>邮箱地址</td></tr>");
Map<String, String> map = new HashMap<String, String>();
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("<tr><td>").append(key).append("</td><td>").append(map.get(key)).append("</td></tr>");
}
request.getSession().setAttribute("excel", sb.toString());
response.sendRedirect(request.getContextPath() + "/export.jsp");
}
}
然后新建一个跳转后的jsp页面,也即是处理excel文件的工具。源码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page contentType="application/msexcel"%>
<%
response.setContentType("application/msexcel;charset=UTF-8");
response.setHeader("Content-disposition", "attachment; filename=test.xls");
%>
<html>
<head>
<title>Excel</title>
</head>
<body>
<%
String str = new String(session.getAttribute("excel").toString());
out.print(str);
%>
</body>
</html>
在这里导出的文档编码是根据本地电脑的编码形式进行编码的,所以,如果本地是中文则需要修改response.setContentType("application/msexcel;charset=UTF-8");中的编码,将其改为GBK或者GB18030,只要支持中文就行。
功能实现,基本效果如下:

Demo2:
第二种方式是直接通过流的形式响应客户端浏览器,通过浏览器来提供下载。只是在这个地方,将ContentType设置在了action中,而并非是在jsp页面上。
加入JXL的jar包,Action源码:
package com.red.action; import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jxl.Workbook;
import jxl.format.UnderlineStyle;
import jxl.write.Colour;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /**
* 第三方插件导出Excel
* @author Red
*/
public class WriteExcelAction extends ActionSupport {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse(); public void writeExcel() throws RowsExceededException, 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 = new WritableCellFormat(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 = new WritableCellFormat(wfont); // 开始生成主体内容
wsheet.addCell(new Label(0, 2, "姓名"));
wsheet.addCell(new Label(1, 2, "邮箱"));
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Map<String, String> map = new HashMap<String, String>();
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 |
两种方式实现java生成Excel的更多相关文章
- java 下载文件的两种方式和java文件的上传
一:以网络的方式下载文件 try { // path是指欲下载的文件的路径. File file = new File(path); // 以流的形式下载文件. InputStream fis = n ...
- Java中HashMap遍历的两种方式
Java中HashMap遍历的两种方式 转]Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: ...
- Xamarin Android Activity全屏的两种方式
方式一 直接在Activity的Attribute中定义 如下 在 MainActivity 中 [Activity(Label = "app", MainLauncher = t ...
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- Java并发--线程间协作的两种方式:wait、notify、notifyAll和Condition
在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界 ...
- java的取出map里所有元素的两种方式
/* * 取出map元素的两种方式 */package com.map.test; import java.util.HashMap;import java.util.Iterator;import ...
- 一步步分析Java深拷贝的两种方式-clone和序列化
今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clon ...
- java打jar包和运行jar包的两种方式
java打jar包和运行jar包的两种方式更详细的打包方式请参考https://www.cnblogs.com/mq0036/p/8566427.html 一.java类不依赖第三方jar包以简单的一 ...
随机推荐
- NiceMark——我的Markdown编辑器
NiceMark--我的Markdown编辑器 闲来无事,写了一个Markdown编辑器.基于electron,完全采用Web前段技术(Html,css,JavaScript)实现.代码已托管在Git ...
- 3.Windows Server 2012 R2数据库部署
很多人竟然不会安装数据库....好吧,来个图文教程,其实和windows里面一样安装,和安装2008一样的 先安装3.5:http://www.cnblogs.com/dunitian/p/53487 ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
- WebGIS项目中利用mysql控制点库进行千万条数据坐标转换时的分表分区优化方案
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 项目中有1000万条历史案卷,为某地方坐标系数据,我们的真实 ...
- pt-heartbeat
pt-heartbeat是用来监测主从延迟的情况的,众所周知,传统的通过show slave status\G命令中的Seconds_Behind_Master值来判断主从延迟并不靠谱. pt-hea ...
- scala练习题1 基础知识
1, 在scala REPL中输入3. 然后按下tab键,有哪些方法可以被调用? 24个方法可以被调用, 8个基本类型: 基本的操作符, 等: 2,在scala REPL中,计算3的平方根,然 ...
- 软件工程(C编码实践篇)学习心得
孟繁琛 + 原创作品转载请注明出处 + <软件工程(C编码实践篇)>MOOC课程 http://mooc.study.163.com/course/USTC-1000002006 软件工程 ...
- 分享一个php的启动关闭脚本(原)
自己简单写的一个php服务的启动脚本和大家分享 思路(实现的原理): 1:function模块+case语句多分支判断 2:通过添加# chkconfig: 2345 43 89注释实现开机自启动(前 ...
- tg2015 信息传递 (洛谷p2661)
题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...
- Xamarin开发Android应用打包apk
Visual Studio中用Xamarin开发Android应用,生成apk文件有3种方法 1.debug时,代码目录下bin\Debug中会自动生成调试用***-Signed.apk文件,但是文件 ...