easyexcel只通过表名来动态查询并动态导出数据
EasyExcel动态表头即动态数据生成
1️⃣ 业务需求
需要将数据库中的所有表放在一个下拉框中,下拉框支持模糊查询到相关的表,然后通过这个表名查询到数据库的数据,切换不同的表查询出来相关表的列和数据
需要注意的点: 1)js实现模糊搜索
2)导出的表头和数据都是动态生成,切换a表就是导出a表的列和数据,切换b表就是b表的列和数据
选择一张表,查询出该表相关表头和数据
点击导出按钮,导出对应数据
选择另外一张表,查询出该表相关表头和数据
实现查询功能较为简单,就是后台查询表头列,然后js for循环实现列加入到table中
js部分
首先我用的框架即版本
spring + mybatis + springmvc + easyexcel实现导出功能,除了easyexcel版本有需要注意,其他的自行版本对应;easyexcel的版本为:
因为easyexcel对poi版本有版本对应,所以你的poi需要升级,poi版本为:
下图为官网版本对应:
接下来就是具体实现过程
这里需要注意的是,registerConverter方法,这个是一个自定义转换器,是用来转换mybatis的hashmap集合,转换的原因是:
由于表格是动态的,他的数据以及表头都是根据你选择的表名来变化的,所以无法定义具体的实体类,所以mybatis那里我们只能写成Map而不是具体的entity
easyexcel导出是不支持hashmap(mybatis,Map会自动转换为hashmap)的,会报一个转换错误的错,所以我们这里需要写转换器
转换器的具体实现:
最后最麻烦的就是数据结构:
最终通过不停的尝试,发现数据结构显示为上图,才会将数据导出来,但是又衍生出来了一个问题,数据导出来的,但是表名和数据匹配是乱的,所以还需要最后的一步就是将字段名和数据列对应
这里我的实现方法是直接循环hashmap,key为头,value为数据,然后各自进一步封装数据结构
接口实现类和mybatis xml的代码就不贴了,就是查询数据库sql,较简单
// 表头
List<List<String>> listHead = new ArrayList<>();
List<List<String>> listHead = new ArrayList<>();
//导出功能 easyexcel 动态头导出 @RequestMapping(value = "/export", method = RequestMethod.GET) public void export(HttpServletResponse response, HttpServletRequest request) throws UnsupportedEncodingException { try { response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setCharacterEncoding("UTF-8"); String fileName = URLEncoder.encode("test", "UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); String tableName = request.getParameter("tableName"); EasyExcel.write(response.getOutputStream()) .registerConverter(new config()) .head(head1(tableName)).sheet("模板") .doWrite(data(tableName )); // 每次导出完清空listHead listHead.clear(); } catch (Exception e) { e.printStackTrace(); } } private List<List<String>> head1(String tableName) { return listHead; } private List<List<Object>> data(String tableName) { // 表格的动态表头 List<String> head = new ArrayList<>(); // 表格内的数据 List<Map<String, Object>> dataHead = DataSelectService.findAllMap(tableName); List<List<Object>> list = new ArrayList<>(); Map<String, Object> mapData = new HashMap<>(); // 取出表头 for (int i = 0; i < dataHead.size(); i++) { mapData = dataHead.get(0); } for (String key : mapData.keySet()) { head.add(key); } for (Map<String, Object> map : dataHead) { List<Object> list1 = new ArrayList<>(); for (String key : map.keySet()) { list1.add(map.get(key)); } list.add(list1); } System.out.println("list" + list); for (String s : head) { listHead.add(Collections.singletonList(s)); } return list; }
自定义转换器config
package com.tiancom.pas.dataSelect.config; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.WriteConverterContext; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.data.WriteCellData; import java.util.HashMap; /** * @Author : YuanXin * @create 2023/12/7 11:34 * @Description : 转换器 */ public class config implements Converter<HashMap<String, Object>> { @Override public Class<HashMap> supportJavaTypeKey() { return HashMap.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; } /** * 这里是写的时候会调用。/ */ @Override public WriteCellData<HashMap<String,Object>> convertToExcelData(WriteConverterContext<HashMap<String, Object>> context) { return new WriteCellData<HashMap<String,Object>>(String.valueOf(context.getValue())); } }