首先需要定义excel实体类


@Data
@ColumnWidth(22)
@HeadRowHeight(30)
public class ExcelProductDTO {//动态下拉框,可以查询数据库数据显示在下拉框中@ExcelSelected(sourceClass = MyExcelSelected.class)@ExcelProperty(value = "生产厂家编号")private String producerCode;@ExcelSelected(source = {"高值","低值"})@ExcelProperty(value = "库存价值类型")private String stockValType;@ExcelSelected(source = {"耗材","普通设备","医疗设备"})@ExcelProperty(value = "库存类型")private String stockType;@ExcelSelected(source = {"有","无"})@ExcelProperty(value = "是否有明细")private Integer hasDetail;@ExcelSelected(source = {"药械","资产","设备"})@ExcelProperty(value = "业务类型")private String ywType;@ExcelSelected(source = {"虚库","实库"})@ExcelProperty(value = "是否虚库")private String isVirtual;@ExcelSelected(source = {"是","否"})@ExcelProperty(value = "是否进口")private String isImport;
}

自定义注解

@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;
}

创建动态下拉框的接口,设置动态下拉框都实现该接口

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;}}

创建Handler,设置excel中的下拉框


@Data
@AllArgsConstructor
public class SelectedSheetWriteHandler implements SheetWriteHandler {private final Map<Integer, ExcelSelectedResolve> selectedMap;/*** Called before create the sheet*/@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}/*** Called after the sheet is created*/@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 这里可以对cell进行任何操作Sheet sheet = writeSheetHolder.getSheet();DataValidationHelper helper = sheet.getDataValidationHelper();selectedMap.forEach((k, v) -> {// 设置下拉列表的行: 首行,末行,首列,末列CellRangeAddressList rangeList = new CellRangeAddressList(v.getFirstRow(), v.getLastRow(), k, k);// 设置下拉列表的值DataValidationConstraint constraint = helper.createExplicitListConstraint(v.getSource());// 设置约束DataValidation validation = helper.createValidation(constraint, rangeList);// 阻止输入非下拉选项的值validation.setErrorStyle(DataValidation.ErrorStyle.STOP);validation.setShowErrorBox(true);validation.setSuppressDropDownArrow(true);validation.createErrorBox("提示", "请输入下拉选项中的内容");sheet.addValidationData(validation);});}
}

创建导出工具类

@Slf4j
public class EasyExcelUtil {/*** 创建即将导出的sheet页(sheet页中含有带下拉框的列)* @param head 导出的表头信息和配置* @param sheetNo sheet索引* @param sheetName sheet名称* @param <T> 泛型* @return sheet页*/public static <T> WriteSheet writeSelectedSheet(Class<T> head, Integer sheetNo, String sheetName) {Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(head);return EasyExcel.writerSheet(sheetNo, sheetName).head(head).registerWriteHandler(new SelectedSheetWriteHandler(selectedMap)).build();}/*** 解析表头类中的下拉注解* @param head 表头类* @param <T> 泛型* @return Map<下拉框列索引, 下拉框内容> map*/private static <T> Map<Integer, ExcelSelectedResolve> resolveSelectedAnnotation(Class<T> head) {Map<Integer, ExcelSelectedResolve> selectedMap = new HashMap<>();// getDeclaredFields(): 返回全部声明的属性;getFields(): 返回public类型的属性Field[] fields = head.getDeclaredFields();for (int i = 0; i < fields.length; i++){Field field = fields[i];// 解析注解信息ExcelSelected selected = field.getAnnotation(ExcelSelected.class);ExcelProperty property = field.getAnnotation(ExcelProperty.class);if (selected != null) {ExcelSelectedResolve excelSelectedResolve = new ExcelSelectedResolve();String[] source = excelSelectedResolve.resolveSelectedSource(selected);if (source != null && source.length > 0){excelSelectedResolve.setSource(source);excelSelectedResolve.setFirstRow(selected.firstRow());excelSelectedResolve.setLastRow(selected.lastRow());if (property != null && property.index() >= 0){selectedMap.put(property.index(), excelSelectedResolve);} else {selectedMap.put(i, excelSelectedResolve);}}}}return selectedMap;}}

.创建动态下拉框配置类


@Component
public class SpringContextUtil implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringContextUtil.applicationContext = applicationContext;}// 获取ApplicationContextpublic static ApplicationContext getApplicationContext() {return applicationContext;}// 通过class获取Beanpublic static <T> T getBean(Class<T> clazz) {return applicationContext.getBean(clazz);}// 通过name以及class获取Beanpublic static <T> T getBean(String name, Class<T> clazz) {return applicationContext.getBean(name, clazz);}}

动态下拉框配置类

//动态下拉框中的数据配置类
public class MyExcelSelected implements ExcelDynamicSelect{@Overridepublic String[] getSource() {//查询下拉框中需要的数据ProductMapper productMapper = SpringContextUtil.getBean(ProductMapper.class);return productMapper.selectList(null).toArray(new String[]{});//当多列需要动态下拉框时,只需自定义类实现ExcelDynamicSelect中的方法,并在方法中查询数据即可。}
}

导出excel到桌面

@Overridepublic void exportProductData(HttpServletResponse response) {//获取当前桌面路径  直接导出文件到桌面上String path = FileSystemView.getFileSystemView().getHomeDirectory().getPath();String fileName = "产品数据表" + System.currentTimeMillis() + ".xlsx";String exportFileName = path + "/" + fileName;//编码问题try {fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");response.setContentType("application/vnd.ms-excel;charset=utf-8");response.setCharacterEncoding("utf-8");response.setDateHeader("Expires", -1);//设置响应头部信息,格式为附件,以及文件名response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);ExcelWriter excelWriter = EasyExcel.write(exportFileName).build();WriteSheet writeSheet = EasyExcelUtil.writeSelectedSheet(ExcelProductDTO.class, 0, "产品信息表");//此处只导出实体类中的数据所以只new 一个空的list,如果想导出数据库数据需要从数据库中查询数据listexcelWriter.write(new ArrayList<ExcelProductDTO>(), writeSheet);excelWriter.finish();} catch (UnsupportedEncodingException e) {log.error("导出Excel编码异常", e.getMessage());} catch (IOException e) {log.error("导出Excel文件异常", e.getMessage());}}

如果需要在前端显示下载文件可参考以下代码(本人为实现仅参考)

@Overridepublic void exportProductData(HttpServletResponse response) {String fileName = "产品数据表" + System.currentTimeMillis() + ".xlsx";//编码问题try {fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");response.setContentType("application/vnd.ms-excel;charset=utf-8");response.setCharacterEncoding("utf-8");response.setDateHeader("Expires", -1);//设置响应头部信息,格式为附件,以及文件名response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();WriteSheet writeSheet = EasyExcelUtil.writeSelectedSheet(ExcelProductDTO.class, 0, "产品信息表");//此处只导出实体类中的数据所以只new 一个空的list,如果想导出数据库数据需要从数据库中查询数据listexcelWriter.write(new ArrayList<ExcelProductDTO>(), writeSheet);excelWriter.finish();} catch (UnsupportedEncodingException e) {log.error("导出Excel编码异常", e.getMessage());} catch (IOException e) {log.error("导出Excel文件异常", e.getMessage());}}

前端可参考

//在前端请求返回结果中const link = document.createElement("a");let blob = new Blob([res.data], { type: "multipary/form-data" });link.style.display = "none";link.href = URL.createObjectURL(blob);link.setAttribute("download", decodeURI(Date.now()+'导出模板.xlsx'));document.body.appendChild(link);link.click();document.body.removeChild(link);

如果遇到  No converter for [class java.util.LinkedHashMap] with preset Content-Type 'application/vnd.ms-excel;charset=utf-8'] 这个报错可以参考一下解决方法


@Configuration
public class MvcConfig implements WebMvcConfigurer {@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {convert.setSupportedMediaTypes(getSupportedMediaTypes());converters.add(convert);}public List<MediaType> getSupportedMediaTypes() {//创建fastJson消息转换器List<MediaType> supportedMediaTypes = new ArrayList<>();supportedMediaTypes.add(MediaType.APPLICATION_JSON);supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);supportedMediaTypes.add(MediaType.APPLICATION_PDF);supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);supportedMediaTypes.add(MediaType.APPLICATION_XML);supportedMediaTypes.add(MediaType.IMAGE_GIF);supportedMediaTypes.add(MediaType.IMAGE_JPEG);supportedMediaTypes.add(MediaType.IMAGE_PNG);supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);supportedMediaTypes.add(MediaType.TEXT_HTML);supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);supportedMediaTypes.add(MediaType.TEXT_PLAIN);supportedMediaTypes.add(MediaType.TEXT_XML);supportedMediaTypes.add(MediaType.ALL);return supportedMediaTypes;}
}

本人也是参考自己做的:使用EasyExcel导出带下拉框的Excel_√Angelの爱灬的博客-CSDN博客_easyexcel导出下拉框

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

  1. 用Excel VBA连接SQL Server数据库并将表中的数据显示到Excel中

    本实例使用VB语言和OLEDB类连接SQL Server 2005数据库. 在sheet1上右键→查看代码,加入如下代码: Sub admin()Dim conn, xRsSet conn = Cre ...

  2. 自定义注解导出excel数据

    自定义注解导出excel数据 利用自定义注解方式,对数据列表进行简单的导出操作.即在实体对象的属性域上添加导出标识的注解,在对实体进行导出时,利用自定义注解进行反射的方法,获取实体需要导出的属性及值. ...

  3. SpringBoot 整合JWT实现基于自定义注解的-登录请求验证拦截(保姆级教学,附:源码)

    学习目标: Spring Boot 整合JWT实现基于自定义注解的 登录请求接口拦截 例: 一篇掌握 JWT 入门知识  1.1 在学习SpringBoot 整合JWT之前,我们先来说说JWT进行用户 ...

  4. Aop+自定义注解实现数据字典翻译

    目录 前言 源码 思维导图 前言 一般来说,项目开发会用自定义注解去实现日志监控等操作 在实际项目中,前后台数据交互时,每次都需要根据一个code值去进行查询数据库进行中间操作进行获取text值 本博 ...

  5. navicat查询oracle表结构,利用Navicat Premium导出数据库表结构信息至Excel的方法

    因为要编写设计文档,需要用到数据库表结构,想要在word文档中以二维表格的形式展示,故借助Excel形成二维表格样式,还是很方便的样子! 1.新建查询,并将以下SQL语句修改至需要 SELECT CO ...

  6. easyexcel 检查表头是否匹配_利用easyexcel生成excel文件-自定义表头与数据栏对应的处理方式...

    前面几篇文章测试过用easyexcel生成动态表头,动态样式.特别是动态表头以及下面数据列表与表头字段的对应是采用注解方式实现的.但在实际工作中,有些到处是灵活生成的,也就是说对于同一个类,在不同的场 ...

  7. EasyExcel生成带下拉列表或二级级联列表的Excel模版+自定义校验导入数据(附仓库)

    EasyExcel生成带下拉列表或二级级联列表的Excel模版+自定义校验导入数据(附仓库) 目录 EasyExcel生成带下拉列表或二级级联列表的Excel模版+自定义校验导入数据(附仓库) 仓库 ...

  8. java自定义注解实现excel数据导入导出,设置单元格数据验证与生成省市区多列联动效果

    本文通过自定义注解实现excel数据导入导出.以及设置excel文件中列数据验证,即用户在excel文件中输入数据时就可以对数据格式验证是否符合,节省了程序中过多的数据验证操作,注解还额外提供了一系列 ...

  9. Java使用poi做加自定义注解实现对象与Excel相互转换

    引入依赖 maven <dependency><groupId>org.apache.poi</groupId><artifactId>poi</ ...

最新文章

  1. leetcode —— 48. 旋转图像
  2. 线程池异步线程中再次获取线程池资源的问题
  3. 计算机工程学院迎新晚会,计算机与信息工程学院2016级迎新晚会举行
  4. 大型综合体弱电智能化解决方案标书
  5. Linux学习笔记007---Centos7中配置静态ip
  6. matlab中cell2mat的作用,Matlab中cell2mat的使用
  7. QQ空间过滤器 更新记录 (最新版本 2.3)
  8. 多套 企业/工厂/超市/仓库库存管理系统源码 工具软件程序源代码
  9. SLAM入门-相机成像原理与公式推导
  10. Mars3D开发教程学习步骤(不定时更新
  11. Havij 1.152 最新破解版
  12. js实现点击图片在屏幕中放大
  13. 二氧化铅,氧化锌,四氧化三铁-碳复合材料增容电池的方法
  14. Linux CentOS(常用命令)
  15. 【Appium】测试时遇到手机内嵌H5页面的切换问题
  16. (最新)cpu天梯图 (CPU)- Processor Benchmarks
  17. 2022年江苏省建筑三类人员(机械类专职安全生产管理人员C1证)练习题及答案
  18. Appium 介绍以及工作原理
  19. 读书笔记 摘自:《吃掉那只青蛙:博恩·崔西的高效时间管理法则(原书第3版)》
  20. Windows8出现DNS解析错误

热门文章

  1. iterm2 Mac 分屏相关快捷键
  2. 终于看清了那些所谓的网店代运营嘴脸,实在是惨痛的经历!
  3. android 接入qq分享能力报错: java.lang.ClassNotFoundException: com.tencent.stat.StatConfig
  4. Improving Conversational Recommender System by Pretraining Billion-scale Knowledge Graph论文笔记
  5. 华为HG8245C光猫删除TR069并修改ACS
  6. 老mac笔记本更换SSD固态硬盘启动失败的解决办法
  7. html中video标签用法,HTML中的video标签怎么用
  8. wifi mouse hd for linux,无线鼠标(高清试用版本)下载-无线鼠标 WiFi Mouse HD v3.0.3_手机乐园...
  9. 【常用SQL】MySQL查询重复的数据
  10. 华为荣耀8电信卡显示无服务器,华为荣耀8青春版