EasyExcel 导出文件的格式化

news2024/11/26 7:43:46

阿里开源的这个库,让 Excel 导出不再复杂(既要能写,还要写的好看)

之前聊了 EasyExcel 的内容导出,本文主要说一下导出文件的格式化,格式化包括工作表/单元格样式和内容格式化。毕竟,有时候还是要看脸。

内容比较多,文内只会列出关键代码,想要完整源码,可以关注公号「看山的小屋」回复“easyexcel”获取。

注解格式
通过注解定义格式是 EasyExcel 封装的高级功能,可以让我们很方便的定义格式。

格式化内容
先定义一个使用注解格式化内容的实体类:

@Datapublic
class FormatContentItem {
    @ExcelProperty(value = "字符串标题", converter = TitleFormatConverter.class)
    private String string;
    @DateTimeFormat("yyyy 年 MM 月 dd 日 HH 时 mm 分 ss 秒")
    @ExcelProperty(value = "日期标题")
    private Date date;
    @NumberFormat("0.000%")
    @ExcelProperty("数字标题")
    private Double doubleData;
}

其中DateTimeFormat和NumberFormat两个注解都是自带的注解,用于格式化时间和数字。

DateTimeFormat注解有两个属性,一个属性是value,用来定义时间格式,可以参考java.text.SimpleDateFormat;另一个属性是use1904windowing,表示使用时间使用 1904 时间系统还是 1900 时间系统,默认是否。

NumberFormat注解有两个属性,一个属性是value,用来定义数字格式,可以参考java.text.DecimalFormat;另一个属性是roundingMode,用来定义保留小数的方式,使用的是java.math.RoundingMode枚举。

想要格式化字符串,可以借助ExcelProperty的 converter 属性,这个属性传入实现Converter的类。比如示例中的TitleFormatConverter,代码如下:

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

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

    @Override
    public WriteCellData<?> convertToExcelData(
            String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        return new WriteCellData<>(String.format("标题:%s(自定义)", value));
    }
}

结果为:
在这里插入图片描述

定义行高、列宽
使用注解定义行高的话,可以使用HeadRowHeight定义表头高度,使用ContentRowHeight定义表体高度,这个注解定义之后,所有表体高度都是相同的。列宽可以使用ColumnWidth注解定义,这个注解可以定义在类上,表示整个表格的列都一样宽,也可以定义的属性上,表示指定列的宽度。

@Data
@HeadRowHeight(20)
@ContentRowHeight(10)
@ColumnWidth(25)
public class FormatCellItem {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ColumnWidth(50)
    @ExcelProperty("数字标题")
    private Double doubleData;
}

结果为:
在这里插入图片描述
单元格定义样式
控制单元格样式有四个注解:HeadStyle、HeadFontStyle、ContentStyle、ContentFontStyle,这四个注解可以定义在类上作为全局表格的样式,也可以定义在字段上,作为当前列的样式。下面分别说一下这几个注解中比较常用的配置。

Style:分为HeadStyle和ContentStyle,分别定义表头和表体样式
dataFormat:表头格式化,short 格式,是org.apache.poi.ss.usermodel.BuiltinFormats类中已定义格式的小标
border
:分别是 borderLeft、borderRight、borderTop、borderBottom 四个属性,类型是com.alibaba.excel.enums.poi.BorderStyleEnum枚举,用来定义表头单元格边框样式。边框的颜色也可以定义,使用、*BorderColor 定义即可。
fillPatternType:填充类型,类型是com.alibaba.excel.enums.poi.FillPatternTypeEnum枚举,如果想要填充背景色,这个属性需要设置为SOLID_FOREGROUND。
fillForegroundColor:前景色,类型是 short,值却是使用的org.apache.poi.ss.usermodel.IndexedColors枚举的 idx 值,只不过,两个类型不一致,一个是 short,一个是 int,没有办法直接引用。可见 java 中的依赖之间,还是有很多坑的。
fillBackgroundColor:背景色,同fillForegroundColor。
rotation:内容旋转角度
*FontStyle:有HeadFontStyle和ContentFontStyle,分别定义表头和表体的字体样式。
fontName:定义字体名称,类型字符串
fontHeightInPoints:字号大小,类型是 short
italic:是否斜体,类型是com.alibaba.excel.enums.BooleanEnum
bold:是否加粗,类型是com.alibaba.excel.enums.BooleanEnum
strikeout:是否使用删除线(这个词本意是三振出局的意思,应该是与棒球有关)
color:文本颜色,值使用的是org.apache.poi.ss.usermodel.IndexedColors,依然有类型不一致的情况
underline:下划线,类型是 byte,可以直接使用Font.U_NONE、Font.U_SINGLE、Font.U_DOUBLE、Font.U_SINGLE_ACCOUNTING、Font.U_DOUBLE_ACCOUNTING。
我们可以这么定义:

@Data

// 头背景设置成红色 IndexedColors.RED.getIndex()
@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 10)

// 头字体设置成 20
@HeadFontStyle(fontHeightInPoints = 20)

// 内容的背景设置成绿色 IndexedColors.GREEN.getIndex()
@ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 17)

// 内容字体设置成 20
@ContentFontStyle(fontHeightInPoints = 20)
public class FormatStyleCellItem {
    
    // 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()   
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 14)
  
   // 字符串的头字体设置成 20
    @HeadFontStyle(fontHeightInPoints = 30)
  
   // 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()  
    @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)    
   
    // 字符串的内容字体设置成 20
    @ContentFontStyle(fontHeightInPoints = 30)
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
}

结果为:
在这里插入图片描述
类对象定义格式
这种方式可以说是纯手工组装数据了,使用的是com.alibaba.excel.metadata.data.WriteCellData类,这个类相当于是单元格的定义,通过设置com.alibaba.excel.enums.CellDataTypeEnum枚举类型的 type 属性,可以指明当前单元格格式。

守恒定律一直存在。这种方式灵活度很高,可以精细到具体的单元格格式,但是繁琐程度也增加了。

超链接
超链接使用的是com.alibaba.excel.metadata.data.HyperlinkData类,需要设置地址、超链类型(com.alibaba.excel.metadata.data.HyperlinkData.HyperlinkType枚举),然后将值写入到WriteCellData对象的hyperlinkData属性即可。

        // 设置超链接HyperlinkData 
        hyperlinkData=new HyperlinkData();
        hyperlinkData.setAddress("https://www.howardliu.cn");hyperlinkData.setHyperlinkType(HyperlinkType.URL);
        WriteCellData<String> hyperlink=new WriteCellData<>("网站");hyperlink.setHyperlinkData(hyperlinkData);

备注
备注使用的是com.alibaba.excel.metadata.data.CommentData类,需要设置作者、备注内容(com.alibaba.excel.metadata.data.RichTextStringData类型),因为备注的默认大小是单元格大小,如果感觉太小,还可以设置相对高度和宽度。

// 设置备注CommentData 
commentData=new CommentData();commentData.setAuthor("Howard Liu");
commentData.setRichTextStringData(new RichTextStringData("这是一个备注"));
// 备注的默认大小是按照单元格的大小 这里想调整到 4 个单元格那么大 所以向后 向下 各额外占用了一个单元格
commentData.setRelativeLastColumnIndex(1);commentData.setRelativeLastRowIndex(1);
WriteCellData<String> comment = new WriteCellData<>("备注的单元格信息");
comment.setCommentData(commentData);

公式
公式使用的是com.alibaba.excel.metadata.data.FormulaData类,可以直接设置formulaValue公式,不过官方不太推荐使用公式。

// 设置公式
FormulaData formulaData = new FormulaData();
// 将 123456789 中的第一个数字替换成 
// 2// 这里只是例子 如果真的涉及到公式 能内存算好尽量内存算好 公式能不用尽量不用
formulaData.setFormulaValue("REPLACE(123456789,1,1,2)");
 WriteCellData<String> formula = new WriteCellData<>();formula.setFormulaData(formulaData);

单元格格式
通过类定义单元格格式,与通过注解定义本质是一样的。所以与注解HeadStyle、HeadFontStyle、ContentStyle、ContentFontStyle对应,设置单元格格式的类是WriteCellStyle,设置字体的类是WriteFont。其中这些类的属性与注解的也是类似,不再赘述太多,直接上例子。(其实我觉得使用类定义格式的场景不多,真的碰到了,看看类定义就明白了)

// 设置单个单元格的样式 当然样式 很多的话 也可以用注解等方式。
WriteCellStyle writeCellStyleData=new WriteCellStyle();
// 这里需要指定 FillPatternType 为 FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色。
        writeCellStyleData.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// 背景绿色
        writeCellStyleData.setFillForegroundColor(IndexedColors.GREEN.getIndex());
        WriteCellData<String> writeCellStyle=new WriteCellData<>("单元格样式");
        writeCellStyle.setWriteCellStyle(writeCellStyleData);
        writeCellStyle.setType(CellDataTypeEnum.STRING);
// 设置单个单元格多种样式
        RichTextStringData richTextStringData=new RichTextStringData();
        richTextStringData.setTextString("红色绿色默认");
// 前 2 个字红色
        WriteFont writeFont=new WriteFont();
        writeFont.setColor(IndexedColors.RED.getIndex());
        richTextStringData.applyFont(0,2,writeFont);
// 接下来 2 个字绿色
        writeFont=new WriteFont();
        writeFont.setColor(IndexedColors.GREEN.getIndex());
        richTextStringData.applyFont(2,4,writeFont);
        WriteCellData<String> richTest=new WriteCellData<>();
        richTest.setType(CellDataTypeEnum.RICH_TEXT_STRING);
        richTest.setRichTextStringDataValue(richTextStringData);

结果为:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1332508.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【leetcode21】合并两个有序链表Java代码讲解

12.22 21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2…

Appium Server 启动失败常见原因及解决办法

Error: listen EADDRINUSE: address already in use 0.0.0.0:4723 如下图&#xff1a; 错误原因&#xff1a;Appium 默认的4723端口被占用 解决办法&#xff1a; 出现该提示&#xff0c;有可能是 Appium Server 已启动&#xff0c;关闭已经启动的 Appium Server 即可。472…

音视频类App广告变现如何破局,最大化广告变现收益,让应用增收?

音视频App已然成为了我们日常获取、发布和交换信息的重要方式&#xff0c;在音视频行业不断的拓展中&#xff0c;用户的渗透率提升。 据数据显示&#xff0c;我国网络视听用户的规模已达9亿人次&#xff0c;网民使用率也突破了90%。庞大的市场规模和用户需求吸引了大批开发者和…

SRE - 监控建设

监控⽂档 随着信息技术的迅速发展及其在商业和工业环境中的广泛应用,系统的可靠性成为了组织的生存之本。Site Reliability Engineering(SRE)作为一种实践的结合体,广泛地用于确保和提升软件系统的可靠性。其中,它的一个重要组成部分是制定和监控服务的关键性能指标(Ser…

行为型设计模式(五):访问者模式 观察者模式

访问者模式 Visitor 1、什么是访问者模式 访问者模式允许定义一些不改变数据结构的前提下的操作。通过这种方式&#xff0c;可以在不修改元素类的情况下定义新的操作。访问者模式常用于对复杂对象结构进行操作&#xff0c;而又不希望在这些对象上破坏封装性。 2、为什么使用…

摄影企业网站搭建的作用是什么

几乎每个成年人都有一部手机&#xff0c;在互联网信息时代&#xff0c;手机的作用不言而喻&#xff0c;拍照/摄像成为了不少人经常会做的事&#xff0c;拍一张美美的照片发到社交圈赢得赞声&#xff0c;或是为以后留下回忆或发给自己在意的人&#xff0c;但这只限于生活记叙类图…

收集足够苹果的最小花园周长(LeetCode日记)

LeetCode-1954-收集足够苹果的最小花园周长 题目信息: 给你一个用无限二维网格表示的花园&#xff0c;每一个 整数坐标处都有一棵苹果树。整数坐标 ( i , j ) (i, j) (i,j) 处的苹果树有 ∣ i ∣ ∣ j ∣ |i| |j| ∣i∣∣j∣ 个苹果。 你将会买下正中心坐标是 ( 0 , 0 )…

免费使用谷歌Gemini模型学习LLM编程

虽然谷歌的Gemini大语言模型爆出很大的乌龙&#xff0c;但这不影响我们使用Gemini Pro来学习LLM编程。 目前Bard还没有全部切换为Gemini Pro模型&#xff0c;但是作为程序员&#xff0c;已经不需要等待&#xff0c;可以直接调用Gemini Pro的接口了。谷歌这次开发者优先的做法值…

12.23C语言 指针

& 地址运算符&#xff0c;用于取地址 /*注释内容*/ //注释一行 *的意思&#xff1a;1.算术运算符 2.用于指针声明int *ptr;表示这个变量是一个指针3.数组元素访问&#xff1a;在数组名后面使用 * 可以表示数组的起始地址。例如&#xff1a; int arr[5] {1, 2, 3, 4, 5…

WEB 3D技术 three.js 通过lil-gui 控制x y z轴数值 操作分组 设置布尔值控制 颜色材质控制

上文 WEB 3D技术 three.js 通过lil-gui管理公共事件中 我们用 lil-gui 处理了一下基础事件和按钮的管理 那么 本文 我们来具体说说它能做的其他事 我们先将基础代码改成这样 import ./style.css import * as THREE from "three"; //引入lil-gui import { GUI } fro…

题解:CF1914E-Game with Marbles

题解&#xff1a;CF1914E-Game with Marbles 事先说明一下&#xff0c;本题解不讲解简单数据范围的算法&#xff0c;因为复杂数据范围的就很简单。 这道题的大体意思是这样的&#xff1a;小A有颜色为i(i1~n)的小球a[i]个&#xff0c;小B有颜色为i(i1~n)的小球b[i]个。现在他们…

有关List的线程安全、高效读取:不变模式下的CopyOnWriteArrayList类、数据共享通道:BlockingQueue

有关List的线程安全 队列、链表之类的数据结构也是极常用的&#xff0c;几乎所有的应用程序都会与之相关。在java中&#xff0c; ArrayList和Vector都使用数组作为其内部实现。两者最大的不同在与Vector是线程安全的。 而ArrayList不是。此外LinkedList使用链表的数据结构实现…

ubuntu 22.04 安装mysql服务

完整内容&#xff1a; https://developer.aliyun.com/article/1260321 # 安装服务 sudo apt install mysql-server# 按向导设置root密码 sudo mysql_secure_installation# 使用设置的密码登录 sudo mysql -u root -p也可以使用工具登录&#xff0c;例如: navicat for mysql

掌握iText:轻松实现固定pdf模板的动态数据填充

推荐语 如果你在工作中需要处理大量的PDF表单&#xff0c;那么使用iText5实现固定PDF模板的动态数据填充&#xff0c;将是一种非常有效的方法。这篇技术文章详细介绍了如何使用iText5库来读取已有的PDF模板&#xff0c;并动态地填充表单数据&#xff0c;生成最终的表单文件。通…

虚拟机的下载、安装(模拟出服务器)

下载 vmware workstation&#xff08;收费的虚拟机&#xff09; 下载vbox 网址&#xff1a;Oracle VM VirtualBox&#xff08;免费的虚拟机&#xff09; 以下选择一个下载即可&#xff0c;建议下载vbox&#xff0c;因为是免费的。安装的时候默认下一步即可&#xff08;路径最好…

Vue2从源码角度来回答一些常见的问题

1.请说一下Vue2响应式数据的理解&#xff08;先知道基本的问题在哪里&#xff0c;源码的角度来回答&#xff0c;用的时候会有哪些问题&#xff09; 可以监控一个数据的修改和获取操作。针对对象格式会给每个对象的属性进行劫持 Object.defineProperty 源码层面 initData ->…

卷积神经网络基础与补充

参考自 up主的b站链接&#xff1a;霹雳吧啦Wz的个人空间-霹雳吧啦Wz个人主页-哔哩哔哩视频这位大佬的博客 https://blog.csdn.net/m0_37867091?typeblog CNN的历史发展&#xff1a; 这一点老师上课的时候也有讲到&#xff0c;BP的出现对CNN的发展至关重要 卷积的特性&#x…

nodejs+vue+ElementUi大学新生入学系统的设计与实现1hme0

采用B/S模式架构系统&#xff0c;开发简单&#xff0c;只需要连接网络即可登录本系统&#xff0c;不需要安装任何客户端。开发工具采用VSCode&#xff0c;前端采用VueElementUI&#xff0c;后端采用Node.js&#xff0c;数据库采用MySQL。 涉及的技术栈 1&#xff09; 前台页面…

kubelet源码学习(二):kubelet创建Pod流程

本文基于Kubernetes v1.22.4版本进行源码学习 4、kubelet创建Pod流程 syncLoop()的主要逻辑是在syncLoopIteration()方法中实现&#xff0c;Pod创建相关代码只需要看处理configCh部分的代码 // pkg/kubelet/kubelet.go // 该方法会监听多个channel,当发现任何一个channel有数…

Springboot+vue的交通管理在线服务系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的交通管理在线服务系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的交通管理在线服务系统&#xff0c;采用M&#xff08;m…