EasyExcel导出工具类

简介: EasyExcel导出工具类

 目录

工具类

头部实体类(要和工具类在同一个module或项目下)

日期转换器


工具类

/**
 * 导出Excel工具类
 */
public class EasyExcelUtil<T> {
    /**
     * 单sheet(Map写入)
     * @param response 响应对象
     * @param headList 头部集合
     * @param dataList 数据集合
     */
    public static void write(HttpServletResponse response, List<ExcelHead> headList, List<Map<String, Object>> dataList) throws IOException {
        ExcelWriterBuilder writerBuilder = EasyExcel.write();
        writerBuilder.file(response.getOutputStream());
        writerBuilder.excelType(ExcelTypeEnum.XLSX);
        //日期转换器
        TimestampStringConverter converter = new TimestampStringConverter();
        writerBuilder.registerConverter(converter).registerWriteHandler(new ColumnWidthStyleStrategy())
                .head(convertHead(headList)).sheet("sheet1")
                .doWrite(convertData(headList, dataList));
    }
    /**
     * 多sheet(Map写入)
     * @param response 响应对象
     * @param headMap 头部Map数据
     * @param dataMap 数据Map数据
     * @param sheetMap sheet Map数据
     */
    public static void multipleWrite(HttpServletResponse response
            , Map<String,List<ExcelHead>> headMap
            , Map<String,List<Map<String, Object>>> dataMap
            , Map<String,String> sheetMap) throws IOException {
        //日期转换器
        TimestampStringConverter converter = new TimestampStringConverter();
        ExcelWriter excelWriter = EasyExcel.write()
                .registerConverter(converter)
                .registerWriteHandler(new ColumnWidthStyleStrategy())
                .file(response.getOutputStream())
                .excelType(ExcelTypeEnum.XLSX).autoCloseStream(true).build();
        int i = 0;
        for (Map.Entry<String,List<ExcelHead>> entry : headMap.entrySet()) {
            WriteSheet writeSheet = EasyExcel
                    .writerSheet(i++, sheetMap.get(entry.getKey()))
                    .head(convertHead(entry.getValue())).build();
            excelWriter.write(convertData(entry.getValue(), dataMap.get(entry.getKey())), writeSheet);
        }
        excelWriter.finish();
    }
    /**
     * 实体写入
     * @param response 响应对象
     * @param sheetName sheet名称
     * @param c 实体类
     * @param list 实体数据
     */
    public static <T> void writeSheet(HttpServletResponse response, String sheetName, Class<T> c, List<T> list) throws IOException {
        EasyExcel.write(response.getOutputStream(), c).sheet(sheetName).doWrite(list);
    }
    /**
     * 读取并存储到实体
     * @param fileName 路径地址
     * @param sheetName sheet名称
     * @param c 实体类
     */
    public static <T> List<T> read(String fileName, String sheetName, Class c) {
        List<T> list = new ArrayList();
        EasyExcel.read(fileName, c, new ReadListener<T>() {
            @Override
            public void invoke(T o, AnalysisContext analysisContext) {
                list.add(o);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            }
        }).sheet(sheetName).doRead();
        return list;
    }
    /**
     * 读取并存储到实体
     * @param fileName 路径地址
     * @param sheetNo 指定sheet
     */
    public static Map<String,Object> readToMap(String fileName, Integer sheetNo) {
        Map<String,Object> result = new HashMap<>();
        List<Map<String,Object>> dataList = new ArrayList();
        //头部map
        Map<String,String> headMap = new HashMap<>();
        //头部拼音map
        Map<String,String> pinyinMap = new HashMap<>();
        EasyExcel.read(fileName,new AnalysisEventListener<Map<Integer, Object>>() {
            @Override
            public void invoke(Map<Integer, Object> data, AnalysisContext context) {
                Map<String,Object> map = new HashMap<>();
                for (Integer key : data.keySet()) {
                    if(key!=null && data.get(key)!=null) {
                        map.put("field_" + key.toString(), data.get(key));
                    }
                }
                dataList.add(map);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            }
            @Override
            public void invokeHead(Map<Integer, ReadCellData<?>> head, AnalysisContext context) {
                for (Integer key : head.keySet()) {
                    if(key!=null && head.get(key)!=null && StringUtils.isNotBlank(head.get(key).getStringValue())) {
                        headMap.put("field_" + key.toString(), head.get(key).getStringValue());
                        pinyinMap.put("field_" + key.toString(), Pinyin4jUtils.getPinYinHeadChar(head.get(key).getStringValue()));
                    }
                }
            }
        }).sheet(sheetNo).headRowNumber(1).doRead();
        result.put("headMap",headMap);
        result.put("pinyinMap",pinyinMap);
        result.put("dataList",dataList);
        result.put("count",dataList.size());
        return result;
    }
    /**
     * 读取表头并存储到实体
     * @param fileName 路径地址
     * @param sheetNo 指定sheet
     */
    public static Map<String,Object> readToMapHead(String fileName, Integer sheetNo) {
        Map<String,Object> result = new HashMap<>();
        //头部map
        Map<String,String> headMap = new HashMap<>();
        //头部拼音map
        Map<String,String> pinyinMap = new HashMap<>();
        EasyExcel.read(fileName,new AnalysisEventListener<Map<Integer, Object>>() {
            @Override
            public void invoke(Map<Integer, Object> data, AnalysisContext context) {
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            }
            @Override
            public void invokeHead(Map<Integer, ReadCellData<?>> head, AnalysisContext context) {
                for (Integer key : head.keySet()) {
                    if(key!=null && head.get(key)!=null && StringUtils.isNotBlank(head.get(key).getStringValue())) {
                        headMap.put("field_" + key.toString(), head.get(key).getStringValue());
                        pinyinMap.put("field_" + key.toString(), Pinyin4jUtils.getPinYinHeadChar(head.get(key).getStringValue()));
                    }
                }
            }
        }).sheet(sheetNo).headRowNumber(1).doRead();
        result.put("headMap",headMap);
        result.put("pinyinMap",pinyinMap);
        return result;
    }
    /**
     * 头部转换
     * @param headList 头部集合
     */
    private static List<List<String>> convertHead(List<ExcelHead> headList) {
        List<List<String>> list = new ArrayList<>();
        for (ExcelHead head : headList) {
            list.add(Lists.newArrayList(head.getTitle()));
        }
        //沒有搞清楚head的参数为List<List<String>>,用List<String>就OK了
        return list;
    }
    /**
     * 数据转换
     * @param headList 头部集合
     * @param dataList 数据集合
     */
    private static List<List<Object>> convertData(List<ExcelHead> headList, List<Map<String, Object>> dataList) {
        List<List<Object>> result = new ArrayList();
        //对dataList转为easyExcel的数据格式
        for (Map<String, Object> data : dataList) {
            List<Object> row = new ArrayList();
            for (ExcelHead h : headList) {
                Object o = data.get(h.getFieldName());
                //需要对null的处理,比如age的null,要转为-1
                row.add(handler(o, h.getNullValue()));
            }
            result.add(row);
        }
        return result;
    }
    /**
     * 空值处理
     * @param o 数值
     * @param nullValue 空值置换
     */
    private static Object handler(Object o, Object nullValue) {
        return o != null ? o : nullValue;
    }
}

image.gif

头部实体类(要和工具类在同一个module或项目下)

/**
 * Excel头部实体
 */
public class ExcelHead<T> {
    private String fieldName;
    private String title;
    private T nullValue;
    public ExcelHead(String fieldName, String title) {
        this.fieldName = fieldName;
        this.title = title;
    }
    public ExcelHead(String fieldName, String title, T nullValue) {
        this.fieldName = fieldName;
        this.title = title;
        this.nullValue = nullValue;
    }
    public String getFieldName() {
        return fieldName;
    }
    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public T getNullValue() {
        return nullValue;
    }
    public void setNullValue(T nullValue) {
        this.nullValue = nullValue;
    }
}

image.gif

注意:真正导出表格的是ExcelWriterSheetBuilder类中的方法,前面只是封装,这个是真正导出用到的;这个类是EasyExcel自带的。

日期转换器

/**
 * 日期转换器
 */
public class TimestampStringConverter implements Converter<Timestamp> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return Timestamp.class;
    }
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
    @Override
    public WriteCellData<?> convertToExcelData(Timestamp value, ExcelContentProperty contentProperty,
                                               GlobalConfiguration globalConfiguration) {
        WriteCellData cellData = new WriteCellData();
        String cellValue;
        if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
            cellValue = DateUtils.format(value.toLocalDateTime(), null, globalConfiguration.getLocale());
        } else {
            cellValue = DateUtils.format(value.toLocalDateTime(), contentProperty.getDateTimeFormatProperty().getFormat(),
                    globalConfiguration.getLocale());
        }
        cellData.setType(CellDataTypeEnum.STRING);
        cellData.setStringValue(cellValue);
        cellData.setData(cellValue);
        return cellData;
    }
}

image.gif


相关文章
|
XML 缓存 前端开发
Thymeleaf一篇就够了
Thymeleaf是Springboot官方支持的模板引擎,有着动静分离等独有特点,通过本文简单学习下吧!
65283 25
Thymeleaf一篇就够了
|
前端开发
轻松搞定-vue-随机验证码
轻松搞定-vue-随机验证码
466 0
|
传感器 存储 定位技术
一起玩转树莓派(18)——MPU6050陀螺仪加速度传感器模块应用
现在智能手机的功能已经非常强大,除了基础的通信功能外,测位测速,空间角度等数据的测量也非常方便,这在线路导航,地图,体感游戏等应用中十分重要。不知你是否想过,智能设备是如何获取到其所在的空间状态与加速度等数据的呢?MPU6050就是提供这类数据测量的一种传感器模块。
3216 0
|
11月前
|
消息中间件 监控 Java
《聊聊线程池中线程数量》:不多不少,刚刚好的艺术
本文深入探讨Java线程池的核心参数与线程数配置策略,结合CPU密集型与I/O密集型任务特点,提供理论公式与实战示例,帮助开发者科学设定线程数,提升系统性能。
|
Java 数据库连接 应用服务中间件
从“ClassNotFoundException”到“终于搞定!”——一次 Web 应用排查之旅
本文详细记录了在开发 Web 应用过程中遇到的多个典型问题及解决方法,包括 JSP 编译失败、MyBatis 核心类加载错误、配置文件混乱以及映射文件路径不匹配等。通过逐步排查和调整目录结构、分离配置文件、正确管理依赖,最终解决了所有问题。文章总结了调试经验,强调了目录结构的重要性、配置文件的清晰划分以及日志分析的价值,为开发者提供了实用的参考。
806 0
|
JSON 数据处理 Swift
Swift 中的网络编程,主要介绍了 URLSession 和 Alamofire 两大框架的特点、用法及实际应用
本文深入探讨了 Swift 中的网络编程,主要介绍了 URLSession 和 Alamofire 两大框架的特点、用法及实际应用。URLSession 由苹果提供,支持底层网络控制;Alamofire 则是在 URLSession 基础上增加了更简洁的接口和功能扩展。文章通过具体案例对比了两者的使用方法,帮助开发者根据需求选择合适的网络编程工具。
627 3
|
机器学习/深度学习 监控 计算机视觉
测试 opencv-python 中的 mat 和 Umat 处理图像的差异(GPU加速)
测试 opencv-python 中的 mat 和 Umat 处理图像的差异(GPU加速)
1798 0
|
存储 数据库连接 API
构建RESTful API:使用FastAPI实现高效的增删改查操作
构建RESTful API:使用FastAPI实现高效的增删改查操作
1109 0
|
消息中间件 Java Kafka
Kafka ACK机制详解!
本文深入剖析了Kafka的ACK机制,涵盖其原理、源码分析及应用场景,并探讨了acks=0、acks=1和acks=all三种级别的优缺点。文中还介绍了ISR(同步副本)的工作原理及其维护机制,帮助读者理解如何在性能与可靠性之间找到最佳平衡。适合希望深入了解Kafka消息传递机制的开发者阅读。
2215 0