EasyExcel工具类,带下拉框

2023-05-16

代码

public class EasyExcelUtil {
    /**
     * excel下载
     *
     * @param response  返回对象
     * @param fileName  文件名
     * @param sheetName 页签名称
     * @param head      对象
     * @param data      数据
     */
    public static void writeExcel(HttpServletResponse response, String fileName, String sheetName, Class head, List data) {
        try (OutputStream outputStream = response.getOutputStream()) {
            setRespHeader(response, fileName);

            EasyExcel.write(outputStream, head).sheet(sheetName).doWrite(data);
        } catch (IOException e) {
            log.error("excel下载失败", e);
            throw new ServiceException("excel下载失败");
        }
    }

    /**
     * 设置响应头
     *
     * @param response
     * @param fileName
     * @throws UnsupportedEncodingException
     */
    public static void setRespHeader(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileNameUrl = URLEncoder.encode(fileName, "UTF-8");
        response.setHeader("content-disposition", "attachment;filename=" + fileNameUrl + ".xlsx");
        response.setHeader("filename", fileNameUrl + ".xlsx");
    }

    /**
     * 获取默认表头内容的样式
     * @return
     */
    private static HorizontalCellStyleStrategy getDefaultHorizontalCellStyleStrategy(){
        /** 表头样式 **/
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景色(浅灰色)
        // 可以参考:https://www.cnblogs.com/vofill/p/11230387.html
        headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 字体大小
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 10);
        headWriteCellStyle.setWriteFont(headWriteFont);
        //设置表头居中对齐
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        /** 内容样式 **/
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 内容字体样式(名称、大小)
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontName("宋体");
        contentWriteFont.setFontHeightInPoints((short) 10);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        //设置内容垂直居中对齐
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置内容水平居中对齐
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        //设置边框样式
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        // 头样式与内容样式合并
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }

    /**
     * 导出
     * @param response
     * @param data
     * @param fileName
     * @param sheetName
     * @param clazz
     * @throws Exception
     */
    public static void writeExcel(HttpServletResponse response, List<?> data, String fileName, String sheetName, Class<?> clazz) throws Exception {
        long exportStartTime = System.currentTimeMillis();
        log.info("报表导出Size: "+data.size()+"条。");
        setRespHeader(response,fileName);
        EasyExcel.write(response.getOutputStream(), clazz).excelType(ExcelTypeEnum.XLSX).sheet(sheetName).registerWriteHandler(getDefaultHorizontalCellStyleStrategy()).doWrite(data);
        log.debug("报表导出结束时间:"+ new Date()+";写入耗时: "+(System.currentTimeMillis()-exportStartTime)+"ms" );
    }

    /**
     * 导出 下拉框
     * @param response
     * @param data
     * @param mapDropDown Map<Integer,String[]> key是列的index 从0开始  value 是数据集
     * @param fileName
     * @param sheetName
     * @param clazz
     */
    @SneakyThrows
    public static void writeExcel(HttpServletResponse response, List<?> data, Map<Integer,String[]> mapDropDown, String fileName, String sheetName, Class<?> clazz){
        long exportStartTime = System.currentTimeMillis();
        log.info("报表导出Size: "+data.size()+"条。");
        setRespHeader(response,fileName);
        EasyExcel.write(response.getOutputStream(), clazz)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet(sheetName)
                .registerWriteHandler(getDefaultHorizontalCellStyleStrategy())
                .registerWriteHandler(new TemplateCellWriteHandlerDate(mapDropDown))
                .doWrite(data);
        log.debug("报表导出结束时间:"+ new Date()+";写入耗时: "+(System.currentTimeMillis()-exportStartTime)+"ms" );
    }

    /**
     * @author QiuYu
     * @createDate 2020-11-16
     * @param response
     * @param data  查询结果
     * @param fileName 导出文件名称
     * @param clazz 映射实体class类
     * @param <T>  查询结果类型
     * @throws Exception
     */
    public static<T> void writeExcel(HttpServletResponse response, List<T> data, String fileName, Class<?> clazz) throws Exception {
        long exportStartTime = System.currentTimeMillis();
        log.info("报表导出Size: "+data.size()+"条。");

        //List<List<T>> lists = SplitListUtil.splitList(data,MAXROWS); // 分割的集合
        List<List<T>> lists = CollectionUtil.split(data, MAXROWS); // 分割的集合
        setRespHeader(response,fileName);
        OutputStream out = response.getOutputStream();
        ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(out, clazz).excelType(ExcelTypeEnum.XLSX).registerWriteHandler(getDefaultHorizontalCellStyleStrategy());
        ExcelWriter excelWriter = excelWriterBuilder.build();
        ExcelWriterSheetBuilder excelWriterSheetBuilder;
        WriteSheet writeSheet;
        if (CollectionUtil.isNotEmpty(lists)){
            for (int i =1;i<=lists.size();i++){
                excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriter);
                excelWriterSheetBuilder.sheetNo(i);
                excelWriterSheetBuilder.sheetName("sheet"+i);
                writeSheet = excelWriterSheetBuilder.build();
                excelWriter.write(lists.get(i-1),writeSheet);
            }
        }
        out.flush();
        excelWriter.finish();
        out.close();
        log.debug("报表导出结束时间:"+ new Date()+";写入耗时: "+(System.currentTimeMillis()-exportStartTime)+"ms" );
    }

}


/**
 * excel通用单元格格式类下拉框赋值
 */
public class TemplateCellWriteHandlerDate implements SheetWriteHandler {

    /**
     * 模板的首行行高 ,通过构造器注入
     */
    private Map<Integer, String[]> explicitListConstraintMap;
    public TemplateCellWriteHandlerDate(Map<Integer, String[]> explicitListConstraintMap) {
        this.explicitListConstraintMap = explicitListConstraintMap;
    }
    /**
     * 设置阈值,避免生成的导入模板下拉值获取不到
     */
    private static final Integer LIMIT_NUMBER = 50;



    /**
     * 返回excel列标A-Z-AA-ZZ
     *
     * @param num 列数
     * @return java.lang.String
     */
    private String getExcelLine(int num) {
        String line = "";
        int first = num / 26;
        int second = num % 26;
        if (first > 0) {
            line = (char) ('A' + first - 1) + "";
        }
        line += (char) ('A' + second) + "";
        return line;
    }

    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // TODO Auto-generated method stub

    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 这里可以对cell进行任何操作
        Sheet sheet = writeSheetHolder.getSheet();
        DataValidationHelper helper = sheet.getDataValidationHelper();

        // k 为存在下拉数据集的单元格下表 v为下拉数据集
        explicitListConstraintMap.forEach((k, v) -> {
            // 设置下拉单元格的首行 末行 首列 末列
            CellRangeAddressList rangeList = new CellRangeAddressList(1, 65536, k, k);
            // 如果下拉值总数大于100,则使用一个新sheet存储,避免生成的导入模板下拉值获取不到
            if (v.length > LIMIT_NUMBER) {
                //定义sheet的名称
                //1.创建一个隐藏的sheet 名称为 hidden + k
                String sheetName = "hidden" + k;
                Workbook workbook = writeWorkbookHolder.getWorkbook();
                Sheet hiddenSheet = workbook.createSheet(sheetName);
                for (int i = 0, length = v.length; i < length; i++) {
                    // 开始的行数i,列数k
                    hiddenSheet.createRow(i).createCell(k).setCellValue(v[i]);
                }
                Name category1Name = workbook.createName();
                category1Name.setNameName(sheetName);
                String excelLine = getExcelLine(k);
                // =hidden!$H:$1:$H$50  sheet为hidden的 H1列开始H50行数据获取下拉数组
                String refers = "=" + sheetName + "!$" + excelLine + "$1:$" + excelLine + "$" + (v.length + 1);
                // 将刚才设置的sheet引用到你的下拉列表中
                DataValidationConstraint constraint = helper.createFormulaListConstraint(refers);
                DataValidation dataValidation = helper.createValidation(constraint, rangeList);
                writeSheetHolder.getSheet().addValidationData(dataValidation);
                // 设置存储下拉列值得sheet为隐藏
                int hiddenIndex = workbook.getSheetIndex(sheetName);
                if (!workbook.isSheetHidden(hiddenIndex)) {
                    workbook.setSheetHidden(hiddenIndex, true);
                }
            }
            // 下拉列表约束数据
            DataValidationConstraint constraint = helper.createExplicitListConstraint(v);
            // 设置约束
            DataValidation validation = helper.createValidation(constraint, rangeList);
            // 阻止输入非下拉选项的值
            validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
            validation.setShowErrorBox(true);
            validation.setSuppressDropDownArrow(true);
            validation.createErrorBox("提示", "此值与单元格定义格式不一致");
            // validation.createPromptBox("填写说明:","填写内容只能为下拉数据集中的单位,其他单位将会导致无法入仓");
            sheet.addValidationData(validation);
        });
    }
}

用法

@GetMapping("/downloadExcel")
public void downloadExcelModel(HttpServletResponse response) {
        List<CatalogExcel> list = new ArrayList<>();
        Map<Integer,String[]> mapDropDown = new HashMap<>();
        //0未确认,1已确认,2已生成
        String[] confirmStas = {"未确认","已确认","已生成"};
        mapDropDown.put(1,confirmStas);
        ExcelUtils.writeExcel(response, list,mapDropDown,"导入模板" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"),"sheet", CatalogExcel.class);
}

导入解析

@Data
public class CatalogExcel implements Serializable {
    /**
     * 确认状态(0未确认,1已确认,2已生成)
     */
    @ExcelProperty(value = "确认状态(0未确认,1已确认,2已生成)", index = 13, converter = ConfirmStasConverter.class)
    @ColumnWidth(15)
    private String confirmStas;

    public static class ConfirmStasConverter implements Converter<String> {
        @Override
        public Class<?> supportJavaTypeKey() {
            return String.class;
        }

        @Override
        public CellDataTypeEnum supportExcelTypeKey() {
            return CellDataTypeEnum.STRING;
        }

        @Override
        public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
            //0未确认,1已确认,2已生成
            String confirmStasName = Optional.ofNullable(cellData).map(o -> cellData.getStringValue()).orElse("未确认");
            return ConfirmStasEnum.getConfirmStasCode(confirmStasName);
        }

        @Override
        public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
            //0未确认,1已确认,2已生成
            String confirmStas = Optional.ofNullable(value).orElse("0");
            return new CellData(Objects.requireNonNull(ConfirmStasEnum.getConfirmStasName(confirmStas)));
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EasyExcel工具类,带下拉框 的相关文章

  • Unregistering JMX-exposed beans on shutdown Disconnected from the target VM(springboot启动报错: )

    具体报错 xff1a Unregistering JMX exposed beans on shutdown Disconnected from the target VM address 39 127 0 0 1 52998 39 tra
  • python排序算法——归并排序(附代码)

    python排序算法 归并排序 文章目录 python排序算法 归并排序一 前言二 算法描述三 代码实现总结 一 前言 相关知识来自 python算法设计与分析 初级排序算法是指几种较为基础且容易理解的排序算法 初级排序算法包括插入排序 选
  • springboot使用fastjson解析json中文乱码问题

    使用fastjson解析json 需要在配置文件application properties中添加 spring http encoding force 61 true 否则 中文会出现乱码
  • springboot访问数据库报 Invalid bound statement (not found)

    如果在使用mapper xml时报了Invalid bound statement not found 的错误 xff0c 并且自己的mapper xml的路径和文件名都没有错误的情况 xff0c 很可能是因为没有在pom xml中配置如下
  • springboot项目创建

    1step xff1a File gt New gt project 2step 在New Project窗口选择Spring Initializer gt 选择default gt Next 3step 命名好项目名等信息点击 Next
  • SpringBoot存入数据库问号问题

    将resources目录下的application properties配置文件中数据库URL配置改为 xff1a spring datasource url 61 jdbc mysql localhost 3306 student use
  • 线程之wait/notify机制

    什么是等待 通知机制 举个栗子 xff1a 餐厅里 xff0c 厨师做好菜之后 xff0c 通知等待中的服务员就是一个简单的等待通知机制 wait xff1a wait方法代码的作用是使当前执行代码的线程进入等待 xff0c wait方法是
  • MySQL常用函数

    开始来熬大骨汤 xff0c 每周一碗大骨汤 xff0c 你也能变成光 于南京 MySQL函数的位置 xff1a 函数可以在select语句及其子句 xff08 例如 where order by having等 xff09 中 xff0c
  • idea的Browse Repositories搜索下载安装插件失败

    我在下载一个插件时 xff0c 刚开始出先下载超时time out xff0c 后来改了一些东西 xff0c 在Browse Repositories界面中 xff0c 直接搜不到插件了 xff08 一个插件都搜不到 xff09 xff0c
  • 安装goole浏览器报错

    1 下载一个谷歌的rpm包 xff0c 配置repo源 root 64 physical cat etc yum repos d google chrome repo google chrome name 61 google chrome
  • 经典编程书籍(C++, 网络, Windows, Linux)

    导读 xff1a 书单中列举的都是相关领域的经典书籍 xff0c 必读之作 此书单的编辑参考了很多网站 xff0c 包括一些名家的推荐 xff0c 例如侯捷 xff0c 孟岩 xff0c 荣耀 xff0c 潘爱民等等 xff0c 在此也向这
  • 域名+解析+GitHub来搭建自己的个人网站

    摘要 文章主要介绍域名解析 xff0c 使用GitHub上的开源项目来搭建一个个人博客 并不需要购买服务器 xff0c 没有数据库访问 xff0c 适合搭建自己的博客或者个人网站 xff0c 不适合大型网站 购买域名 可以在万网上面注册一个
  • Linux服务器批量管理工具 - TeamRemote

    产生背景 xff1a 当前网上流行的一些优秀且功能强大的工具 xff0c 如puppet xff0c dsh xff0c parallel ssh xff0c ansible等 但不得不说 xff0c 他们的上手起来太复杂了 xff0c 导
  • C语言书籍推荐

    C 语言书籍推荐 宗旨 xff1a 技术的学习是有限的 xff0c 分享的精神是无限的 一 基础 1 C语言入门很简单 零起点学通C语言 xff08 多媒体范例教学 xff09 C语言从入门到精通 2 C程序设计语言 第2版 新版 C程序设
  • MATLAB排序函数

    MATLAB排序函数 2011 06 29 13 02 08 源自网络 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • 具有FTP、FTPS和sftp功能的文本编辑器——EditPlus功能介绍

    EditPlus是Windows的文本编辑器 xff0c 具有内置的FTP FTPS和sftp功能 虽然它可以很好地替代记事本 xff0c 但它也为网页作者和程序员提供了许多强大的功能 功能特征 01 语法高亮 EditPlus 默认支持H
  • 《iOS高级编程》中的内存管理基础【MRC】

    文章目录 关于我的仓库前言准备工作内存管理 引用计数 的思考 p 2 p 13 记住一张表格内存管理四大原则注意点疑点 内存管理四兄弟 alloc retain release dealloc p 13 p 20 说明alloc计数GNU实
  • python获取指定路径的文件夹下所有TXT文本内容

    有时候 xff0c 我们需要读取某个指定路径的文件夹下的所有txt的文本内容 xff0c 具体步骤 xff1a 可以使用os listdir 方法先获取文件夹下所有文本的文件名 xff0c 然后循环遍历文件名 xff0c 使用open 方法
  • 生物识别传感器 安全性要求背景

    7 3 10 生物识别传感器 如需了解衡量生物识别解锁模式的安全性的其他背景 xff0c 请参阅衡量生物识别的安全性文档 如果设备实现包含安全锁定屏幕 xff0c 则 xff1a 应包含生物识别传感器 生物识别传感器可基于其欺骗和冒名攻击的
  • 笔记本win10 睡眠时会自动唤醒?修复后唤醒缓慢也解决了

    家里笔记本 xff08 Dell XPS13 xff09 xff0c 睡眠后就睡觉了 醒来后 xff0c 发现电池一直耗电 xff1f xff01 查看 Event Viewer 34 xff0c 看到睡眠后几秒钟就自动唤醒了 xff0c

随机推荐