我的编程空间,编程开发者的网络收藏夹
学习永远不晚

EasyExcel代码层面设置写出的Excel样式、以及拦截器策略的使用、自动列宽设置、EasyExcel默认设置详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

EasyExcel代码层面设置写出的Excel样式、以及拦截器策略的使用、自动列宽设置、EasyExcel默认设置详解

一、概述

虽然EasyExcel已经提供了一系列注解方式去设置样式。

但是如果没有实体类,或者想要更精确的去设置导出文件的Excel样式的时候就需要在代码层面去控制样式了。

二、使用已有拦截器自定义样式

主要步骤:

  • 创建Excel对应的实体对象
  • 创建一个style策略 并注册
  • 写出Excel

第一步是否需要创建Excel实体对象,得根据实际需求而定,如果导出字段不固定则使用无模型的方式即可

不使用实体类时可以直接传入ListString>>类型的数据来作为表头和数据内容。

2.1 定义一个Excel实体类

@Getter@Setter@EqualsAndHashCodepublic class DemoData {    @ExcelProperty("字符串标题")    private String string;    @ExcelProperty("日期标题")    private Date date;    @ExcelProperty("数字标题")    private Double doubleData;        @ExcelIgnore    private String ignore;}

2.2 设置表头样式

// 创建一个写出的单元格样式对象WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 背景设置为红色headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());// 创建写出Excel的字体对象WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short)20);// 设置字体大小为20headWriteFont.setItalic(BooleanEnum.TRUE.getBooleanValue());// 设置字体斜体headWriteCellStyle.setWriteFont(headWriteFont);// 把字体对象设置到单元格样式对象中

2.3 设置内容样式

// 创建一个写出的单元格样式对象WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND// 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);// 设置内容背景色为绿色contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());// 边框设置contentWriteCellStyle.setBorderTop(BorderStyle.THIN); // 设置单元格上边框为细线contentWriteCellStyle.setBorderBottom(BorderStyle.THICK); // 设置单元格下边框为粗线contentWriteCellStyle.setBorderLeft(BorderStyle.MEDIUM);     // 设置单元格左边框为中线contentWriteCellStyle.setBorderRight(BorderStyle.MEDIUM_DASHED); // 设置单元格右边框为中虚线// 创建写出Excel的字体对象WriteFont contentWriteFont = new WriteFont();contentWriteFont.setFontHeightInPoints((short)20);  //设置字体大小contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); //设置文字居中contentWriteCellStyle.setWriteFont(contentWriteFont);  // 把字体对象设置到单元格样式对象中

2.4 使用EasyExcel默认的拦截器策略自定义样式

常见的策略有两种:

  • HorizontalCellStyleStrategy :每一行的样式都一样 或者隔行一样

    源码中它主要有两个构造函数:

    // 构造函数一:接收一个WriteCellStyle对象和一个List集合// 第一个参数是表头部分单元格的样式// 第二个参数是内容部分的单元格样式public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle,    List<WriteCellStyle> contentWriteCellStyleList) {    this.headWriteCellStyle = headWriteCellStyle;    this.contentWriteCellStyleList = contentWriteCellStyleList;}// 构造函数二:接收两个WriteCellStyle对象// 第一个参数是表头部分的单元格的样式// 第二个参数是内容部分的单元格样式public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle,          WriteCellStyle contentWriteCellStyle) {    this.headWriteCellStyle = headWriteCellStyle;    if (contentWriteCellStyle != null) {        this.contentWriteCellStyleList =             ListUtils.newArrayList(new WriteCellStyle[]{contentWriteCellStyle});    }}

    WriteCellStyle其实只是一个单元格的对象。

    把它交由HorizontalCellStyleStrategy之后,就可以被渲染成一行的对象。然后每行都按这个策略执行。

    接收List参数时,会循环渲染集合中的样式对象。

  • AbstractVerticalCellStyleStrategy :每一列的样式都一样 需要自己回调每一页

    它是一个抽象类,需要自己定义类去继承它,然后重写里面对应的方法。

    这部分文档中的描述几乎没有,全靠自己摸索,可能官方更推荐第一种方式

2.5 使用默认的拦截器HorizontalCellStyleStrategy自定义样式

// 完整代码@Testpublic void handlerStyleWrite() {    // 创建一个写出的单元格样式对象    WriteCellStyle headWriteCellStyle = new WriteCellStyle();    // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND    // 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定    contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);    // 设置内容背景色为绿色    contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());    // 边框设置    contentWriteCellStyle.setBorderTop(BorderStyle.THIN);// 设置单元格上边框为细线    contentWriteCellStyle.setBorderBottom(BorderStyle.THICK);// 设置单元格下边框为粗线    contentWriteCellStyle.setBorderLeft(BorderStyle.MEDIUM);    // 设置单元格左边框为中线    contentWriteCellStyle.setBorderRight(BorderStyle.MEDIUM_DASHED);//设置单元格右边框为中虚线    // 创建写出Excel的字体对象    WriteFont contentWriteFont = new WriteFont();    contentWriteFont.setFontHeightInPoints((short)20); //设置字体大小    contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//设置文字居中    contentWriteCellStyle.setWriteFont(contentWriteFont);  // 把字体对象设置到单元格样式对象中        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现    HorizontalCellStyleStrategy horizontalCellStyleStrategy =        new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭    EasyExcel.write(fileName, DemoData.class)        .registerWriteHandler(horizontalCellStyleStrategy)        .sheet("horizontalCellStyleStrategy拦截器设置样式")        .doWrite(data());}

2.5 使用默认的拦截器AbstractVerticalCellStyleStrategy自定义样式

1)创建一个类实现AbstractVerticalCellStyleStrategy

public class CustomVerticalCellStyleStrategy extends AbstractVerticalCellStyleStrategy {    // 重写定义表头样式的方法    @Override    protected WriteCellStyle headCellStyle(Head head) {        WriteCellStyle writeCellStyle = new WriteCellStyle();        writeCellStyle.setFillBackgroundColor(IndexedColors.RED.getIndex());        WriteFont writeFont = new WriteFont();        writeFont.setColor(IndexedColors.RED.getIndex());        writeFont.setBold(false);        writeFont.setFontHeightInPoints(Short.valueOf((short)15));        writeCellStyle.setWriteFont(writeFont);        return writeCellStyle;    }    // 重写定义内容部分样式的方法    @Override    protected WriteCellStyle contentCellStyle(Head head) {        WriteCellStyle writeCellStyle = new WriteCellStyle();        writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);        writeCellStyle.setFillBackgroundColor(IndexedColors.GREEN.getIndex());        writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);        return writeCellStyle;    }}

这个方式在背景色设置方面存在问题,不知道是不是bug,这种方式还是慎用吧

2)具体使用

@Testpublic void handlerStyleWrite() {// 创建拦截器对象    CustomVerticalCellStyleStrategy customVerticalCellStyleStrategy         = new CustomVerticalCellStyleStrategy();    // 写出Excel    EasyExcel.write(fileName, DemoData.class)        .registerWriteHandler(customVerticalCellStyleStrategy)        .sheet("horizontalCellStyleStrategy拦截器设置样式")        .doWrite(data());}

三、自定义拦截器设置Excel样式

3.1 为什么不使用AbstractCellWriteHandler

老版本中自定义拦截器主要是继承 Easyexcel 的抽象类AbstractCellWriteHandler 控制器。

重写beforeCellCreate前置处理方法和afterCellDispose后置处理方法完成对应的方法达到控制单个单元格

样式的效果。但是AbstractCellWriteHandler这个抽象类在3.x版本已经被弃用,所以现在不推荐使用它。

3.2 实现CellWriteHandler接口

前面的两种方式,都只能在代码层面批量设置样式,而不能设置导出Excel中的一部分单元格样式。

实现这个接口后可以重写afterCellDispose方法来对单个单元格的样式进行设置。

每个单元格处理完毕之后都会调用它。

虽然文档中说不太推荐,可能是这里代码多了会影响性能,但是这是目前设置单个单元格最好的方式了。

3.1 基础使用

1)定义类实现CellWriteHandler接口,并重写afterCellDispose方法

public class CustomCellWriteStrategy implements CellWriteHandler {    // 在单元格处理之后执行    @Override    public void afterCellDispose(CellWriteHandlerContext context) {        // 当前事件会在 数据设置到poi的cell里面才会回调        // 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true        if (BooleanUtils.isNotTrue(context.getHead())) {            // 获取第一个单元格对象            // 只要不是头 一定会有数据 当然fill(填充)的情况 可能要context.getCellDataList()             // 这个需要看模板,因为一个单元格会有多个 WriteCellData            WriteCellData<?> cellData = context.getFirstCellData();                        // cellData 可以获取样式/数据,也可以直接设置样式/数据,设置后会立即生效            // 这里也需要用cellData去获取样式            // 很重要的一个原因是 WriteCellStyle 和 dataFormatData绑定的             // 简单的说 比如你加了 DateTimeFormat,已经将writeCellStyle里面的dataFormatData改了   // 如果你自己new了一个WriteCellStyle,可能注解的样式就失效了            // 然后getOrCreateStyle 用于返回一个样式,如果为空,则创建一个后返回            // (总之记住用这个方法获取样式即可)            WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();            writeCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND            // 要不然背景色不会生效            writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);                        // 获取当前单元格的数据,必要的时候可以根据数据来设置单元格的颜色            // 比如当前列为状态列,数据为1是正常,背景色为绿色,反正不正常,背景色设置为红            // 这种需求的实现将变得可能            Object data = cellData.getStringValue();            System.out.println("data: " + data);                        // 这样样式就设置好了 后面有个FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置 到 cell里面去 所以可以不用管了        }    }}

2)写出Excel时注册处理策略

@Testpublic void handlerStyleWrite() {// 创建处理器策略对象    CustomCellWriteStrategy customCellWriteStrategy = new CustomCellWriteStrategy();    // 写出Excel    EasyExcel.write(fileName, DemoData.class)        .registerWriteHandler(customCellWriteStrategy)        .sheet("自定义单个单元格样式演示")        .doWrite(data());}

四、设置列宽

有实体类的时候,可以使用注解去设置列宽,但是如果是那种无模型的,又该怎么去设置列宽呢。

官方提供的LongestMatchColumnWidthStyleStrategy

4.1 AbstractColumnWidthStyleStrategy

1)基础写法

定义一个类,去继承AbstractColumnWidthStyleStrategy这个抽象类,并且重写里面的setColumnWidth方法

public class ExcelWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {        @Override    protected void setColumnWidth(WriteSheetHolder writeSheetHolder,      List<WriteCellData<?>> cellDataList,      Cell cell,      Head head,      Integer relativeRowIndex,      Boolean isHead) {        // 使用sheet对象 简单设置 index所对应的列的列宽        Sheet sheet = writeSheetHolder.getSheet();        sheet.setColumnWidth(cell.getColumnIndex(), 5000);    }}

每处理一个单元格都会调用一次setColumnWidth方法,这个方法有两种重载,重写哪一个都行。

2)自适应列宽写法

public class ExcelWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {     // 单元格的最大宽度    private static final int MAX_COLUMN_WIDTH = 50;                       // 缓存(第一个Map的键是sheet的index, 第二个Map的键是列的index, 值是数据长度)    private  Map<Integer, Map<Integer, Integer>> CACHE = new HashMap(8);        // 重写设置列宽的方法    @Override    protected void setColumnWidth(WriteSheetHolder writeSheetHolder,       List<WriteCellData<?>> cellDataList,       Cell cell,       Head head,       Integer relativeRowIndex,       Boolean isHead) {        boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);        // 当时表头或者单元格数据列表有数据时才进行处理        if (needSetWidth) {            Map<Integer, Integer> maxColumnWidthMap =                 CACHE.get(writeSheetHolder.getSheetNo());                        if (maxColumnWidthMap == null) {                maxColumnWidthMap = new HashMap(16);                CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);            }            // 获取数据长度            Integer columnWidth = this.getLength(cellDataList, cell, isHead);            if (columnWidth >= 0) {                if (columnWidth > MAX_COLUMN_WIDTH) {                    columnWidth = MAX_COLUMN_WIDTH;                }                // 确保一个列的列宽以表头为主,如果表头已经设置了列宽,单元格将会跟随表头的列宽                Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());    if (maxColumnWidth == null || columnWidth > maxColumnWidth) {                    maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);                    // 如果使用EasyExcel默认表头,那么使用columnWidth * 512                    // 如果不使用EasyExcel默认表头,那么使用columnWidth * 256                    // 如果是自己定义的字体大小,可以再去测试这个参数常量                    writeSheetHolder                        .getSheet()                        .setColumnWidth(cell.getColumnIndex(), columnWidth * 512);                }            }        }    }        private Integer dataLength(List<WriteCellData<?>> cellDataList,    Cell cell,    Boolean isHead) {        if (isHead) {            return cell.getStringCellValue().getBytes().length;        } else {            WriteCellData cellData = cellDataList.get(0);            CellDataTypeEnum type = cellData.getType();            if (type == null) {                return -1;            } else {                switch(type) {                    case STRING:                        return cellData.getStringValue().getBytes().length;                    case BOOLEAN:                        return cellData.getBooleanValue().toString().getBytes().length;                    case NUMBER:                        return cellData.getNumberValue().toString().getBytes().length;                    default:                        return -1;                }            }        }    }}

可以根据自己的需求自行改造

4.2 写出Excel时注册处理策略

@Testpublic void handlerStyleWrite() {// 创建处理器策略对象    ExcelWidthStyleStrategy excelWidthStyleStrategy = new ExcelWidthStyleStrategy();    // 写出Excel    EasyExcel.write(fileName, DemoData.class)        .registerWriteHandler(excelWidthStyleStrategy)        .sheet("单个单元格列宽设置")        .doWrite(data());}

五、EasyExcel其它默认设置

5.1 表头自动合并

EasyExcel.write(response.getOutputStream(), DemoData.class)            .automaticMergeHead(false) // 自动合并表头            .sheet("模板")            .doWrite(demoData);

automaticMergeHead设置为true,那么对于相邻表格中存在相同内容单元格,easyexcel会自动将其合并。

它的默认值也是true

如果不想使用表头自动合并,就设置为false即可。

5.2 取消导出Excel的默认风格

EasyExcel.write(response.getOutputStream(), DemoData.class)            .useDefaultStyle(false) // 取消导出Excel的默认风格            .sheet("模板")            .doWrite(demoData);

easyexcel的默认风格是最明显的体现,对于表头会显示灰色背景,并且字体会加粗和放大。

在这里插入图片描述

如果不想使用这个默认风格,把useDefaultStyle设置为false即可。

5.3 是否使用1904日期窗口

EasyExcel.write(response.getOutputStream(), DemoData.class)            .use1904windowing(true) // 设置使用1904的时间格式            .sheet("模板")            .doWrite(demoData);

EasyExcel中时间是存储1900年起的一个双精度浮点数。一般也是使用1900的时间格式就可以了。

如果有业务想把开始日期改为1904,就可以设置use1904windowingtrue即可。

来源地址:https://blog.csdn.net/qq_44749491/article/details/127917454

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

EasyExcel代码层面设置写出的Excel样式、以及拦截器策略的使用、自动列宽设置、EasyExcel默认设置详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录