easyExcel多行表头设定不同样式和特定单元格设定样式的实现

easyexcel · 浏览次数 : 18

小编点评

The code you provided describes a custom cell write handler for Excel, which allows you to apply different styles to specific cells or rows based on certain conditions. Here's a summary of the key points: **Custom Cell Write Handler:** * This class handles cell styling for specific situations by storing cell styles in a `cellStyleMap`. * It overrides the `beforeCellCreate`, `afterCellCreate`, and `afterCellDispose` methods to apply styles based on cell values and conditions. * **Before cell creation:** * It checks if the cell contains specific strings like "×" or "未通过". * If it's a header cell, it sets a custom cell style with a specific border, alignment, and font. * **After cell creation:** * If the cell content doesn't contain the specified strings, it applies the default cell style. * If it's a data cell, it sets the border, alignment, and font of the cell to specific values. **Style Setting:** * The `getHeadStyleStrategy` method returns a horizontal cell style strategy that sets the alignment and font for the header cells. * This strategy defines the horizontal alignment (CENTER) and vertical alignment (CENTER) of the header cells. **Condition-Based Styling:** * The code checks for specific cell values (e.g., "×" or "未通过") and applies corresponding styles (e.g., bold, red border). * It also sets the cell style to `null` for certain conditions, effectively disabling it. **Overall, this custom cell write handler allows you to customize cell styles based on various conditions, providing a flexible way to achieve specific formatting requirements.** **Additional Notes:** * The code assumes the presence of a `cellStyleMap` containing predefined cell styles. * The specific styles applied to different cells are not defined in the provided code. * The code relies on the `WriteCellStyle` and `HorizontalCellStyleStrategy` classes for cell styling.

正文

前言

有个需求,需要设置Excel导出的样式,样式如下图所示,有三个表头行,第一个表头行需要加粗和灰色背景,另外两个表头行使用另外的样式,并且当测试结果单元格出现x或者未通过的时候,设置其为红色字体。

image-20240506162318563

实现步骤

写入ExcelSheet的部分代码

 for (Map.Entry<String, List<ExcelDTO>> entry : entries) {
                String excelFileName = entry.getKey() + ".xlsx";
                File tempFile = File.createTempFile(excelTempFolderPath + entry.getKey(), ".xlsx");
                ExcelWriter excelWriter = EasyExcel.write(tempFile).build();

                WriteSheet writeSheet = EasyExcel.
                        writerSheet("sheet")
                        .head(ReceiveCardExcelDTO.class)
                        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                        .registerWriteHandler(new CustomWriteHandler("测试报告"))
                        .registerWriteHandler(new CustomCellWriteHandler())
                        .registerWriteHandler(getHeadStyleStrategy())
                        .build();
                writeSheet.setRelativeHeadRowIndex(1);

                List<List<String>> headTitles = Lists.newArrayList();
                // 固定title
                headTitles.add(Lists.newArrayList("工单号", "卡信息"));
                headTitles.add(Lists.newArrayList(entry.getKey(), "升级固件"));
                headTitles.add(Lists.newArrayList(entry.getKey(), "SDRAM"));
                headTitles.add(Lists.newArrayList("型号", "HUB"));
          
     headTitles.add(Lists.newArrayList(receiveCardOrderMap.get(entry.getValue().get(0).getMark()).getReceiveCardType(), "网口"));
                headTitles.add(Lists.newArrayList("测试时间", "测试结果"));
                headTitles.add(Lists.newArrayList(cn.hutool.core.date.DateUtil.format(entry.getValue().get(0).getTestTime(), "yyyy-MM-dd HH:mm:ss"), "详情"));
                writeSheet.setHead(headTitles);
                excelWriter.write(entry.getValue(), writeSheet);
                excelWriter.finish();

重点是如下几个handler,下面会进行讲解

            WriteSheet writeSheet = EasyExcel.
                    writerSheet("sheet")
                    .head(ReceiveCardExcelDTO.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .registerWriteHandler(new CustomWriteHandler("测试报告"))
                    .registerWriteHandler(new CustomCellWriteHandler())
                    .registerWriteHandler(getHeadStyleStrategy())
                    .build();

测试报告标题行的实现

这里对应的是CustomWriteHandler类

/********************************
 *  @interface : CustomWriteHandler
 *  @function  : 添加excel head额外内容
 *  @date      : 2024.04.23 11:13
 *  @author    : zh
 ********************************/
public class CustomWriteHandler implements SheetWriteHandler {

    private String title;


    public CustomWriteHandler(String title) {
        this.title = title;
    }

    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {

    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        Workbook workbook = writeWorkbookHolder.getWorkbook();
        Sheet sheet = workbook.getSheet(writeSheetHolder.getSheetName());
        Row row1 = sheet.getRow(0);
        if (row1 == null) {
            row1 = sheet.createRow(0);
        }
        row1.setHeight((short) 500);
        Cell cell1 = row1.getCell(0);
        if (cell1 == null) {
            cell1 = row1.createCell(0);
        }
        cell1.setCellValue(title);
        CellStyle cellStyle = workbook.createCellStyle();

        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeight((short) 220);
        font.setFontName("宋体");
    
        sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 0, 0, 6));

        CellStyle headStyle = workbook.createCellStyle();
        headStyle.setFont(font);
        headStyle.setAlignment(HorizontalAlignment.CENTER);
        headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置表头背景色为灰色
        headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);


        CellStyle contentStyle = workbook.createCellStyle();
        contentStyle.setAlignment(HorizontalAlignment.CENTER);
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentStyle.setBorderTop(BorderStyle.THIN);
        contentStyle.setBorderBottom(BorderStyle.THIN);
        contentStyle.setBorderLeft(BorderStyle.THIN);
        contentStyle.setBorderRight(BorderStyle.THIN);

        for (Row row : sheet) {
            if (row.getRowNum() == 0) {
                for (Cell cell : row) {
                    // 表头
                    cell.setCellStyle(headStyle);
                }
                break;
            }
        }
    }
}

在这里register并填入相关的标题,到此第一行标题头设置完毕。

image-20240506171306644

这里其实就是相当于这行标题是独立开来设置的,先预留了第一行的位置,然后后续把标题插入这行,后面再针对这行设置独立的样式。

image-20240506171607437

其他标题行的设置

可以看到每个list都有两个元素

List<List<String>> headTitles = Lists.newArrayList();
                // 固定title
                headTitles.add(Lists.newArrayList("工单号", "卡信息"));
                headTitles.add(Lists.newArrayList(entry.getKey(), "升级固件"));
                headTitles.add(Lists.newArrayList(entry.getKey(), "SDRAM"));
                headTitles.add(Lists.newArrayList("型号", "HUB"));

对比excel标题

image-20240506171506824

可以看到其实每个list都是两行标题竖着的两个内容,第一个列标题两行就分别是工单号,卡信息;第二列因为涉及到合并,所以出现了两个entry.getKey()对应不同的两个内容(升级固件和SDRAM),依次类推;

标题行样式的设定

对应这个registerWriteHandler(getHeadStyleStrategy())

调getHeadStyleStrategy()方法,返回了一个策略,这里只设置了header的样式

    public static HorizontalCellStyleStrategy getHeadStyleStrategy() {
        // 头的策略  样式调整
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 水平对齐方式
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        headWriteCellStyle.setFillPatternType(FillPatternType.NO_FILL);
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setBold(false);
        headWriteFont.setFontHeightInPoints((short) 12);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 垂直对齐方式
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        return new HorizontalCellStyleStrategy(headWriteCellStyle, (List<WriteCellStyle>) null);
    }

特定单元格样式的修改

对应了这个.registerWriteHandler(new CustomCellWriteHandler())

/********************************
 *  @interface : CustomCellWriteHandler
 *  @function  : 处理excel特定内容格式
 *  @date      : 2024.04.23 11:13
 *  @author    : zh
 ********************************/
public class CustomCellWriteHandler implements CellWriteHandler {


    Map<String,CellStyle> cellStyleMap = new HashMap<>();



    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        Cell cell = context.getCell();
        int rowIndex = cell.getRowIndex();
        int cellIndex = cell.getColumnIndex();

        // 自定义样式处理
        // 当前事件会在 数据设置到poi的cell里面才会回调
        // 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true
        if (BooleanUtils.isNotTrue(context.getHead())) {
            if (cell.getStringCellValue().contains("×") || cell.getStringCellValue().contains("未通过")) {
                CellStyle cellStyle = null;
                if (cellStyleMap.get("red") != null) {
                    cellStyle = cellStyleMap.get("red");
                } else {
                    // 拿到poi的workbook
                    Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
                    // 这里能复用的地方缓存起来 一个表格最多创建6W个样式
                    // 不同单元格传同一个cellStyle
                    cellStyle = workbook.createCellStyle();
                    cellStyle.setBorderBottom(BorderStyle.THIN);
                    cellStyle.setBorderTop(BorderStyle.THIN);
                    cellStyle.setBorderLeft(BorderStyle.THIN);
                    cellStyle.setBorderRight(BorderStyle.THIN);
                    cellStyle.setAlignment(HorizontalAlignment.CENTER);
                    Font font = workbook.createFont();
                    font.setColor(Font.COLOR_RED);
                    cellStyle.setFont(font);
                    cellStyleMap.put("red", cellStyle);
                }
                cell.setCellStyle(cellStyle);
                // 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确
                // 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到
                // cell里面去 会导致自己设置的不一样
                context.getFirstCellData().setWriteCellStyle(null);
            }
        }


    }
}

到此就可以实现上述excel样式了。

与easyExcel多行表头设定不同样式和特定单元格设定样式的实现相似的内容:

easyExcel多行表头设定不同样式和特定单元格设定样式的实现

前言 有个需求,需要设置Excel导出的样式,样式如下图所示,有三个表头行,第一个表头行需要加粗和灰色背景,另外两个表头行使用另外的样式,并且当测试结果单元格出现x或者未通过的时候,设置其为红色字体。 实现步骤 写入ExcelSheet的部分代码 for (Map.Entry

EasyExcel 无法读取图片?用poi写了一个工具类

在平时的开发中,经常要开发 Excel 的导入导出功能。一般使用 poi 或者 EasyExcel 开发,使用 poi 做 excel 比较复杂,大部分开发都会使用 EasyExcel 因为一行代码就能实现导入和导出的功能。但是 EasyExcel 不支持图片的读的操作,本文操作如何实现图片的读和写

厉害了!12秒将百万数据通过EasyExcel导入MySQL数据库中

一、写在开头 我们在上一篇文章中提到了通过EasyExcel处理Mysql百万数据的导入功能(一键看原文),当时我们经过测试数据的反复测验,100万条放在excel中的数据,4个字段的情况下,导入数据库,平均耗时500秒,这对于我们来说肯定难以接受,今天我们就来做一次性能优化。 二、性能瓶颈分析 一

EasyExcel处理Mysql百万数据的导入导出案例,秒级效率,拿来即用!

一、写在开头 今天终于更新新专栏 《EfficientFarm》 的第二篇博文啦,本文主要来记录一下对于EasyExcel的高效应用,包括对MySQL数据库百万级数据量的导入与导出操作,以及性能的优化(争取做到秒级性能!)。 二、如何做技术选型 其实在市面上我们有很多常用的excel操作依赖库,除了

[EasyExcel] 导出合并单元格

前言 使用spring boot 对excel 进行操作在平时项目中要经常使用。常见通过jxl和poi 的方式进行操作。但他们都存在一个严重的问题就是非常的耗内存。这里介绍一种 Easy Excel 工具来对excel进行操作。 一、Easy Excel是什么? EasyExcel是阿里巴巴开源的一

SpringBoot 整合 EasyExcel 实现自由导入导出,太强了

在实际的业务系统开发过程中,操作 Excel 实现数据的导入导出基本上是个非常常见的需求。 之前,我们有介绍一款非常好用的工具:EasyPoi,有读者提出在数据量大的情况下,EasyPoi 会占用内存大,性能不够好,严重的时候,还会出现内存异常的现象。 今天我给大家推荐一款性能更好的 Excel 导

在表格开发中,如何选择适合自己的处理工具?

引言 GcExcel和EasyExcel都是卓越的高性能Excel处理库。GcExcel是由葡萄城公司开发,可用于Java和.Net平台;而EasyExcel是阿里巴巴开发的基于Java的开源Excel处理库。 在本文中,我们将对GcExcel和EasyExcel进行比较,帮助读者在实际场景中做出明

比 poi导入导出更好用的 EasyExcel使用小结

转载请注明出处: 官方文档: https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read 1.简洁 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,p