Myexcel入门
Myexcel入门
简介
Myexcel 是一个可以导入、导出和加密 excel 的工具包。
优点
- 生成任意复杂表格
- 支持图片导入导出
- 完全屏蔽POI复杂度:使用HTML作为模板,学习成本几乎为零,无需关心POI本身的任何操作
- 支持常用的背景色、边框、字体等样式设置:详情
- 支持多种模板引擎:内置FreeMarker、groovy、Beetl、thymeleaf等常用模板引擎
- 低内存导入导出
测试文件,24.3m excel,500000行,8列,循环读取40次,平均内存占用约75兆,对比阿里巴巴easyexcel(v2.1.6)同文件测试,内存占用约三分之一easyexcel。
- MyExcel所有版本均只支持jdk8+
- 模板文件只能放在classpath下
入门使用示例
依赖添加
<dependency>
<groupId>com.github.liaochong</groupId>
<artifactId>myexcel</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
Excel默认导出
附件导出示例:
public void defaultBuild(HttpServletResponse response) throws Exception {
List<ArtCrowd> dataList = this.getDataList();
// 默认导出默认计算宽度、斑马线背景色
Workbook workbook = DefaultExcelBuilder.of(ArtCrowd.class).build(dataList);
// 不使用默认样式
// Workbook workbook = DefaultExcelBuilder.of(ArtCrowd.class).noStyle().build(dataList);
// 宽度策略 无自动宽度 NO_AUTO | 自适应宽度 AUTO_WIDTH | 组件调整宽度 COMPUTE_AUTO_WIDTH
//Workbook workbook = DefaultExcelBuilder.of(ArtCrowd.class).widthStrategy(WidthStrategy.AUTO_WIDTH).build(dataList);
// 普通导出
// AttachmentExportUtil.export(workbook, "艺术生信息", response);
// 加密导出
AttachmentExportUtil.encryptExport(workbook, "艺术生信息", response,"111");
}
文件导出示例:
public void defaultBuild() {
List<ArtCrowd> dataList = this.getDataList();
Workbook workbook = DefaultExcelBuilder.of(ArtCrowd.class).build(dataList);
// 普通导出
// FileExportUtil.export(workbook, new File("/User/demo.xlsx"));
// 加密导出
FileExportUtil.encryptExport(workbook, new File("/User/demo.xlsx"),"123456");
}
Excel流式导出
流式导出和默认导出的区别在于,流式导出采用生产者消费者模式,可以批量获取数据,批量写入excel。
使用步骤
-
导出配置
DefaultStreamExcelBuilder<ArtCrowd> streamExcelBuilder = DefaultStreamExcelBuilder .of(ArtCrowd.class) .threadPool(Executors.newFixedThreadPool(10))// 线程池 可选 .capacity(1000)// 设置excel 容量 如果设置,当Excel行数达到容量时,将生成一个新的EXCEL 可选 .start();
-
数据添加
append 参数可以是列表或单个数据
streamExcelBuilder.asyncAppend(this::getDataList);
-
构建完成
Workbook workbook = streamExcelBuilder.build();
-
导出数据
附件导出
AttachmentExportUtil.export(workbook, "艺术生信息1", response);
多文件导出
List<Path> paths = streamExcelBuilder.buildAsPaths();
Zip文件导出
Path zip = streamExcelBuilder.buildAsZip("test"); // 设置了capacity AttachmentExportUtil.export(zip,"finalName.zip",response);
Excel动态导出
-
动态指定标题和字段顺序
List<String> titles = new ArrayList<>(); titles.add("姓名"); titles.add("年龄"); List<String> order = new ArrayList<>(); order.add("name"); order.add("age"); Workbook workbook = DefaultExcelBuilder.of(TestDO.class) .sheetName("default example") .titles(titles) // 自定义表头 .fieldDisplayOrder(order) // 自定义顺序 .build(dataList);
-
字段分组
该方法基于注解@ExcelColumn的groups属性
@ExcelColumn(title="姓名",groups={People.class}) String name; @ExcelColumn(title="年龄") String age; DefaultExcelBuilder.of(ArtCrowd.class).build(People.class);
上面的例子只会导出“name”字段
-
map数据导出
Excel模板导出
常用
public void buildWithDefaultStyle(HttpServletResponse response) {
Map<String, Object> dataMap = this.getDataMap();
try (FreemarkerExcelBuilder excelBuilder = new FreemarkerExcelBuilder()){
Workbook workbook = excelBuilder
// fileTemplate(dirPath,fileName)
.classpathTemplate("/templates/freemarkerToExcelExample1.ftl")
.build(dataMap);
AttachmentExportUtil.export(workbook, "freemarker_excel", response);
} catch (IOException e) {
e.printStackTrace();
}
}
多个table生成在同一个sheet里
public void buildWithDefaultStyle(HttpServletResponse response) {
Map<String, Object> dataMap = this.getDataMap();
try (FreemarkerExcelBuilder excelBuilder = new FreemarkerExcelBuilder()){
Workbook workbook = excelBuilder
.classpathTemplate("/templates/freemarkerToExcelExample1.ftl")
.sheetStrategy(SheetStrategy.ONE_SHEET)
.build(dataMap);
AttachmentExportUtil.export(workbook, "freemarker_excel", response);
} catch (IOException e) {
e.printStackTrace();
}
}
效果
每个table各生成一个sheet
public void buildWithDefaultStyle(HttpServletResponse response) {
Map<String, Object> dataMap = this.getDataMap();
try (FreemarkerExcelBuilder excelBuilder = new FreemarkerExcelBuilder()){
Workbook workbook = excelBuilder
.classpathTemplate("/templates/freemarkerToExcelExample1.ftl")
.sheetStrategy(SheetStrategy.MULTI_SHEET)
.build(dataMap);
AttachmentExportUtil.export(workbook, "freemarker_excel", response);
} catch (IOException e) {
e.printStackTrace();
}
}
效果
sheet1
sheet2
sheet3
支持公式
在td上添加属性:formula,无需设定具体值
<table>
<tr>
<td>1</td>
</tr>
<tr>
<td>19</td>
</tr>
<tr>
<td formula>SUM(A1:A2)</td>
</tr>
</table>
单元格设置
string
<table>
<tr>
<td string>199999999999999.0999999234</td>
</tr>
</table>
double
<table>
<tr>
<td double>199999999999999.0999999234</td>
</tr>
</table>
boolean
<table>
<tr>
<td boolean>true</td>
</tr>
</table>
单元格斜线绘制
斜线样式:
SOLID、DOT、DASH、LG_DASH、DASH_DOT、LG_DASH_DOT、LG_DASH_DOT_DOT、SYS_DASH、SYS_DOT、SYS_DASH_DOT、SYS_DASH_DOT_DOT
// 2代表斜线的宽度width #000000 颜色
<td slant="solid 2 #000000">
</td>
添加批注
<td comment-text="批注内容" comment-author="作者"></td>
freemarkerToExcelExample1.ftl
<table>
<caption>${sheetName}</caption>
<thead>
<tr style="background-color: #6495ED">
<th colspan="3" style="text-align: center;vertical-align: middle;font-weight: bold;font-size: 14px;">产品介绍</th>
</tr>
<tr>
<#list titles as title>
<th>${title}</th>
</#list>
</tr>
</thead>
<tbody>
<#list data as item>
<tr>
<td>${item.category}</td>
<td>${item.name}</td>
<td>${item.count}</td>
<td url>百度地址</td>
</tr>
</#list>
</tbody>
</table>
<table>
<caption>${sheetName}</caption>
<thead>
<tr style="background-color: #6495ED">
<th colspan="3" style="text-align: center;vertical-align: middle;font-weight: bold;font-size: 14px;">产品介绍</th>
</tr>
<tr>
<#list titles as title>
<th>${title}</th>
</#list>
</tr>
</thead>
<tbody>
<#list data1 as item>
<tr>
<td style="border-top-style:dotted">${item.category}</td>
<td style="border-top-style:thick">${item.name}</td>
<td style="border-top-style:double">${item.count}</td>
<td url>百度地址</td>
<td style="border-top-style:hair"></td>
<td style="border-top-style:medium_dashed"></td>
<td style="border-top-style:dash_dot"></td>
</tr>
</#list>
</tbody>
</table>
<table>
<caption>${sheetName}</caption>
<thead>
<tr style="background-color: #6495ED">
<th colspan="3" style="text-align: center;vertical-align: middle;font-weight: bold;font-size: 14px;">产品介绍</th>
</tr>
<tr>
<#list titles as title>
<th>${title}</th>
</#list>
</tr>
</thead>
<tbody>
<#list data2 as item>
<tr>
<td style="text-decoration: underline;font-style:italic;border-top-style:thin;font-family: 微软雅黑">${item.category}</td>
<td style="text-decoration: line-through ;font-family:Times Microsoft YaHei UI;border-top-style:dashed">${item.name}</td>
<td style="border-top-style:medium">${item.count}</td>
<td url>百度地址</td>
<td><a href="http://www.baidu.com">百度</a></td>
<td><a url="http://www.baidu.com">Baidu</a></td>
<td style="color:blue"><a href="mailto:poi@apache.org?subject=Hyperlinks">邮件地址</a></td>
<td dropDownList>男, 女</td>
<td style="width: 10px;height: 10px">
</td>
<td string>19</td>
<td string slant="solid 2 #000000">199999999999999.0999999234</td>
<td double>199999999999999.0999999234</td>
<td boolean>19</td>
</tr>
</#list>
</tbody>
</table>
<table>
<tr>
<td>1</td>
</tr>
<tr>
<td>19</td>
</tr>
<tr>
<td formula>SUM(A1:A2)</td>
</tr>
<tr>
<td formula>MAX(A1:A2)</td>
</tr>
<tr>
<td string slant="SOLID 2 #000000">SOLID</td>
</tr>
<tr>
<td string slant="DOT 2 #000000">DOT</td>
</tr>
<tr>
<td string slant="DASH 2 #000000">DASH</td>
</tr>
<tr>
<td string slant="LG_DASH 2 #000000">LG_DASH</td>
</tr>
<tr>
<td string slant="DASH_DOT 2 #000000">DASH_DOT</td>
</tr>
<tr>
<td string slant="LG_DASH_DOT 2 #000000">LG_DASH_DOT</td>
</tr>
<tr>
<td string slant="LG_DASH_DOT_DOT 2 #000000">LG_DASH_DOT_DOT</td>
</tr>
<tr>
<td string slant="SYS_DASH 2 #000000">SYS_DASH</td>
</tr>
<tr>
<td string slant="SYS_DOT 2 #000000">SYS_DOT</td>
</tr>
<tr>
<td string slant="SYS_DASH_DOT 2 #000000">SYS_DASH_DOT</td>
</tr>
<tr>
<td string slant="SYS_DASH_DOT_DOT 2 #000000" comment-text="批注内容" comment-author="作者">SYS_DASH_DOT_DOT</td>
</tr>
</table>
CSV导出
public void csv(HttpServletResponse response) {
Csv csv = CsvBuilder.of(ArtCrowd.class)
.build(getDataList());
AttachmentExportUtil.export(csv.getFilePath(), "123.csv", response);
}
自定义样式
标题(title)样式自定义
@ExcelColumn(style={"title->color:red","cell->color:green"})
Integer age;
内容行样式自定义
@ExcelColumn(style="cell->color:green")
Integer age;
方法调用设定样式
DefaultExcelBuilder.of(ArtCrowd.class)
.style("title->color:red","background-color:green;")
.build(dataList);
注
使用 ->
分隔符:
title
标明该样式针对标题;cell
标明该样式针对内容行;odd
标明该样式针对奇数内容行;even
标明该样式针对偶数内容行;
模板设定样式
<tr>
<td style="text-decoration: underline;font-style:italic;border-top-style:thin;font-family: 微软雅黑">${item.category}</td>
<td style="text-decoration: line-through ;font-family:Times Microsoft YaHei UI;border-top-style:dashed" >${item.name}</td>
<td style="border-top-style:medium">${item.count}</td>
<td url>百度地址</td>
</tr>
常用样式
width
CSS | Value | Example |
---|---|---|
width | such as 15px | style="width: 15px" |
height
CSS | Value | Example |
---|---|---|
height | such as 15px, special attention A kind of If the template is used, the style can only be placed on tr | style="height: 15px" |
background
CSS | Value | Example |
---|---|---|
background-color | Hex: ffffff, RGB: rgb (0255255), common background color name: green, Hex is recommended | style="background-color:#ABFF00" |
border
CSS | Value | Example |
---|---|---|
border-style | thin、dashed、medium、dotted、thick、double、hair、medium_dashed、dash_dot | style="border-style:thin" |
border-top-style | thin、dashed、medium、dotted、thick、double、hair、medium_dashed、dash_dot | style="border-top-style:thin" |
border-right-style | thin、dashed、medium、dotted、thick、double、hair、medium_dashed、dash_dot | style="border-top-style:thin" |
border-bottom-style | thin、dashed、medium、dotted、thick、double、hair、medium_dashed、dash_dot | style="border-top-style:thin" |
border-left-style | thin、dashed、medium、dotted、thick、double、hair、medium_dashed、dash_dot | style="border-top-style:thin" |
font
CSS | Value | Example |
---|---|---|
color | green | style="color:green;" |
font-size | value: 14px (only the value will be intercepted, and the non value part will be deleted) | style="font-size:14px" |
font-family | Times New Roman(alternative fonts are not supported) | style="font-family:Times New Roman" |
font-style | italic | style="font-style:italic" |
font-weight | bold | style="font-weight:bold" |
text-decoration | line-through、underline | style="text-decoration: underline" |
多级表头
多级表头,针对的是DefaultExcelBuilder、DefaultStreamExcelBuilder
@ExcelColumn(title="拓展信息->年龄")
Integer age
默认以->
作为分隔符,也可自定义分隔符:@ExcelModel(titleSeparator="#")
@ExcelColumn(title="拓展信息#年龄")
Integer age
单元格换行
DefaultExcelBuilder、DefaultStreamExcelBuilder
@ExcelModel(wrapText=true)
public class Entity(){
}
模板换行使用<br/或者
图片导出
属性定义
@ExcelColumn(fileType = FileType.IMAGE)
File image;
@ExcelColumn(fileType = FileType.IMAGE)
InputStream image;
@ExcelColumn(fileType = FileType.IMAGE)
Path image;
@ExcelColumn(fileType = FileType.IMAGE)
String image="https://img1.baidu.com/it/u=1499001738,37769528&fm=253&fmt=auto&app=120&f=JPEG?w=889&h=500";
@ExcelColumn(fileType = FileType.IMAGE)
String image="/Usr/location/1.jpg";
模板导出
<td>
<img src="图片路径(绝对路径、Http、base64)"/>
</td>
效果图
下拉列表
该功能仅针对DefaultExcelBuilder、DefaultStreamExcelBuilder
下拉列表是受字数限制的。列表的总字符不能超过 250 个字符
@ExcelColumn(title="下拉列表")
List<String> options;
模板下拉列表
option 1, option 2, option 3 , 英文逗号分隔
<td dropDownList>option 1, option 2, option 3</td>
写入自定义转化
简单映射
该功能仅针对DefaultExcelBuilder、DefaultStreamExcelBuilder。
导出经常遇到的一个场景:导出数据包含可枚举字段,如性别,存储在数据库中以0、1,导出为男、女。
@ExcelColumn(title="性别",mapping="0:男,1:女")
Integer gender;
使用 mapping
属性,以 ,
分隔成组,每组以 :
分隔,需要注意的是,该属性仅支持简单映射,不支持含有:
,,
特殊字符的映射
自定义转化
实现CustomWriteConverter<Object, Object>接口
// 1
@Component
public class DefaultCustomWriteConverter implements CustomWriteConverter<Object, Object> {
@Autowired
private MyConverter myConverter;
@Override
public Object convert(Object originalData, CustomWriteContext customWriteContext) {
if (originalData.equals(0)) {
return "男";
}else {
return "女";
}
}
}
//2 使用注解
@ExcelColumn(title = "性别", writeConverter = DefaultCustomWriteConverter.class)
Integer gender;
// 3.如使用了spring等,则需要绑定上下文,如无,则无需使用binding
@Autowired
private DefaultCustomWriteConverter defaultCustomWriteConverter;
DefaultStreamExcelBuilder.of(Stu.class).binding(defaultCustomWriteConverter).start();
添加水印
// 使用水印工具添加水印
WatermarkUtil.addWatermark(workbook,"水印");
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现