前言
这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战 。
需求分析
将省份详情信息作为数据源导出 Excel
,要求表头为中文,全部内容宽度实现自适应,并设置工作簿名称为省份表,导出文件名设置为导出省份信息。
代码实现
首先,分析表头字段包含哪些,写对应的 VO
对象:
1 | java复制代码/** |
然后,就是根据所需信息写 SQL
进行查询,具体写法参见我的文章 【MP】还在用 QueryWrapper 吗? - 掘金 (juejin.cn) ,具体写法不作赘述!
其次,写 Service
层,导出需要数据源,先得获取所有省份详情信息,作为导出 Excel
的数据源。
1 | java复制代码/** |
有数据源还不行,还得将其写入到 Excel
当中,作为一个接口,调用后客户端下载该文件,所以要用到 HttpServletResponse
设置响应头和响应体信息。
接着,实现接口中的方法,这一步很关键,导出的格式、异常亦或是数据问题都出在这个地方,一定要考虑周全!!
1 | java复制代码@Override |
CollUtil.removeNull(provinces)
很关键!倘若数据库表中有空记录的话,这里不做移除就会引发 NPE
异常,这里做一个过滤操作,保险起见。
这里选择使用 BigWriter
而不是使用 Writer
,主要是因为前者不容易引发内存溢出,对于大量数据的输出更为安全、可靠,虽然数据源的量并不大,用着舒心就完事了,并不用担心和 ExcelWriter
用法不一致。
1 | java复制代码@Override |
设置表头别名,ExcelWriter
类提供了两种方法,一种是上面代码给出的,另一种则是通过键值对的方式进行设置,具体见 Hutool 工具不糊涂 - 掘金 (juejin.cn) ExcelUtil
Excel
操作工具类,不过要注意的是使用无序的 HashMap
入参表头也跟着无序,需使用 LinkedHashMap
来保证保存的有序性。
表头别名设置好后,直接向 Excel
的 Workbook
中写入数据源即可,写入完后要响应客户端,写出文件到客户端,所以需要设置响应体和响应头,在响应头中传入导出文件名,如果是中文文件名的话,需要进行编码不能直接塞入,否则会出现文件名乱码问题,这时你就能看到弹出的下载框,点击后就能成功看到导出的数据列表了。
1 | java复制代码 |
注意: 只有调用 flush
或者 close
方法后才会真正写出文件,并释放 Workbook
对象资源,否则带有数据的 Workbook
一直会常驻内存。
最后,在控制层暴露接口给前端进行调用:
1 | java复制代码@GetMapping("provinces/excel/export") |
激动的心,颤抖的手,点击 SEND
按钮:
不看不知道,一看吓一跳:
摆在我眼前的问题该如何去解决呢?
一行代码 excelWriter.autoSizeColumnAll();
??并不能设置所有的列框为自动根据内容进行调整,于是被度娘告知需开启自动跟踪所有列自动调整大小,所以我们首先的获取当前 Sheet
:
1 | java复制代码 |
这里需要将 Sheet
强转成 SXSSFSheet
类型,开启方法是属于 SXSSFSheet
类的
1 | java复制代码 |
解决中文自适应宽度不足的问题,对已定义的每一列设置列宽:
1 | java复制代码 |
接口测试
完美,撒花 ✿✿ヽ(°▽°)ノ✿
总结 & 思考
虽然实现了预期需求,但是我觉得还不够完美,代码不够优雅、简洁,并不具备通用性!!
如果导出的是其他数据列表呢,上述代码也不能照搬照抄的呀,所以说复用性较差,为了能优雅地对指定数据类型进行表格的导出,就必须对 Hutool
中的 ExcelUtil
进行二次封装或者自己站在 POI
包上造轮子,考虑到发量我毅然决然选择第一种方案,这波直接站在巨人的巨人的肩膀上进行开发。
考虑到 导出的效率 、 功能扩展性 以及 使用便捷性 ,在封装的基础上写一个自定义 @Excel
注解,实现一“解”多用,麻麻再也不用担心我不会写 Excel
导出接口了 (^-^)V
具体实现代码详解,请参考 【ExcelUtil】二次封装,注解驱动,用起来不要太舒服! - 掘金 (juejin.cn) 。
对 Hutool
工具包中常用工具类(ExcelUtil…)有疑问,移步至 Hutool 工具不糊涂 - 掘金 (juejin.cn) 。
结尾
撰文不易,欢迎大家点赞、评论,你的关注、点赞是我坚持的不懈动力,感谢大家能够看到这里!Peace & Love。
本文转载自: 掘金