前言
最近的excel导出需求,表头不是固定的,是根据前端的传参,确定要展示的文字和列数。
项目之前用 jxl 的库,先做一个excel模板放在项目文件夹,模板里面有通配字符,代码读取该模板并填充。
这次的需求虽然类似动态表头,但是实现的难度变大了,既有横向的日期分布,又有纵向的信息分类,横向的列数取决于前端参数,用固定模板甚至不可能实现(不可事先预知横向有多少列)。
评估之后很果断地改用EaxyExcel。
改用EaxyExcel,第一不用预定excel模板,第二能灵活设置表头的列数,颜色、宽度。
后来有另一个需求,用EaxyExcel很好的满足,如果用别的库实现起来巨麻烦,等一下再说。
效果图
默认
纯白
设置背景色
实现
导入依赖
先引入EasyExcel和Guava工具类,还有lombok
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
<!-- springboot test启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
单元测试
/**
* 动态表头,并设置宽度,字体,背景
*
* @date 01/22/2021 03:36
*/
public class Demo3ForCSDN {
/**
* @throws IOException
*/
@Test
public void test() throws IOException {
// 文件输出位置
OutputStream out = new FileOutputStream("/Users/quanlinglong/Downloads/mergeDemo/demo" + System.currentTimeMillis() + ".xlsx");
ExcelWriter writer = EasyExcelFactory
.write(out)
// 核心代码:表头和正文的样式在此
.registerWriteHandler(setConfigure())
.build();
// 动态添加表头,适用一些表头动态变化的场景
WriteSheet sheet1 = new WriteSheet();
sheet1.setSheetName("客户信息");
sheet1.setSheetNo(0);
// 创建一个表格,用于 Sheet 中使用
WriteTable table = new WriteTable();
table.setTableNo(1);
// 核心代码:设置表头
table.setHead(head());
// 写数据
writer.write(contentData(), sheet1, table);
writer.finish();
out.close();
}
private static List<List<String>> head() {
List<List<String>> headTitles = Lists.newArrayList();
String empty = " ";
//第一列,1/2/3行
headTitles.add(Lists.newArrayList(empty, "交通"));
//第二列,1/2/3行
headTitles.add(Lists.newArrayList(empty, "人口数"));
// 第三列
headTitles.add(Lists.newArrayList(empty, empty, "频道"));
// 第四列及之后
ArrayList<String> foodList = Lists.newArrayList("气温", "风力", "湿度");
ArrayList<String> mealList = Lists.newArrayList("深圳", "北京", "上海");
ArrayList<String> dateList = Lists.newArrayList("星期一(2021-01-25)", "星期二(2021-01-26)");
// 根据实际需要,决定要渲染多少列
dateList.forEach(date -> {
mealList.forEach(meal -> {
foodList.forEach(food -> {
headTitles.add(Lists.newArrayList(empty, date, meal, food));
});
});
});
return headTitles;
}
private static List<List<Object>> contentData() {
List<List<Object>> contentList = Lists.newArrayList();
//这里一个List<Object>才代表一行数据,需要映射成每行数据填充,横向填充(把实体数据的字段设置成一个List<Object>)
contentList.add(Lists.newArrayList("骑车", "10", "苹果🍎", "25", "2级", "40%"));
contentList.add(Lists.newArrayList("高铁", "20", "橙子🍊", "25", "2级", "40%"));
return contentList;
}
//配置字体,表头背景等
private static HorizontalCellStyleStrategy setConfigure() {
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// 背景色
headWriteCellStyle.setFillForegroundColor(IndexedColors.YELLOW1.getIndex()); // 黄色背景
WriteFont headWriteFont = new WriteFont();
// 加粗
headWriteFont.setBold(true);
// headWriteFont.setFontHeightInPoints((short) 14); // 设置行高,不重要
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// 字体策略
WriteFont contentWriteFont = new WriteFont();
// 字体大小
// contentWriteFont.setFontHeightInPoints((short) 14);
contentWriteCellStyle.setWriteFont(contentWriteFont);
//边框
//导出数据垂直居中
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//导出数据水平居中
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
contentWriteCellStyle.setBorderLeft(BorderStyle.NONE);
contentWriteCellStyle.setBorderTop(BorderStyle.NONE);
contentWriteCellStyle.setBorderRight(BorderStyle.NONE);
contentWriteCellStyle.setBorderBottom(BorderStyle.NONE);
//设置 自动换行
contentWriteCellStyle.setWrapped(true);
//设置
// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}
}
根据传进来的参数,决定展示多少列,展示什么内容。写数据就传入一个List,相当于二维数组。官方文档有个例子,定义一个类,用注解定义表头,那样表头的内容是固定的,展示多少列取决于类里面有多少字段,一开始就固定了,不满足我的需求。
动态生成表头的方式,不需要定义类,不用先做一个excel模板。后来有一个需求,提供错误重下载的功能,即系统识别到用户上传的excel内容填写有误,要高亮单元格,以及重新下载和填写。这个功能,就把读数据时的表头和内容整理下,用上述方式生成一个流,存到云存储,返回一个链接。
总结一下:
- 根据传参决定展示表头的列数和内容,宽度,背景色等
- 写数据时传入一个List即可
希望对你有用