SSM POI Excel导出 封装类拿走直接用

新手上路,经过查询其他博客的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,效果同样不理想。

哪里有不足希望大家多多提一下意见,我会努力完善的。

猜你喜欢

转载自blog.csdn.net/qq_43510878/article/details/84678880