Java从零开始实现导出excel(二)_aftersheetcreate_追晨始梦的博客-程序员宅基地

技术标签: spring  java  流处理  Excel文件导出  后端  

Java从零开始实现导出excel(二)

新人博主,随笔记录。主要还是通过自己日常工作积累,系统整理一些技术。希望能够节省更多人的时间,走出自己的路。

看了自己发的文章,可以帮助一些小伙伴很开心!!

简述:

上一篇文章主要用我个人觉得,效果很好的方法做excel的导出。但是那只是符合正常,简单的excel导出。可能很多小伙伴,会遇到一些复杂的样式的excel的导出。这一篇同样是用EasyExcel,主要是做一些数据格式复杂的excel,当然这一篇文章不包含复杂表头的excel导出

环境搭建:

这一篇的环境和上一篇我们共用一个。因为都是用EasyExcel这个包中的API,所以没必要换一个工程。还不明白的小伙伴可以去瞟一眼我的上一篇文章Java从零开始实现导出excel(一)

创建导出实体:

这里同样用的是上一篇的实体。不过有点改变,我将性别这一列放开了。
在这里插入图片描述
这里有个需要注意的地方,因为EasyExcel是通过实体中@ExcelProperty注解中的index去匹配excel中的列,所以当我们不使用模板时,index一定要是连续且有效的,否则我们生成的excel中会出现空白表头列的情况

例如:下面这图是我没有放开性别那个字段时导出的excel表头
在这里插入图片描述

导出Excel

导出方法:

 /**
     * 使用EasyExcel导出excel
     * @param response
     * @throws Exception
     */
    @GetMapping(value = "/exportExcel")
    public void exportExcel(HttpServletResponse response) 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();
        List<Student> data = getData();
        Map<Integer,String[]> map = new HashMap<>();
        map.put(2,new String[]{
    "男","女"});//下拉导出
        ExcelUtil.exportBySelect(out,data,map);
        out.close();
    }


    //封装导出数据
    private List<Student> getData() {
    
        List<Student> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
    
            Student student = new Student();
            student.setName("测试学生姓名-" + i);
            student.setAge(i);
            student.setSex(i % 2 == 1 ? "男" : "女");
            student.setNum(111111L);
            student.setAddress("追晨始梦程序员宅基地");
            list.add(student);
        }
        return list;
    }

工具类:

ExcelUtil

 /**
     * 功能描述: 导出数据到Excel
     * <p>
     * 使用阿里easyPoi 自定义导出excel携带下拉框
     *
     * @param out         输出
     * @param list        需写入的数据
     * @param mapDropDown 下拉框数据
     */
    public static void exportBySelect(OutputStream out, List<? extends BaseRowModel> list, Map<Integer, String[]> mapDropDown) {
    

            EasyExcelFactory.write(out, list.get(0).getClass()).registerWriteHandler(new EasyExcelSheetSelectUtils(mapDropDown)).sheet().doWrite(list);

    }

这个公共方法中,我们需要去调用registerWriteHandler方法:将我们创建的自定义拦截器放入其中。

这个拦截器是我们这篇文章的重点——直接代码看

EasyExcelSheetSelectUtils


package com.example.demo;


import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;

import java.util.Map;

/**
 * 自定义设置excel样式
 */
public class EasyExcelSheetSelectUtils implements SheetWriteHandler {
    

    //第0列开始 设置某列的下拉内容
    private Map<Integer,String[]> mapDropDown;

    public EasyExcelSheetSelectUtils(Map<Integer, String[]> mapDropDown) {
    
        this.mapDropDown = mapDropDown;
    }

    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
    

    }

    /**
     * 自定义设置excel样式
     * @param writeWorkbookHolder
     * @param writeSheetHolder
     */
    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
    

        //获取sheet页
        Sheet sheet = writeSheetHolder.getSheet();
        ///开始设置下拉框 //设置下拉框
        DataValidationHelper helper = sheet.getDataValidationHelper();
        for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
    
            /***起始行、终止行、起始列、终止列**/
            CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, entry.getKey(), entry.getKey());
            /***设置下拉框数据**/
            DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
            DataValidation dataValidation = helper.createValidation(constraint, addressList);
            /***处理Excel兼容性问题**/
            if (dataValidation instanceof XSSFDataValidation) {
    
                dataValidation.setSuppressDropDownArrow(true);
                dataValidation.setShowErrorBox(true);
            } else {
    
                dataValidation.setSuppressDropDownArrow(false);
            }
            sheet.addValidationData(dataValidation);
        }
        //合并单元格
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 0, 0));
    }
}

这个里面我写了两个常见的案例:

  1. 下拉框
  2. 合并单元格

当然了,可能小伙伴们在实际工作中可能有很多不一样的需求,看完我的两个案例的实现,相信你所需要的样式,都可以自己实现。

1. 下拉框

这个功能可能模板导出时候,会更加方便一点。这里我觉得主要是一个思想

首先我们看实现的过程
在这里插入图片描述
我们自定义的拦截器一定要继承SheetWriteHandler这个接口
这个接口中有两个虚函数:
在这里插入图片描述
我们这里一般会用到下面那个函数 :afterSheetCreate

我们在自定义的拦截器中定义了一个私有属性mapDropDown,用来装下拉框的参数。用一个有参构造将我们需要的数据传进来
key: 表示第几列需要加入下拉框
value: 表示加入下拉框的值

在这里插入图片描述

2.合并单元格

这里我是只做了个案例,将excel表格中的第一列的第一行和第二行进行合并
在这里插入图片描述

导出文件效果:

在这里插入图片描述

这里面,最重要的一步是,我们能获取到sheet页

在这里插入图片描述有了这个sheet页的对象,那其他自定义功能的效果,小伙伴们可以发挥自己的技术,根据自己的需求完成excel导出!

源码链接

官方文档地址

补充

这篇文章写完,突然想到,其实我们自定义拦截器在模板导出的方法中也是可以用的。我测试了一下。只需要改动调用方法即可:
在这里插入图片描述
效果:

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44357774/article/details/113741231

智能推荐

Python绘图问题:Matplotlib中%matplotlib inline是什么、如何使用?_matplotlib-inline是单独包吗-程序员宅基地

原文链接:https://blog.csdn.net/liangzuojiayi/article/details/78183783%matplotlib inline是魔法函数官方给出的定义是:IPython有一组预先定义好的所谓的魔法函数(Magic Functions),你可以通过命令行的语法形式来访问它们。可见“%matplotlib inline”就是模仿命令行来访问magic函数..._matplotlib-inline是单独包吗

JS之数组 创建数组 访问数组和数组的长度 数组的相关方法-程序员宅基地

创建数组访问数组和数组的长度数组的相关方法创建数组<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>创建数组</title></head><body&..._js创建一个数组,并返回该数组的长度

WordPress 添加title中的logo-程序员宅基地

WordPress 添加title中的logo<!--网页标题左侧显示--><link rel="icon" href="/favicon.png" type="image/x-icon"><!--收藏夹显示图标--><link rel="shortcut icon" href="/favicon.png" t..._wordpress 标题logo

MyCAT-程序员宅基地

为什么80%的码农都做不了架构师?>>> ...

visio安装问题总结_visio we can't install this product can't be insta-程序员宅基地

最常见的就是下载:office deployment tool来解决,这也是官方的办法。_visio we can't install this product can't be installed on the selected updat

全排列c++代码_全排列算法:递归&amp;字典序实现-程序员宅基地

(给算法爱好者加星标,修炼编程内功)作者:HankingHuhttps://blog.csdn.net/u013309870/article/details/68941284全排列:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。例如:1 、2 、3 三个元素的全排列为:{1,2,3},{1,3..._c++全排列 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个

随便推点

一组在线 Rich Text 编辑器 -程序员宅基地

今天坐了一天,把以前的东西整理了一通,简单“装饰”一下,放到网上给大家看:Cross-Browser Rich Text Editor 一个兼容多种浏览器(IE5.5+, Mozilla1.3+)的编辑器 dotnetBB 论坛上使用的编辑器 使用的是 DIV 而非 IFRAME 动网 HTML 编辑器 很老的一个,好像是动网新闻上的? 一个叫 M

阳性,阴性,假阳性,假阴性,敏感度,特异性_真阳性假阳性四格表计算-程序员宅基地

一般从医学角度说,阳性(positive),代表有病或者有病毒,阴性(negative),代表正常。假阳性(false positive)是指因为种种原因把不具备阳性症状的人检测出阳性的结果。其实就是将没病的检查成有病的,假阳性检测结果易造成误诊,假阴性(false negative)就是将有病的检查为没病,假阴性结果导致漏诊。 敏感度(sensitivity):又称真阳性率,即患..._真阳性假阳性四格表计算

djcpth计算机实验报告,计算机组成原理实验_夏天的火苗的博客-程序员宅基地

时间:2019-05-15 03:31:36 作者:adminALU设计 module ALU(ALU_OP,AB_SW,F_LED_SW,LED); input[2:0] ALU_OP,AB_SW,F_LED_SW; output[7:0] LED; reg[7:0] LED; reg[31:0] A,B,F; reg OF,ZF; always@(*) begin时间:2019-05-..._计算机组成原理cpth实验报告

Failed to compile with 2 errors-程序员宅基地

翻译过来是:编译失败,出现2个错误These dependencies were not found没有找到这些依赖项根据下方提示重新下载cli

c语言结构体初始化及赋值,结构体的定义、初始化和赋值_阿廖林诺的博客-程序员宅基地

结构体初始化1、结构体的构造函数中初始化在C++中,结构体与类在使用上已没有本质上的区别了,所以可以使用构造函数来初始化。如下代码所示:struct Stu{int nNum;bool bSex;char szName[20];char szEmail[100];//构造函数初始化Stu(){nNum = 0;bSex = false;memset(szName,0,sizeof(szName))..._c语言结构体初始化赋值

HTTP客户端帮助文档-程序员宅基地

HTTP 客户端是使用get方式提交http请求,来获取数据。该步骤有“一般”、“字段”两个标签页。“一般”标签页配置信息如图1所示。 图1 “一般”标签页配置信息下文详细解释各控件的含义:1、步骤名称:步骤的名称,在单一转换中,名称必须唯一。2、URL:指定请求地址。3、从字段中获取URL:勾选后,第四个控件“URL字...

推荐文章

热门文章

相关标签