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
博客:http://itred.cnblogs.com
GitHub:https://github.com/itRed
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段说明,
且在文章明显位置给出原文链接,否则保留追究法律责任的权利。

两种方式实现java生成Excel的更多相关文章

  1. java 下载文件的两种方式和java文件的上传

    一:以网络的方式下载文件 try { // path是指欲下载的文件的路径. File file = new File(path); // 以流的形式下载文件. InputStream fis = n ...

  2. Java中HashMap遍历的两种方式

    Java中HashMap遍历的两种方式 转]Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: ...

  3. Xamarin Android Activity全屏的两种方式

    方式一 直接在Activity的Attribute中定义 如下 在 MainActivity 中 [Activity(Label = "app", MainLauncher = t ...

  4. Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  5. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  6. Java并发--线程间协作的两种方式:wait、notify、notifyAll和Condition

    在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界 ...

  7. java的取出map里所有元素的两种方式

    /* * 取出map元素的两种方式 */package com.map.test; import java.util.HashMap;import java.util.Iterator;import ...

  8. 一步步分析Java深拷贝的两种方式-clone和序列化

    今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clon ...

  9. java打jar包和运行jar包的两种方式

    java打jar包和运行jar包的两种方式更详细的打包方式请参考https://www.cnblogs.com/mq0036/p/8566427.html 一.java类不依赖第三方jar包以简单的一 ...

随机推荐

  1. Ajax 概念 分析 举例

    Ajax是结合了访问数据库,数据访问,Jquery 可以做页面局部刷新或者说是页面不刷新,我可以让页面不刷新,仅仅是数据的刷新,没有频繁的刷页面,是现在比较常用的一种方式做页面那么它是怎么实现页面无刷 ...

  2. 水印第三版 ~ 变态水印(这次用Magick.NET来实现,附需求分析和源码)

    技能 汇总:http://www.cnblogs.com/dunitian/p/4822808.html#skill 以前的水印,只是简单走起,用的是原生态的方法.现在各种变态水印,于是就不再用原生态 ...

  3. inline-block元素间距问题的几种解决方案

    不知道大家有没有碰到过设置了display:inline-block;的几个相邻元素之间有几px间距的问题,这里提供几种简单实用的解决方法,希望能够帮到大家!   方法1. 将<li>标签 ...

  4. Smarty的基本使用与总结

    含义: Smarty是PHP的一个引擎模板,可以更好的进行逻辑与显示的分离,即我们常说的MVC,这个引擎的作用就是将C分离出来. 环境需求:PHP5.2或者更高版本 我使用的环境是:PHP5.3,wi ...

  5. AFNetworking 3.0 源码解读(七)之 AFAutoPurgingImageCache

    这篇我们就要介绍AFAutoPurgingImageCache这个类了.这个类给了我们临时管理图片内存的能力. 前言 假如说我们要写一个通用的网络框架,除了必备的请求数据的方法外,必须提供一个下载器来 ...

  6. 用javascript 写个函数返回一个页面里共使用了多少种HTML 标签

    今天我无意间看到一个面试题: 如何用javascript 写个函数返回一个页面里共使用了多少种HTML 标签? 不知你看到 是否蒙B了,如果是我 面试,肯定脑子嗡嗡的响.... 网上搜了搜也没有找到答 ...

  7. Chrome V8引擎系列随笔 (1):Math.Random()函数概览

    先让大家来看一幅图,这幅图是V8引擎4.7版本和4.9版本Math.Random()函数的值的分布图,我可以这么理解 .从下图中,也许你会认为这是个二维码?其实这幅图告诉我们一个道理,第二张图的点的分 ...

  8. 【转】外部应用和drools-wb6.1集成解决方案

    一.手把手教你集成外部应用和drools workbench6.1 1.         首先按照官方文档安装workbench ,我用的是最完整版的jbpm6-console的平台系统,里面既包含j ...

  9. Android Studio:Failed to resolve ***

    更换电脑后,也更新了所有的SDK的tool,仍然报错:Failed to resolve  各种jar包,出现这种问题主要是因为在Android studio中默认不允许在线更新,修改方法如下:

  10. Ubuntu安装redis并配置远程、密码以及开启php扩展

    一.前言 redis是当前流行的nosql数据库,很多网站都用它来做缓存,今天我们来安装并配置下redis 二.安装并配置redis 1.安装redis sudo apt-get install re ...