您现在的位置是:首页 > 正文

EasyExcel——自定义注解、实现动态获取下拉框内容

2024-02-01 04:48:56阅读 3

问题场景

在使用EasyExcel进行导出时,有时候需要根据数据库表内容,为导出数据列单元格做内容下拉框,通常在下载导入模板时使用,这样可有将导出的模板作为导入数据的表单,实现对用户输入的一个合法限制,效果大致如下:

代码实现

EasyExcel工具的使用这里就不赘述了,这里主要展示了在导出过程中是如何从数据库表获取动态下拉框内容,以及和固定下拉框内容的对比。

导出实体类

import com.alibaba.excel.annotation.ExcelProperty;

import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.*;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor

@HeadRowHeight(value = 25) // 头部行高
@ContentRowHeight(value = 15) // 内容行高
@ColumnWidth(value = 20) // 列宽
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER) // 表头样式
@HeadFontStyle(fontName = "黑体")
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER) // 内容样式

//添加自定关注解,将导出信息增加下拉框判断

public class EmpDo {

//    private String source = "";
//    private MyExcelSelected excelSelected

    @ExcelProperty("姓名")
    @ColumnWidth(10)
    private String name;

    /**
     * 性别: 1:男  0:女
     */
    @ExcelSelected(source = {"男","女"})
    @ExcelProperty(value = "性别", converter = GenderConverter.class)
    @ColumnWidth(10)
    private Integer gender;

    @ExcelProperty("年龄")
    @ColumnWidth(10)

    private Integer age;

    @ExcelProperty("电话")
    @ColumnWidth(25)
    private String tel;

    @ExcelProperty("邮箱")
    @ColumnWidth(25)
    private String email;
    /**
     * 对照部门表
     * 1-开发部  2-运维部  3-开发一部  4-开发二部  5-开发三部  6-运维一部  7-运维二部
     */
    //动态获取下拉框内容
    @ExcelSelected(sourceClass = DeptSelected.class)
    @ExcelProperty(value = "部门", converter = DeptConverter.class)
    @ColumnWidth(10)
    private String deptId;

    @ExcelProperty(value = "入职时间")
    @ColumnWidth(25)
    @DateTimeFormat("yyyy-MM-dd")
    private Date hireDate;

    /**
     * 工作状态(0:在职、1:离职、2:复职、3:外部人员、4:退休人员)
     */
    @ExcelSelected(source = {"在职","离职","复职","外部人员","退休人员"})
    @ExcelProperty(value = "工作状态", converter = JobStatusConverter.class)
    @ColumnWidth(20)
    private Integer jobStatus;

    /**
     * 是否党员(0:党员 1:非党员)
     */
    @ExcelSelected(source = {"党员","非党员"})
    @ExcelProperty(value = "是否党员", converter = IspartyConverter.class)
    @ColumnWidth(20)
    private Integer isParty;
}

这里演示的是部门列动态获取下拉框内容,性别、工作状态以及是否党员状态值固定,所以直接在导入导出转换器内写成固定的了。 

自定义注解

(1)

@Documented
@Target({ElementType.FIELD})//用此注解用在属性上。
@Retention(RetentionPolicy.RUNTIME)//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
public @interface ExcelSelected {
    /**
     * 固定下拉内容
     */
    String[] source() default {};

    /**
     * 动态下拉内容
     */
    Class<? extends ExcelDynamicSelect>[] sourceClass() default {};

    /**
     * 设置下拉框的起始行,默认为第二行
     */
    int firstRow() default 1;

    /**
     * 设置下拉框的结束行,默认为最后一行
     */
    int lastRow() default 0x10000;
}

(2)

public interface ExcelDynamicSelect {
    /**
     * 获取动态生成的下拉框可选数据
     * @return 动态生成的下拉框可选数据
     */
    String[] getSource();
}

自定义注解解析类

/**
 * 自定义注解解析类
 */
@Data
@Slf4j
public class ExcelSelectedResolve {
    /**
     * 下拉内容
     */
    private String[] source;

    /**
     * 设置下拉框的起始行,默认为第二行
     */
    private int firstRow;

    /**
     * 设置下拉框的结束行,默认为最后一行
     */
    private int lastRow;

    public String[] resolveSelectedSource(ExcelSelected excelSelected) {
        if (excelSelected == null) {
            return null;
        }

        // 获取固定下拉框的内容
        String[] source = excelSelected.source();
        if (source.length > 0) {
            return source;
        }

        // 获取动态下拉框的内容
        Class<? extends ExcelDynamicSelect>[] classes = excelSelected.sourceClass();
        if (classes.length > 0) {
            try {
                ExcelDynamicSelect excelDynamicSelect = classes[0].newInstance();
                String[] dynamicSelectSource = excelDynamicSelect.getSource();
                if (dynamicSelectSource != null && dynamicSelectSource.length > 0) {
                    return dynamicSelectSource;
                }
            } catch (InstantiationException | IllegalAccessException e) {
                log.error("解析动态下拉框数据异常", e);
            }
        }
        return null;
    }

}

动态下拉列数据配置类 

这个类的作用是获取数据库中所有的部门信息,并返回作为部门列的下拉框内容。

如果有其他列也许要制作动态内容下拉框,以此类推创建对应的类实现相同接口即可。

//动态下拉框中的数据配置类
public class DeptSelected implements ExcelDynamicSelect{

    @Override
    public String[] getSource() {
        //查询下拉框中需要的数据  部门信息
        SysDeptDao sysDeptDao = SpringContextUtil.getBean(SysDeptDao.class);
        List<SysDeptEntity> sysDeptEntities = sysDeptDao.selectList(null);
        List<String> nameList = new ArrayList<>();
        //获取部门名称填入集合
        for (SysDeptEntity dept : sysDeptEntities) {
            nameList.add(dept.getName());
        }
        //将部门名称集合转换为数组返回 作为下拉框内容
        return nameList.toArray(new String[]{});
    }
}

这里返回的数据将作为导出实体类中的部门列下拉框内容:

转换器

部门转换器

这里的转换Map集合对照内容是从数据库获取的,作用是将人员信息中的部门id导出时转换为部门名称。

/**
 * @Description: 部门转换器
 */
public class DeptConverter implements Converter<String> {

    private final SysDeptDao sysDeptDao = SpringContextUtil.getBean(SysDeptDao.class);
    private final List<SysDeptEntity> deptList = sysDeptDao.selectList(null);

    @Override
    public Class<?> supportJavaTypeKey() {
        //实体类对象属性类型
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        //excel中对应的单元格属性类型
        return CellDataTypeEnum.STRING;
    }

    /**
     * 将单元格中数据转化为java对象属性 
     * @param context
     * @return
     * @throws Exception
     */
    @Override
    public String convertToJavaData(ReadConverterContext<?> context) throws Exception {
        //创建集合用于存储部门id和名称对应关系
        Map<String,String> mapToJavaData = new HashMap<>();
        //遍历部门列表将部门id和名称放入map
        for (SysDeptEntity sysDeptEntity : deptList) {
            mapToJavaData.put(sysDeptEntity.getName(),sysDeptEntity.getId());
        }
        //从cellData中读取数据 转换为实体类中的对象数值
        return mapToJavaData.get(context.getReadCellData().getStringValue());
    }

    /**
     * 将java对象转化为excel单元格数据  
     * @param context
     * @return
     * @throws Exception
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) throws Exception {

        Map<String,String> mapToExcelData = new HashMap<>();

        for (SysDeptEntity sysDeptEntity : deptList) {
            mapToExcelData.put(sysDeptEntity.getId(),sysDeptEntity.getName());
        }


        //将java属性转换为excel对应属性类型
        return new WriteCellData<>(mapToExcelData.get(context.getValue()));
    }
}

性别转换器

性别只有男、女两种选择,所以这里直接固定了Map集合的内容,直接将存储的值转换为名称导出。其他固定下拉内容的列同理。

public class GenderConverter implements Converter<Integer> {

    @Override
    public Class<?> supportJavaTypeKey() {
        //实体类中对象属性类型
        return Integer.class;
    }
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        //Excel中对应的cellData(单元格数据)属性类型
        return CellDataTypeEnum.STRING;
    }

    /**
     * 将单元格数据转化为java对象,男-1,女-0,用于导入时识别转化为实体类相应类型字段
     * @param context
     * @return
     * @throws Exception
     */
    @Override
    public Integer convertToJavaData(ReadConverterContext<?> context) throws Exception {

        Map<String,Integer> mapToJavaData = new HashMap<>();
        mapToJavaData.put("男",1);
        mapToJavaData.put("女",0);

        // 从CellData中读取数据,判断Excel中的值,将其转换为预期的数值
        return mapToJavaData.get(context.getReadCellData().getStringValue());
    }

    /**
     * 将java对象转为单元格数据,也就是0转成女,1转成男,用于导出excel时对性别字段进行转换
     * @param context
     * @return
     * @throws Exception
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<Integer> context) throws Exception {

        Map<Integer,String> mapToExcelData = new HashMap<>();
        mapToExcelData.put(1,"男");
        mapToExcelData.put(0,"女");

        // 判断实体类中获取的值,转换为Excel预期的值,并封装为CellData对象
        return new WriteCellData<>(mapToExcelData.get(context.getValue()));
    }
}

测试结果

数据库部门表信息

导出Excel表部门下拉框内容

注: 内容为本人参考其他博主分享,结合自身需求学习实践产生,参考博客为:

Easyexcel生成excel并通过自定义注解实现下拉框以及动态下拉框(将数据库中的数据显示在excel下拉框中)-CSDN博客

网站文章

  • Redis集群

    Redis集群

    Redis集群是一个提供在多个Redis节点间共享数据的程序集,可以支持多个Master。

    2024-02-01 04:48:50
  • 记一次生产环境GitLab服务和数据迁移到阿里云和GitLab版本升级

    记一次生产环境GitLab服务和数据迁移到阿里云和GitLab版本升级

    GitLab是一个用于管理代码的仓库系统,他是一个开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务,可通过Web界面进行访问公开的或者私人项目。它拥有与Github类似的功能,能够浏览源代码,管理代码缺陷和注释。.........

    2024-02-01 04:48:20
  • SpringBoot整合Elasticsearch-elasticsearch-rest-high-level-client

    前言在前面几篇文章中演示ES安装时对外暴露有两个端口,一个是9200,一个是9300,这里9300是一个TCP端口,ES集群环境下也是通过9300端口通信的,是长连接的形式通信的,这里不推荐使用Spr...

    2024-02-01 04:48:13
  • Spring Boot 系统启动任务

    1. 背景 有时候我们会希望在Spring Boot项目启动时,完成一些初始化工作。 例如加载初始化的缓存信息,初始化一些系统运行的基本参数。 此时,就可以通过Spring Boot系统启动任务实现,...

    2024-02-01 04:48:05
  • DVWA--存储型XSS(初中高)

    DVWA--存储型XSS(初中高)

    选择“View Source”查看源程序,发现服务器端对message框内容使用了htmlspecialchars() 函数进行转义,对name框使用str_replace()函数进行替换。选择“Vi...

    2024-02-01 04:47:36
  • Spring框架源码(五) @configuration源码深度解析

    Spring框架源码(五) @configuration源码深度解析

    Configuration 注解是spring-context模块提供的一个给开发者使用的配置类注解,开发者可以通过@Configuration注解来定义配置类,也可以使用xml形式注入。例如配置数据...

    2024-02-01 04:47:30
  • Aria2下载软件的Linux安装、配置文件编辑、开机启动、浏览器插件连接

    Aria2下载软件的Linux安装、配置文件编辑、开机启动、浏览器插件连接

    1. 安装。 这里主要是在Debian及衍生发行版上的操作。 直接用 apt install aria2 即可 apt update apt install aria2 # aria2 的命令是 ar...

    2024-02-01 04:47:23
  • 新起点

    2019年7月9日:进入新的工作环境,面对全新的电脑,就像现在的自己一样,犹如一张白纸,可以随意涂画。年轻的心斗志昂扬,重新出发创出属于自己的精彩。1. 不断学习2.认真负责3.勤学好问...

    2024-02-01 04:47:17
  • monkey环境搭建

    monkey环境搭建

    monkey的安装环境需要4块:1.Java环境JDK的安装2.Android SDK环境3.启动模拟器(夜神模拟器)或者真机4.执行monkey测试命令第一部分:Java环境的安装1)下载好JDK的安装包后,双击安装2)配置环境变量:我的电脑--右键属性--高级系统设置--环境变量在系统变量处点击新建:填写变量名和JDK的安装路径JAVA...

    2024-02-01 04:46:47
  • 记录自己第一次科研经历

    这里写自定义目录标题科研之路研究方向选择功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右Sma...

    2024-02-01 04:46:40