1.首先理解一下无对象生成表头,就需要添加head属性,自己在Java代码中手动书写表头信息,然后添加到head中,如果是动态的,则用代码循环
2.因为自己代码逻辑多一些,就多用文字表述来说一下,里面有我的业务逻辑,不建议直接粘贴,其实很简单,理解为主
3.首先看一下官方文档https://www.yuque.com/easyexcel/doc/write#avjBv
主要参考的是:不创建对象写
/**
* 设置表头
*
* @param exportList
* @return
*/
public List> head(List exportList) {
String time = exportList.get(0).getMonth();
String year = time.substring(0, 4);
String month = time.substring(5, 7);
//初始化第一行表头
String bigTitle = "表头名字" + year + "年度" + month + "月工时分摊表";
//创建表头集合
List> head = new ArrayList<>();
//这里的每一个list都是代表一列,按照顺序来,相同的名称会自动合并单元格,比如说两个序号,
//就是把第第一列的第二第三格合并到了一起
//然后行单元格合并是同理的,可以看到bigTitle每一个list都有,都是在第一个,说明每一列的
//第一个单元格都是这个值,所以最终的效果就是你生成的表格第一行全部合并,然后可以展示大表
//头,
//第一列
List title = new ArrayList<>(Arrays.asList(bigTitle, "序号", "序号", "序号"));
head.add(title);
//第二列
List title1 = new ArrayList<>(Arrays.asList(bigTitle, "技术人员", "技术人员", "技术人员"));
head.add(title1);
//第三列
List title2 = new ArrayList<>(Arrays.asList(bigTitle, "月总工时", "月总工时", "月总工时"));
head.add(title2);
//动态生成列,也就是说这一部分的表头是动态生成的,
for (ExportHour exportHour : exportList) {
List title3 = new ArrayList<>(Arrays.asList(bigTitle, "月工时", exportHour.getProjectName(), exportHour.getProjectName()));
head.add(title3);
}
//列
List title7 = new ArrayList<>(Arrays.asList(bigTitle, "月工时", "合计工时", "合计工时"));
head.add(title7);
//列
List title5 = new ArrayList<>(Arrays.asList(bigTitle, "", "核验", "核验"));
head.add(title5);
//最后直接把这些生成的表头集合返回就行了
return head;
}
看一下我写的,其实很简单,只是有我的业务逻辑在而已,这个是参考
/**
* 写数据
*
* @param exportList
* @param
* @return
*/
private List data(List exportList) {
int i = 1;
List> list = ListUtils.newArrayList();
Integer size = getDates(exportList.get(0).getMonth()).size();
Integer sumHour = size * 8;
// 获取指定月份下的所有项目所涉及的人员
List strings = projectHourService.queryUserList();
List list1 = strings.stream().distinct().collect(Collectors.toList());
for (String userId : list1) {
List head = ListUtils.newArrayList();
// 序号
head.add(i + "");
i++;
head.add(userService.selectUserById(Long.valueOf(userId)).getNickName());
// 月总工时
head.add(sumHour + "");
BigDecimal sumhour = BigDecimal.ZERO;
for (ExportHour exportHour : exportList) {
List userInfo = exportHour.getExportList();
List info = userInfo.stream().filter(a -> a.getUserId().toString().equals(userId))
.collect(Collectors.toList());
if (info.size() > 0) {
sumhour = sumhour.add(info.get(0).getSumUserHors());
// 个人项目工时
head.add(info.get(0).getSumUserHors().toString());
} else {
head.add("");
}
}
// 合计工时
head.add(sumhour.toString());
BigDecimal result = sumhour.subtract(new BigDecimal(size * 8));
head.add(result + "");
list.add(head);
}
return list;
}
其实跟创建表头的思路是一样的,用同样的方法,一次次创建表头,只不过是每一列只填一个数据,把你需要填充的数据添加到一个个的head里就行了,只不过这次是填充的数据而已,这么说懂吧
现在表头和数据都准备好了,那就是写入数据
/**
* 项目详情导出
*
* @return
*/
@PostMapping("/export")
@PreAuthorize("@ss.hasPermi('system:project:stat:query')")
@ApiOperation("导出")
public void export(HttpServletResponse response, @RequestBody BaseProjectDto baseProjectDto) throws IOException {
String fileName = URLEncoder.encode("projectWorkingHour", "UTF-8").concat(".xlsx");
//response输出文件流
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
List list = projectHourService.queryProjectHors(baseProjectDto);
//导出对象,输出数据流,CustomCellWriteHandler()是我写的简单的一个拦截器,下面会贴
//可以看一下,不需要拦截器的话,把registerWriteHandler去掉就行了
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
.registerWriteHandler(new CustomCellWriteHandler())
.build();
int i = 0;
for (ResultExport export : list) {
if (export.getDateResults().size() > 0) {
// 创建sheet页,设置sheet页名称,同时写入表头信息
WriteSheet writeSheet = EasyExcel.writerSheet(i, export.getDateTime())
.head(head(list.get(i).getDateResults()))
.build();
// 写入数据,并将sheet页对象传入
excelWriter.write(data(list.get(i).getDateResults()), writeSheet);
}
i++;
}
//这一步很关键,不然文件会损坏
excelWriter.finish();
}
response就不用说了把,这些请求头参数不用动,直接拿过来就行了,不想用,百度也行
注意:文件名必须是英文,不要是中文,否则会报错,文件名字是啥无所谓,下载的时候前端给指定就行了,sheet页可以是中文。
JDK不要是简易版的,不然没有数据流出来,简易版的jdk后面带-slim这个后缀
到这里的话,就可以进行导出了,应该是没啥问题了,可以试一下
我这里只是简单的定制格式,更复杂的,请问度娘或者谷歌
/**
* @author: zbh19
* @date: 2022/5/5 1:57
* @description: 表头样式拦截器
*/
@Slf4j
@Component
public class CustomCellWriteHandler implements CellWriteHandler {
@Override
public void afterCellDataConverted(CellWriteHandlerContext context) {
}
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
WriteCellData> cellData = context.getFirstCellData();
int rowNum = context.getRow().getRowNum();
Integer columnIndex = context.getColumnIndex();
Sheet sheet = context.getWriteSheetHolder().getSheet();
Cell cell = context.getCell();
if (BooleanUtils.isTrue(context.getHead())) {
WriteCellStyle writeCellStyle = cellData.getWriteCellStyle();
//字体
WriteFont writeFont = writeCellStyle.getWriteFont();
//背景颜色
writeCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
//字体大小
writeFont.setFontHeightInPoints((short) 16);
//字体加粗
writeFont.setBold(true);
writeCellStyle.setWriteFont(writeFont);
//列宽,行高
sheet.setColumnWidth(cell.getColumnIndex(), 4000);
sheet.setDefaultRowHeight((short) 400);
}
}
}
最后来个我的效果图:
好了,完事了,就这吧!~~~