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

这篇具有很好参考价值的文章主要介绍了EasyExcel代码层面设置写出的Excel样式、以及拦截器策略的使用、自动列宽设置、EasyExcel默认设置详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

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

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

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

主要步骤:

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

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

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

2.1 定义一个Excel实体类

@Getter
@Setter
@EqualsAndHashCode
public 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);				// 设置字体大小为20
headWriteFont.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<WriteCellStyle>集合
    // 第一个参数是表头部分单元格的样式
    // 第二个参数是内容部分的单元格样式
    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<WriteCellStyle>参数时,会循环渲染集合中的样式对象。

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

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

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

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

// 完整代码
@Test
public 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)具体使用

@Test
public 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时注册处理策略

@Test
public 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.dataLength(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);
                }

            }
        }
    }

    /**
     * 获取当前单元格的数据长度
     * @param cellDataList
     * @param cell
     * @param isHead
     * @return
     */
    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时注册处理策略

@Test
public 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的默认风格是最明显的体现,对于表头会显示灰色背景,并且字体会加粗和放大。

easyexcel设置表头样式,EasyExcel,excel,java,开发语言

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

5.3 是否使用1904日期窗口

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

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

如果有业务想把开始日期改为1904,就可以设置use1904windowingtrue即可。文章来源地址https://www.toymoban.com/news/detail-636049.html

到了这里,关于EasyExcel代码层面设置写出的Excel样式、以及拦截器策略的使用、自动列宽设置、EasyExcel默认设置详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 开源在线excel展示插件 js excel 在线插件 合并单元格 设置单元格样式 编辑工具

     源码:https://github.com/yufb12/dataexcel.git 在线预览地地址 http://www.dataexcel.cn/dataexceljs.html 1、js 版本 es6  2、绘图引擎 zrender 地址  ZRender 文档 (ecomfe.github.io)  3、 文件保存格式json  4、创建并初始化  5、文件 新建保存

    2024年02月17日
    浏览(39)
  • Sa-Token v.1.31.0 新增拦截器 SaInterceptor 功能说明,以及旧代码迁移示例

    前言 如果你的项目没有使用旧写法,可以忽略本篇文章 移步官网,本文只针对旧版本到新版本的迁移提供示例。 1、旧版本 Sa-Token 在 1.30.0 及以下版本中使用两个拦截器: SaAnnotationInterceptor :负责提供注解鉴权能力。 SaRouteInterceptor :负责提供路由拦截鉴权能力。 这次新增

    2024年02月07日
    浏览(80)
  • 【Vue】动态设置元素类以及样式

    1.动态设置类 class 1.1 字符串语法 通过 v-bind 绑定元素的 class 属性,为其指定一个字符串: 此时我们可以通过改变 className 变量来切换样式。注意,当 className 为 \\\'\\\' 时,这个class属性仍然会被添加到真实DOM上,只不过没有值。 1.2 对象语法 通过 v-bind 绑定元素的 class 属性,为其

    2024年02月11日
    浏览(24)
  • 为什么通过EasyExcel下载 Excel 文件时,response.setContentType(“application/octet-stream“) 这样设置,下载下来的文件不能显示文件名称?

    response.setContentType(\\\"application/octet-stream\\\") 是用来告诉浏览器服务器返回的数据是二进制流,因为 octet-stream 意味着 \\\"一个未知的字节流\\\"。当浏览器收到这个响应时,它无法确定数据类型,所以它的解析方式会尝试将这些未知字节自动转换为可读的格式。 当您使用 EasyExcel 将数据

    2024年02月13日
    浏览(36)
  • 工具类——Java导出EXCEL2(设置样式、加载并填充图片、加载指定模板、大数据量设置窗口大小与刷新频率)

    书接上篇:工具类——Java 浏览器导入、导出Excel(Java import、export)demo POI的导出方式:创建/加载Workbook,设置样式,填充数据,然后生成本地临时文件,最终以浏览器的形式打开,完成整个导出动作。 demo如下, demo如下, XSSFClientAnchor anchor = new XSSFClientAnchor(int dx1, int dy1,

    2024年02月01日
    浏览(34)
  • matplotlib图例(legend)如何自由设置其位置、大小以及样式

    python matplotlib中: 这一条代码会帮我们显示图例,而且通常,其会放置在图片中一个不错的位置。但是如果我们的数据,占满了整个图像,此时,其放的位置就会出问题了。 这个参数内置了一些位置,如果这些位置恰好有你想要的,那么用这个就行了,很方便。 这个是绝招

    2024年02月11日
    浏览(37)
  • 纯前端 —— 200行JS代码、实现导出Excel、支持DIY样式,纵横合并

    前期回顾 Vue3 + TS + Element-Plus 封装Tree组件 《亲测可用》_vue3+ts 组件封装-CSDN博客 https://blog.csdn.net/m0_57904695/article/details/131664157?spm=1001.2014.3001.5501 目录 具体思路: 1. 准备HTML结构 2. 定义CSS样式 3. 初始化表格数据 4. 创建表格函数createTable 5. 将表格添加到页面中 6. 导出表格为E

    2024年02月02日
    浏览(27)
  • (完美解决)matplotlib图例(legend)如何自由设置其位置、大小以及样式。

    前言 我们知道,这一条代码会帮我们显示图例,而且通常,其会放置在图片中一个不错的位置。但是如果我们的数据,占满了整个图像,此时,其放的位置就会出问题了。 那么我们该如何自由设置图例位置呢? 位置:loc 这个参数内置了一些位置,如果这些位置恰好有你想要

    2023年04月09日
    浏览(38)
  • easyexcel导入导出+动态列+自定义样式

    目录 1、引用maven依赖 2、模板文件template1.xlsx 3、导出效果 4、导入效果 5、导出用EasyWriteHandler 6、测试工具类 ExcelTest

    2024年02月15日
    浏览(45)
  • EasyExcel格式化映射注解和样式注解详解

    使用注解很简单,只要在对应的实体类上面加上注解即可。 也就是说使用实体类模型来读写 Excel 文件时,可以通过注解来控制实体类字段和 Excel 列之间的对应关系。 2.1 作用 ExcelProperty 注解用于匹配 excel 和实体类字段之间的关系。 可以作用于字段上。 2.1 注解参数 名称 默

    2024年01月20日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包