两种方式实现java生成Excel

时间:2021-08-31 00:40:10

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,只要支持中文就行。

功能实现,基本效果如下:

      两种方式实现java生成Excel

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(); // 关闭流
}
}

实现效果如下:

      两种方式实现java生成Excel

在完成以上两个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. 白话Https

    本文试图以通俗易通的方式介绍Https的工作原理,不纠结具体的术语,不考证严格的流程.我相信弄懂了原理之后,到了具体操作和实现的时候,方向就不会错,然后条条大路通罗马.阅读文本需要提前大致了解对称加密 ...

  2. Nancy 引用源码与NuGet安装差异

    使用NuGet安装Nancy和直接引用源码项目存在一些差异,如序列化,授权验证问题. 如果引用源码的话,自定义JsonSerializer,如下: 注意,需要使用NuGet安装Newtonsoft.J ...

  3. 由于无法创建应用程序域,因此未能执行请求。错误&colon; 0x80070002 系统找不到指定的文件

    前两天安装了一堆补丁后突然发现,原本正常使用了一年的应用系统打不开了,到事件日志中发现有.net framewok 2.0的补丁安装失败的日志,于从从重装补丁开始.到重新注册.net框架,再到所有.n ...

  4. sqlserver快照,启用基于行版本控制的隔离级别

    在sqlserver标准的已提交读(read committed)隔离级别下,读写操作相互阻塞.未提交读(read uncommitted)虽然不会有这种阻塞,但是读操作可能会读到脏数据,这是大部分用 ...

  5. 转:设置Loadrunner负载机临时文件目录

    最近在跑稳定性测试 3 X 24小时的时候,发现负载机产生的日志还运行记录等等竟然有100多G! C盘空间不足,但是D盘还有700多G空间呢,怎么让临时文件转移到D盘? 此处分两种情况: 一. 修改本 ...

  6. 2015 多校联赛 ——HDU5301(技巧)

    Your current task is to make a ground plan for a residential building located in HZXJHS. So you must ...

  7. 大数据项目测试&lt&semi;二&gt&semi;项目的测试工作

    大数据的测试工作: 1.模块的单独测试 2.模块间的联调测试 3.系统的性能测试:内存泄露.磁盘占用.计算效率 4.数据验证(核心) 下面对各个模块的测试工作进行单独讲解. 0. 功能测试 1. 性能 ...

  8. &lbrack;转&rsqb;Node&period;JS使用Sequelize操作MySQL

    Sequelize官方文档  https://sequelize.readthedocs.io/en/latest/ 本文转自:https://www.jianshu.com/p/797e10fe23 ...

  9. 《Python数据可视化编程实战》

    第一章:准备工作环境 WinPython-32bit-3.5.2.2Qt5.exe 1.1 设置matplotlib参数 配置模板以方便各项目共享 D:\Bin\WinPython-32bit-3.5 ...

  10. 编写高质量代码改善C&num;程序的157个建议——建议102:区分接口和抽象类的应用场合

    建议102:区分接口和抽象类的应用场合 接口和抽象类有一些显而易见的区别: 接口支持多继承,抽象类则不能. 接口可以包含方法.属性.索引器.事件的签名,但不能有实现,抽象类则可以. 接口在增加新方法后 ...