使用EasyExcel导出带下拉框的Excel

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() {
            @Override
            public 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;
    @ExcelIgnore
    private 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;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    // 获取ApplicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    // 通过class获取Bean
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    // 通过name以及class获取Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return applicationContext.getBean(name, clazz);
    }
}
动态下拉框配置类
public class CityExcelSelectedImpl implements ExcelDynamicSelect{

    @Override
    public 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>())
    }
}
  • 24
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
要在 EasyExcel 中设置下拉框多选,需要进行以下步骤: 1. 定义下拉框的列表数据,可以使用 List<String> 或者 String[] 等类型存储下拉框的选项。 2. 创建一个 CellRangeAddressList 对象,用于指定下拉框的范围,可以使用 setFirstRow、setLastRow、setFirstCol、setLastCol 方法分别设置下拉框的起始行、结束行、起始列、结束列。 3. 创建一个 DataValidationHelper 对象,用于创建数据验证规则,在 DataValidationHelper 对象上调用 createValidation 方法,设置下拉框的数据来源、校验规则等。 4. 将创建好的数据验证规则应用到 Excel 单元格中,可以使用 Sheet 对象的 addValidationData 方法将数据验证规则应用到指定的单元格范围。 下面是一个示例代码: ``` List<String> options = Arrays.asList("选项1", "选项2", "选项3"); CellRangeAddressList rangeList = new CellRangeAddressList(0, 10, 0, 0); DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationConstraint constraint = helper.createExplicitListConstraint(options.toArray(new String[options.size()])); DataValidation validation = helper.createValidation(constraint, rangeList); validation.setShowErrorBox(true); sheet.addValidationData(validation); ``` 上述代码中,options 变量存储了下拉框的选项,rangeList 变量指定了下拉框的范围,helper 变量创建了 DataValidationHelper 对象,constraint 变量创建了数据验证规则,validation 变量将数据验证规则应用到了指定的单元格范围。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值