Java从零开始实现导出excel(完)
新人博主,随笔记录。主要还是通过自己日常工作积累,系统整理一些技术。希望能够节省更多人的时间,走出自己的路。
简述
这一篇文章主要是在Java从零开始实现导出excel(四)的基础上,导出单个excel文件有多个sheet页,且每个sheet的表头格式都不一样。
那么这里的思路是:
- 先将需要导出的所有数据,封装到一个map中。它的key就是excel中sheet页所对应的位置,value则是当前sheet页所需要导出的数据。
- 将所有需要特殊导出的值,同样封装的另一个map中。
- 在获取WriteSheet时,我们需要通过根据sheet页的顺序获取。
创建导出实体
老师
学生
创建模板
这里就不需要关注@ExcelProperty这个注解了。主要还是实体类中的属性值与模板中的属性值对应就好。
导出excel
导出方法
/**
* 使用EasyExcel填充导出多sheet页的excel
* @param response
* @throws Exception
*/
@GetMapping(value = "/exportSheetsExcelByFill")
public void exportSheetsExcelByFill(HttpServletResponse response, HttpSession session) throws Exception {
response.setContentType("multipart/form-data");
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream;charset=utf-8");
LocalDate time = LocalDate.now();
String fileName = URLDecoder.decode("easyExcel导出模板_" + time, "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("gb2312"), "ISO8859-1") + ".xls" + "\"");
OutputStream out = response.getOutputStream();
//封装多个sheet页的数据
List<Teacher> teacherList = getDataTeacher();
List<Student> studentList = getData();
Map<String,List> exportData = new HashMap<>();
exportData.put("0",teacherList);
exportData.put("1",studentList);
//封装需要填充的特殊数据
Map<String,String> data = new HashMap<>();
data.put("year","2022");
//根据模板导出数excel
ExcelUtil.exportSheetsTemplateByFill("templates/schoolTemplate.xls", "schoolModel.xls", out,ExportExcelDemo.class, exportData,data, session);
}
导出工具类
/**
* 根据模板导出excel
* <p>
* 支持列表循环填写excel
* 以及填充多个sheet页,excel中特殊标记的值
*
* @param templatePath 模板路径
* @param temporaryName 临时文件名称
* @param out 文件输出流
* @param col 导出类class
* @param session session
* @param data 填充列表数据
* @param otherData 填充excel特殊单元格值
*/
public static void exportSheetsTemplateByFill(String templatePath, String temporaryName, OutputStream out, Class col, Map<String, List> data, Map<String, String> otherData, HttpSession session) throws IOException {
String path = null;
try {
InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, session);
ExcelWriter excelWriter = EasyExcel.write(out).withTemplate(path).build();
Set<String> sheetNums = data.keySet();
for (String num : sheetNums) {
WriteSheet writeSheet = EasyExcel.writerSheet(Integer.parseInt(num)).build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
//填充列表
excelWriter.fill(data.get(num), fillConfig, writeSheet);
//填充excel中特殊的单元格值
excelWriter.fill(otherData, fillConfig, writeSheet);
}
excelWriter.finish();
} catch (IOException e) {
e.printStackTrace();
} finally {//删除临时文件
if (StringUtils.isNotEmpty(path)) {
File tempFile = new File(path);
tempFile.delete();
System.err.println("删除临时文件成功=====path:" + path);
}
out.close();
}
}
这里有个关键的点
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
可以看下官方给我们的解释:
// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
// 如果数据量大 list不是最后一行 参照下一个
导出结果图
结语
这个系列的文章结束了。我相信这几篇文章,应该可以解决工作中大多数的导出问题。下面我会写一篇导入,既然有了导出那导入是必不可少的。