使用阿里的EasyExcel实现表格导出功能

在项目B端中,经常会有Excel表格导入导出功能,java中的Apache POI 是一个针对Excel功能非常好的操作库。关于POI网上也有很多的文章,这里主要说一下阿里的EasyExcel实现导表功能;

之前我们项目中的Excel导出功能使用的是poi userModel模式,相信在过去的一段时间中,应该也有不少的项目采用的是这种模式,此种模式的解析速度很快,但是弊端也很大,如果表数据量一旦很大内存就很容易爆掉了。因为userModel的数据解析类似于Dom方式解析,将数据全部加载到内存,然后生成Dom树的过程。

注意:userModel是将所有数据全部加载到内存中进行解析,所以他的解析速度快,内存消耗非常大!但是这也是可能导致OOM(内存溢出)的原因。

导表OOM的解决方案:

1.将数据量减小,比如分批次导出(原来你导的一周的数据分成按天导出,数据量就能小很多)

2.前端js导表

3.阿里EasyExcel

这里着重谈一下阿里EasyExcel工具类:

导表的效果如图:

这里说明一下:上面表格样式最终的呈现需要在实体类上使用部分注解配合,可以通过下面的注解来设置行高列宽,设置标题名和主标题名。

下面是我在项目中针对导表使用到的工具类(因为项目中只用到导出暂时没有表格导入,所以这里我就没写导入了)


/**
 * @Author: LQ
 * @Date: 2019/9/25 16:17
 */
public class EasyExcelUtils {

	/**
	 * 导出Excel(一个sheet)
	 *
	 * @param response  HttpServletResponse
	 * @param list      数据list
	 * @param fileName  导出的文件名
	 * @param sheetName 导入文件的sheet名
	 * @param clazz     实体类
	 */
	public static <T> void writeExcel(HttpServletResponse response, List<T> list, String fileName, String sheetName, Class<T> clazz) {

		OutputStream outputStream = getOutputStream(response, fileName);

		ExcelWriter excelWriter = EasyExcel.write(outputStream, clazz).build();
		WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();

		excelWriter.write(list, writeSheet);

		excelWriter.finish();
	}

	public static <T> void writeStyleExcel(List<T> list, String fileName, String sheetName, Class<T> clazz) {
		// 头的策略
		WriteCellStyle headWriteCellStyle = new WriteCellStyle();
		// 背景设置为红色
		headWriteCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
		headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
		WriteFont headWriteFont = new WriteFont();
		headWriteFont.setFontHeightInPoints((short) 10);
		headWriteFont.setFontName("宋体");
		headWriteCellStyle.setWriteFont(headWriteFont);

		// 内容的策略
		WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
		contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
		contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
		contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
		contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
		contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
		// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
		contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
		// 背景绿色
		contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
		WriteFont contentWriteFont = new WriteFont();
		// 字体大小
		contentWriteFont.setFontHeightInPoints((short) 10);
		contentWriteFont.setFontName("宋体");
		contentWriteCellStyle.setWriteFont(contentWriteFont);
		// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
		HorizontalCellStyleStrategy horizontalCellStyleStrategy =
				new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

		// 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
		EasyExcel.write(fileName, clazz).registerWriteHandler(horizontalCellStyleStrategy).sheet(sheetName)
				.doWrite(list);
	}


	/**
	 * 导出Excel(带样式)
	 *
	 * @return
	 */
	public static <T> void writeStyleExcel(HttpServletResponse response, List<T> list, String fileName, String sheetName, Class<T> clazz) {
		// 头的策略
		WriteCellStyle headWriteCellStyle = new WriteCellStyle();
		// 背景设置为红色
		headWriteCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
		headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
		WriteFont headWriteFont = new WriteFont();
		headWriteFont.setFontHeightInPoints((short) 10);
		headWriteFont.setFontName("宋体");
		headWriteCellStyle.setWriteFont(headWriteFont);

		// 内容的策略
		WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
		contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
		contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
		contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
		contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
		contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
		// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
		contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);

		// 背景绿色
		contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
		WriteFont contentWriteFont = new WriteFont();
		// 字体大小
		contentWriteFont.setFontHeightInPoints((short) 10);
		contentWriteFont.setFontName("宋体");
		contentWriteCellStyle.setWriteFont(contentWriteFont);
		// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现

		HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

		OutputStream outputStream = getOutputStream(response, fileName);
		EasyExcel.write(outputStream, clazz).registerWriteHandler(horizontalCellStyleStrategy).sheet(sheetName).doWrite(list);

	}


	/**
	 * 导出时生成OutputStream
	 */
	private static OutputStream getOutputStream(HttpServletResponse response, String fileName) {
		//创建本地文件
		String filePath = fileName + ".xlsx";
		File file = new File(filePath);
		try {
			if (!file.exists() || file.isDirectory()) {
				file.createNewFile();
			}
			fileName = new String(filePath.getBytes(), "ISO-8859-1");
			response.addHeader("Content-Disposition", "filename=" + fileName);
			return response.getOutputStream();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

除了阿里的easyexcel,在我另一篇文章:https://blog.csdn.net/qq_43655835/article/details/102371136 中也有对excel导入导出的工具类封装,两种封装最终都能实现表格导出,封装方式有差别,可以根据自己的需要来使用。

原文地址:https://www.cnblogs.com/wgty/p/12810498.html