1. 创建注解

import java.lang.annotation.*;/*** 标注导出的列为下拉框类型,并为下拉框设置内容*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelSelected {/*** 固定下拉内容*/String[] source() default {};/*** 动态下拉内容*/Class<? extends ExcelDynamicSelect> sourceClass() default ExcelDynamicSelect.class;/*** 设置下拉框的起始行,默认为第二行*/int firstRow() default 1;/*** 设置下拉框的结束行,默认为最后一行*/int lastRow() default 0x10000;
}

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

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

3.创建导出工具类

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.study.common.easyexcel.annotation.ExcelSelected;
import com.study.common.easyexcel.select.ExcelSelectedResolve;
import lombok.extern.slf4j.Slf4j;
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.CellRangeAddressList;
import org.springframework.http.HttpHeaders;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Slf4j
public class EasyExcelUtil {/*** 导出单sheet页且sheet页中含有下拉框的excel文件** @param response  HttpServletResponse* @param fileName  文件名* @param sheetName sheet页名* @param data      要导出的数据*/public static <T> void writeExcelBySelect(HttpServletResponse response, String fileName, String sheetName, List<T> data) {try {encodeFileName(response, fileName);Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(IterUtil.getElementType(data));EasyExcel.write(response.getOutputStream(), IterUtil.getElementType(data)).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerWriteHandler(selectedSheetWriteHandler(selectedMap)).sheet(StringUtils.isEmpty(sheetName) ? "Sheet1" : sheetName).doWrite(data);} catch (IOException e) {log.error("导出excel文件异常", e);}}/*** 设置文件名** @param response HttpServletResponse* @param fileName 文件名*/private static void encodeFileName(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());response.setCharacterEncoding(StandardCharsets.UTF_8.name());response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment;filename=\"%s\"", fileName + ".xlsx"));response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache");response.setHeader(HttpHeaders.PRAGMA, "no-cache");response.setDateHeader(HttpHeaders.EXPIRES, -1);}/*** 解析表头类中的下拉注解** @param head 表头类* @return Map<下拉框列索引, 下拉框内容> map*/private static <T> Map<Integer, ExcelSelected> resolveSelectedAnnotation(Class<T> head) {Map<Integer, ExcelSelected> selectedMap = new HashMap<>(16);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) {if (property != null && property.index() >= 0) {selectedMap.put(property.index(), selected);} else {selectedMap.put(i, excelSelectedResolve);}}}return selectedMap;}/*** 为excel创建下拉框** @param selectedMap 下拉框配置数据 Map<下拉框列索引, 下拉框内容>* @return intercepts handle sheet creation*/private static SheetWriteHandler selectedSheetWriteHandler(Map<Integer, ExcelSelected> selectedMap) {return new SheetWriteHandler() {@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {Sheet sheet = writeSheetHolder.getSheet();DataValidationHelper helper = sheet.getDataValidationHelper();selectedMap.forEach((k, v) -> {// 获取固定下拉框的内容List<String> source = new ArrayList<>();if (v.source().length > 0) {source.addAll(Arrays.asList(v.source()));}// 获取动态下拉框的内容Class<? extends ExcelDynamicSelect> sourceClass = v.sourceClass();try {ExcelDynamicSelect excelDynamicSelect = sourceClass.newInstance();String[] dynamicSelectSource = excelDynamicSelect.getSource();if (dynamicSelectSource != null && dynamicSelectSource.length > 0) {source.addAll(Arrays.asList(dynamicSelectSource));}} catch (InstantiationException | IllegalAccessException e) {log.error("解析动态下拉框数据异常", e);}if (CollUtil.isNotEmpty(source)) {CellRangeAddressList rangeList = new CellRangeAddressList(v.firstRow(), v.lastRow(), k, k);DataValidationConstraint constraint = helper.createExplicitListConstraint(source.toArray(new String[0]));DataValidation validation = helper.createValidation(constraint, rangeList);validation.setErrorStyle(DataValidation.ErrorStyle.STOP);validation.setShowErrorBox(true);validation.setSuppressDropDownArrow(true);validation.createErrorBox("提示", "请输入下拉选项中的内容");sheet.addValidationData(validation);}});}};}
}

4.测试导出

(1).创建需要导出的实体类并用该注解标注

public class UserDTO {@ExcelProperty(index = 0,value = "编号")private Long id;@ExcelProperty(index = 1,value = "姓名")private String name;@ExcelProperty(index = 2,value = "年龄")private Integer age;@ExcelProperty(index = 3,value = "性别")//静态下拉框@ExcelSelected(source = {"男","女"})private String sex;@ExcelProperty(index = 4,value = "出生日期")private Date birthday;@ExcelProperty(index = 5,value = "居住城市")//动态下拉框-去数据库中查询所有城市供其选择@ExcelSelected(sourceClass = CityExcelSelectedImpl.class)   private String city;@ExcelIgnoreprivate Boolean isDeleted;
}

(2).创建动态下拉框配置类

这里不能用@Component注解标注该类,从而在Spring容器中通过@Resource@Autowired获取Bean,只能通过ApplicationContext工具类获取Bean

ApplicationContext工具类
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;@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 CityExcelSelectedImpl implements ExcelDynamicSelect{@Overridepublic String[] getSource() {CityMapper cityMapper = SpringContextUtil.getBean(CityMapper.class);return cityMapper.selectAllCity().toArray(new String[]{});}}
web测试
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.example.practicevue.model.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;@RestController
@Slf4j
public class exportController {@PostMapping("/exportSelectedExcel")public void export(HttpServletResponse response){EasyExcelUtil.writeExcelBySelect(response, "测试", "", new ArrayList<UserDTO>())}
}

使用EasyExcel导出带下拉框的Excel相关推荐

  1. Easyexcel导出带下拉框选项excel模板

    需求:导出的excel模板,表头字段动态生成.sheet页下拉框内容动态生成 解决思路:为了避免excel下拉框选项过多会导致内容不显示,将下拉框的内容都存储在另一个新建的固定的sheet页,再通过引 ...

  2. EasyExcel导出带下拉框 通用模板

    实体类 @Data @EqualsAndHashCode(callSuper = true) @ApiModel(value="FireChemicalDto", descript ...

  3. EasyExcel在项目中的应用-在web中导出带下拉框和批注的excel文件

    前言 ​ 好长一段时间没有更新博客了,最近刚刚找到实习工作,接触了企业中的项目,在这段时间的实习过程中,终于知道了企业级项目的体量和业务难度跟之前的小项目是完全不同的.10多天的适应期也逐渐让我找到了 ...

  4. 导出带下拉选项的Excel基于EasyExcel实现

    前言 今天就是记录一个计算点而已,帮小组成员搽屁股改bug.场景就是导出Excel的模板,希望枚举字段有下拉选择. 一.技术选型场景 我们这里用的是阿里开源的EasyExcel,导出模板是后端动态生成 ...

  5. EasyExcel导出有下拉框的模板

    Conteoller层: 代码: /*** 创建元数据模板* 导出模板** @param response 响应* @throws Exception 异常*/@GetMapping("/c ...

  6. EasyExcel导出自定义下拉数据集的Excel模板文件

    有时候因为业务需要,导出的Excel模板里面的单元格下拉数据集可能是用户在系统中自定义的数据字典数据,我们需要通过接口拿到相应字段的对应数据集,导出类似下方这种模板: EasyExcel的api地址: ...

  7. Excel表格下载模板(带下拉框选项)

    下载excel模板需要带下拉框选项,现在纯JAVA代码来实现 1.模板标题实体类 import cn.afterturn.easypoi.excel.annotation.Excel; import ...

  8. EasyExcel导出表格——下拉筛选

    EasyExcel导出表格--下拉筛选 单元格添加下拉筛选 确保输入内容规范和准确 减少数据查询,提高用户使用感 根据用户权限,下拉筛选项控制 Controller层 /*** 模板下载* @para ...

  9. Java EXCEL 表格导入导出(带下拉选-带VLOOKUP函数封装)

    Java EXCEL 表格导入导出(带下拉选-带VLOOKUP函数封装) 对于excel Java POI 使用 目前简单导出导入功能网上很多,但是对于有下拉选,样式等缺点却是最大硬伤,故此封装一个通 ...

最新文章

  1. 书评:实战Apache JMeter
  2. Linux TOP 交互命令
  3. 【隔离】跨区消息穿透定义
  4. 【莫队】区间不同数(金牌导航 莫队-1)
  5. 如何在Eclipse中生成Native类对应的JNI的.h文件
  6. matlab画图,均值±标准差
  7. ai自动生成字幕软件有哪些?自动生成字幕软件推荐!
  8. 笔记本无网络计算机,笔记本没有无线网络连接怎么办 解决方法介绍【图解】...
  9. PS利用切片工具将一张大图裁剪成多个子图像并导出
  10. ios开发工程师常见面试题汇总
  11. 和风天气:免费天气接口,包含天气预报及空气质量等实用信息,使用简单方便(划重点:免费)
  12. 有备无患——数据中心基础设施备品备件管理
  13. 如何通俗易懂地讲解牛顿迭代法?
  14. Android JVM和DVM的区别
  15. 【文献翻译】Select-Storage: A New Oracle Design Pattern on Blockchain
  16. 中国自由软件推广先锋的自述,心潮澎湃的一往无前,一定要看!作者:洪峰...
  17. 为什么说冯诺依曼结构是现代计算机的基础,为什么现代计算机被称为冯·诺依曼结构计算机??...
  18. Google I/O开发者大会第二弹之未来
  19. 股息收益率谁最高-资讯中心-金融界
  20. storm显微镜成像原理_超分辨率显微镜技术原理概述

热门文章

  1. 头歌(educoder)第 5 章 Java 面向对象之类和对象 Java面向对象 - 类与对象
  2. Qt、C++学习交流群招管理员咯(群主为一枚Qt程序开发人员)
  3. MySQL级联修改语句
  4. linux less查找特定字符串,linux less命令详情
  5. 一篇文章透彻解读聚类分析及案例实操
  6. 安师大计算机基础,安师大计算机基础(I)实验报告.docx
  7. Java实现sock5代理服务器
  8. Premiere Pro 2022
  9. 海康摄像头web无插件3.2,vue开发,Nginx代理IIS服务器
  10. 学习笔记7-STM32官方库.c/.h文件功能(汇总)