新手上路,经过查询其他博客的poi导出,自己写了一个限制条件特别多的封装类,同时又特别实用,希望能帮助大家。
- 如果使用的不是SSM框架,简单更改代码即可,工具类无需改变。
我使用的框架是maven搭建的SSM框架
导入poi依赖,这里使用的是老版本稳定的poi依赖。
最新稳定版本是4.0
下载jar包可以去官网下载
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.6</version>
</dependency>
为什么要说我写的这个封装类是个限制条件特别多的封装类呢?
首先,Mybaits配置文件查询返回值必须是LinkedHashMap类型,无需使用任何实体类。
将在最后讲述为什么使用LinkedHashMap类型
Mybatis配置文件:
DAO层,service层
方法返回值均为List<map<String,Object>> 类型
控制器代码:
控制器代码比较简单,只需要将response和list传入进工具类即可。
@Controller
public class XController {
@Resource
private XService xserivce;
@RequestMapping("/findAll")
public String findAll(HttpServletRequest request,HttpServletResponse response) {
List<Map<String,Object>> list = xserivce.findAll();
HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook(response,list);
return "index";
}
}
excel导出工具类:
public class ExcelUtil {
/**
*
* @author [email protected]
* @param response
* @param list
* @return HSSFWorkbook
*/
public static HSSFWorkbook getHSSFWorkbook(HttpServletResponse response, List<Map<String, Object>> list) {
// 生成文件名称
String fileName = System.currentTimeMillis() + RandomUtils.nextInt(100000) + ".xls";
// 获取标题内容
Set<String> set = new LinkedHashSet<String>();
Set<String> sets = new LinkedHashSet<String>();
for (int i = 0; i < list.size(); i++) {
set = list.get(i).keySet();
for (String value : set) {
sets.add(value);
}
}
for (int i = 0; i < list.size(); i++) {
for (String s : sets) {
if (list.get(i).get(s) == null || list.get(i).get(s) == "") {
list.get(i).put(s, "");
}
}
}
// 创建标题长度
String title[] = new String[sets.size()];
// 标题内容赋值(赋值,未创建标题)
int titleSize = 0;
for (String s : sets) {
title[titleSize++] = s;
}
// 第一步,创建一个HSSFWorkbook,对应一个Excel文件
HSSFWorkbook wb = new HSSFWorkbook();
// 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
HSSFSheet sheet = wb.createSheet("sheet");
// 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制
HSSFRow row = sheet.createRow(0);
// 第四步,创建单元格,并设置值表头 设置表头居中
HSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式
// 声明列对象
HSSFCell cell = null;
// 创建标题
for (int i = 0; i < title.length; i++) {
cell = row.createCell(i);
cell.setCellValue(title[i]);
cell.setCellStyle(style);
}
// 创建内容
for (int i = 0; i < list.size(); i++) {
row = sheet.createRow(i + 1);
int j = 0;
for (String s : sets) {
row.createCell(j++).setCellValue(list.get(i).get(s).toString());
}
}
try {
setResponseHeader(response, fileName);
OutputStream os = response.getOutputStream();
wb.write(os);
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
return wb;
}
public static void setResponseHeader(HttpServletResponse response, String fileName) {
try {
try {
fileName = new String(fileName.getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
response.setContentType("application/octet-stream;charset=ISO8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.addHeader("Pargam", "no-cache");
response.addHeader("Cache-Control", "no-cache");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
最后要在最后跳转的JSP页面添加上
<%
out.clear();
out = pageContext.pushBody();
%>
否则会出现如下错误:
报错原因:
产生这样的异常原因:是web容器生成的servlet代码中有out.write(""),
这个和JSP中调用的response.getOutputStream()产生冲突.即Servlet规范说明,
不能既调用response.getOutputStream(),又调用response.getWriter(),
无论先调用哪一个,在调用第二个时候应会抛出IllegalStateException,因为在jsp中,
out变量实际上是通过response.getWriter得到的,你的程序中既用了response.getOutputStream,又用了out变量,故出现以上错误。
作者:安_shuai
来源:CSDN
原文:https://blog.csdn.net/xyajia/article/details/78730751
版权声明:本文为博主原创文章,转载请附上博文链接!
这里引用其他博主文章,不再进行多余解释
最后讲述一下为什么要使用sql返回值为什么使用LinkedHashMap,LinkedHashMap的Key和Value都允许空,LinkedHashMap会按从数据库查询时的顺序进行存储,这样查询到的数据就不会顺序颠倒。HashMap会导致我们excel表内的内容乱套,比如三个字段id,name,pass。其中一条数据id值为1,name值为“小明”,pass值为123456,那么excel表内就会出现这样的情况
name | id | pass |
---|---|---|
小明 | 1 | 123456 |
使用LinkedHashMap就不会出现这种情况,我还尝试过TreeMap,效果同样不理想。
哪里有不足希望大家多多提一下意见,我会努力完善的。