SpringBoot整合easyPOI导出Excel模板
1.需求
导出上图这个格式的excel,原生的Apache POI需要对模板样式进行编写比较繁琐,不同的模板还需要重新改动代码,所以我想到了easyPOI,他上手简单只需要写很少的代码即可达到你想要的需求,但是他只能读取Excel的文件路径,这是一个坑,后面就踩到了!!!
2.整合
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
导入上方依赖即可,如果有别的poi依赖可能会有jar包冲突!!
3.Excel模板
我们会发现,表格中的数据都是通过{{xxx}}获取,easypoi是通过map键值对的形式取值,对于需要循环的数据,通过easypoi规定的表达式
模板以{{$fe:maplist 开头,以}}结尾,代表变遍历数据的意思,每个字段前面的t.前缀是easypoi指定的默认值。
fe后面的maplist一定要与后台定义的键对应上.基本的功能到这里就结束了.想以什么样的形式导出,只需要自定义模板即可。
注意:这里的任何一个值都不能为空,如果为空会报WorkBook对象空指针。
4.生产环境所遇到的问题
因为我的模板是放在项目里面的,在windows环境下可以读取到excel模板。但是在linux系统中不行,于是乎我打开了度娘找了很多方法,最后找了一个比较有效的方法。
首先,我们将模板上传到阿里云服务器中,拿到它的网络地址(Http开头的,后面的读取方式就不可以使用new File(url)读取了),然后创建一个临时目录存储模板文件,通过读取临时文件的url的方式进行读取文件。话不多说直接上代码~
参考博客:https://blog.youkuaiyun.com/hzygcs/article/details/85100608`
try {
URL url = new URL("http://file.hne.com/excel/2020/07/09/63392222dca54054cd5f8/thinkAnswer.xlsx");
InputStream inputStream = new BufferedInputStream(url.openStream());
// 模板临时目录
String rootPath = request.getServletContext().getRealPath("template_temp/");
//临时文件名
String filePath = rootPath + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "thinkScore";
tempFile = new File(filePath);
//保存临时文件
ReportUtils.saveTempFile(inputStream,tempFile);
TemplateExportParams params = new TemplateExportParams(filePath);
String fileName = student.getTrueName()+"思考题成绩详情.xlsx";
//浏览器下载方法
ReportUtils.export(response,workBook,fileName);
} catch (IOException e) {
logger.error("api/teacherExperiment/exportExcelWithPrepareAnswer:导出思考题Excel失败"+e.getMessage());
return new FebsResponse().fail().message("导出思考题Excel失败");
} finally{
// 删除临时文件
if (tempFile.exists()) {
tempFile.delete();
}
}
return new FebsResponse().success().message("导出思考题Excel成功");
}
工具类
public class ReportUtils {
// Excel 导出 通过浏览器下载的形式
public static void export(HttpServletResponse response, Workbook workbook, String fileName) throws IOException {
response.setHeader("Content-Disposition",
"attachment;filename=" + new String(fileName.getBytes("UTF-8"), "iso8859-1"));
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
BufferedOutputStream bufferedOutPut = new BufferedOutputStream(response.getOutputStream());
workbook.write(bufferedOutPut);
bufferedOutPut.flush();
bufferedOutPut.close();
}
// 保存到临时目录
public static void saveTempFile(InputStream inputStream, File tempFile) throws IOException {
if(!tempFile.getParentFile().exists()){ //如果文件的目录不存在
tempFile.getParentFile().mkdirs(); //创建目录
}
OutputStream os = new FileOutputStream(tempFile);
byte[] b = new byte[2048];
int length;
while ((length = inputStream.read(b)) > 0) {
os.write(b, 0, length);
}
os.flush();
os.close();
inputStream.close();
}
}