EasyExcel导出工具类
前言
此工具类包含常用的
1.下载模板
2.导出Excel
3.自定义策略导出Excel
3.简单填充
4.列表填充并通过响应流返回
5.单个对象简单填充
6.复杂填充(支持单值 + 列表混合填充)
7.复杂填充并合并单元格(支持单值 + 列表混合填充 + 自定义合并单元格)
8.多列填充 + 单值填充
EasyExcel官方文档:
https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill
导出模板及效果
4.列表填充并通过响应流返回
导出的模板

导出后的文件

5.单个对象简单填充
导出的模板

导出后的文件

6.复杂填充(支持单值 + 列表混合填充)
导出的模板

导出后的文件

7.复杂填充并合并单元格(支持单值 + 列表混合填充 + 自定义合并单元格)
导出的模板

导出后的文件

8.多列填充 + 单值填充
导出的模板
说明:data0/data1…就是方法里面alias的值

导出后的文件

导出工具类代码
package cn.crec.smart.common.utils;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class ExcelExportUtil {
/**
* 1.下载模版文件
* @Params: response 响应体
* @Params: inputStream 文件输入流
* @Params: fileName 文件名
* @Params: suffix 文件后缀名
*/
public static void downloadTemplate(HttpServletResponse response, InputStream inputStream, String fileName, String suffix) throws IOException {
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("\\+", "%20");
response.setHeader("Content-Disposition", "filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
ServletOutputStream outputStream = response.getOutputStream();
ExcelWriter excelWriter = EasyExcelFactory.write(outputStream).withTemplate(inputStream).build();
excelWriter.finish();
outputStream.flush();
}
/**
* 2.导出Excel
* @Params: response 响应体
* @Params: fileName 文件名
* @Params: suffix 文件后缀名
* @Params: data 需要导出的数据
* @Params: head 导出的列名
* @Params: title 导出的列字段
*/
public static <T> void export(HttpServletResponse response, String fileName, String suffix, List<T> data, List<List<String>> head, List<String> title) throws IOException {
String sheetName = fileName;
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("\\+", "%20");
response.setHeader("Content-Disposition", "filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
EasyExcel.write(response.getOutputStream()).head(head)
.includeColumnFieldNames(title) //只要导出对象中字段的数据
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.sheet(sheetName).doWrite(data);
}
/**
* 3.自定义策略导出Excel
* @Params: response 响应体
* @Params: fileName 文件名
* @Params: suffix 文件后缀名
* @Params: data 需要导出的数据
* @Params: head 导出的列名
* @Params: title 导出的列字段
* @Params: strategyList 自定义策略集合
*/
public static <T> void export(HttpServletResponse response, String fileName, String suffix, List<T> data, List<List<String>> head, List<String> title, List<WriteHandler> strategyList) throws IOException {
String sheetName = fileName;
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("\\+", "%20");
response.setHeader("Content-Disposition", "filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
ExcelWriterBuilder write = EasyExcel.write(response.getOutputStream());
if (CollUtil.isNotEmpty(title)) {
write.includeColumnFieldNames(title);
}
write.head(head).autoCloseStream(false); // 不要自动关闭,交给 Servlet 自己处理
//设置自定义导出策略
strategyList.forEach(write::registerWriteHandler);
//导出数据
write.sheet(sheetName).doWrite(data);
}
/**
* 4.列表填充并通过响应流返回
* @param response 响应对象
* @param templateStream 模板输入流(如从 resources 读取)
* @param fileName 文件名(不含后缀)
* @param suffix 文件后缀(如 .xlsx)
* @param dataList 要填充的列表数据(需与模板占位符匹配)
* @param <T> 数据类型
* @throws IOException IO异常
*/
public static <T> void populateTemplate(
HttpServletResponse response,
InputStream templateStream,
String fileName,
String suffix,
List<T> dataList
) throws IOException {
// 1. 处理响应头,避免中文乱码
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
// 2. 基于响应流创建
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
.withTemplate(templateStream)
.build()) {
// 3. 指定要填充的 sheet
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 4. 执行列表填充
excelWriter.fill(dataList, writeSheet);
}
}
/**
* 5.单个对象简单填充
* @param response 响应对象(用于输出文件)
* @param templateStream 模板输入流(如 resources 中的模板)
* @param fileName 文件名(不含后缀)
* @param suffix 文件后缀(如 .xlsx)
* @param data 单个填充对象(字段名需与模板占位符一致)
* @param <T> 数据类型
* @throws IOException IO异常
*/
public static <T> void simpleFill(
HttpServletResponse response,
InputStream templateStream,
String fileName,
String suffix,
T data
) throws IOException {
// 1. 处理响应头,避免中文乱码
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
// 2. 构建 ExcelWriter 并填充数据
try (ExcelWriter writer = EasyExcel.write(response.getOutputStream())
.withTemplate(templateStream)
.build()) {
// 3. 指定填充的 sheet(默认第一个 sheet)
WriteSheet sheet = EasyExcel.writerSheet().build();
// 4. 执行填充(单个对象直接传入,官方简单填充核心方法)
writer.fill(data, sheet);
}
}
/**
* 6.复杂填充(支持单值 + 列表混合填充)
* @param response 响应对象,用于浏览器下载
* @param templateStream Excel 模板输入流(如从 resources 或文件系统读取)
* @param fileName 下载文件名(不含后缀)
* @param suffix 文件后缀(如 .xlsx)
* @param data 简单填充的数据
* @param dataList 列表填充的数据
* @param <T> 泛型
* @throws IOException
*/
public static <T> void complexPopulateTemplate(
HttpServletResponse response,
InputStream templateStream,
String fileName,
String suffix,
Map<String, Object> data,
List<T> dataList
) throws IOException {
// 1. 处理响应头,避免中文乱码
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
// 2. 创建 ExcelWriter,关联模板和响应输出流
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
.withTemplate(templateStream)
.build()) {
// 3. 指定要填充的 Sheet(默认第一个 Sheet,可根据模板调整)
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 4. 执行填充:单值
excelWriter.fill(data, writeSheet);
// 4. 执行填充:列表数据
excelWriter.fill(dataList, writeSheet);
}
}
/**
* 7.复杂填充并合并单元格(支持单值 + 列表混合填充 + 自定义合并单元格)
* @param response 响应对象,用于浏览器下载
* @param templateStream Excel 模板输入流(如从 resources 或文件系统读取)
* @param fileName 下载文件名(不含后缀)
* @param suffix 文件后缀(如 .xlsx)
* @param data 简单填充的数据
* @param dataList 列表填充的数据
* @param mergeList 合并策略
* @param <T> 泛型
* @throws IOException
*/
public static <T> void complexPopulateTemplateMergeCells(
HttpServletResponse response,
InputStream templateStream,
String fileName,
String suffix,
Map<String, Object> data,
List<T> dataList,
List<LoopMergeStrategy> mergeList
) throws IOException {
// 处理响应头,避免中文乱码
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
//关联模板
ExcelWriterBuilder excelWriterBuilder = EasyExcel
.write(response.getOutputStream())
.withTemplate(templateStream);
//注册所有合并策略
for (LoopMergeStrategy merge : mergeList) {
excelWriterBuilder.registerWriteHandler(merge);
}
//创建 ExcelWriter,关联模板和响应输出流
try (ExcelWriter excelWriter = excelWriterBuilder.build();) {
// 指定要填充的 Sheet(默认第一个 Sheet,可根据模板调整)
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 执行填充:单值
excelWriter.fill(data, writeSheet);
// 执行填充:列表数据
excelWriter.fill(dataList, writeSheet);
}
}
/**
* 8.多列填充 + 单值填充
* @param response 响应对象(用于输出文件)
* @param templateStream 模板输入流(如 resources 中的模板)
* @param fileName 文件名(不含后缀)
* @param suffix 文件后缀(如 .xlsx)
* @param data 简单填充的数据
* @param categoryLists 多个列表数据
* @param <T>
* @throws IOException
*/
@SafeVarargs
public static <T> void multiCategoryFill(
HttpServletResponse response,
InputStream templateStream,
String fileName,
String suffix,
Map<String, Object> data,
List<T>... categoryLists
) throws IOException {
// 1. 处理响应头,避免中文乱码
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + suffix);
response.setContentType("application/octet-stream");
// 2. 构建ExcelWriter,基于响应流输出
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
.withTemplate(templateStream)
.build()) {
WriteSheet writeSheet = EasyExcel.writerSheet().build(); // 默认第一个sheet
// 3. 循环填充每个分类(带索引的别名:data0、data1、data2...)
for (int i = 0; i < categoryLists.length; i++) { // 用普通for循环,获取索引i
List<T> categoryList = categoryLists[i];
// 空列表兼容:避免NullPointerException
List<T> fillData = Objects.requireNonNullElse(categoryList, List.of());
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
// excel的列
String alias = "data" + i;
// 填充当前分类:别名=带索引的dataX,必须和模板占位符一致
excelWriter.fill(new FillWrapper(alias, fillData),fillConfig, writeSheet);
}
// 4.执行填充:单值
excelWriter.fill(data, writeSheet);
}
}
}
629

被折叠的 条评论
为什么被折叠?



