做个记录,试了很多方法都不行(本来想使用对象单独写一个table,但是没找到属性),又不想更换依赖,后面才看到的模板填充,能用............
//依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easypoi.version}</version>
</dependency>
控制层
//Controller层
@ApiOperation(value = "导出", notes = "导出")
@GetMapping("/export/{projectId}")
public void exportByProjectId(@PathVariable String projectId,HttpServletResponse response) {
projectOrderService.exportByProjectId(projectId,response);
}
添加一个模板
代码( projectOrderExcelVO 是一个对象,他里面带了一个list )
service层
//service层
public void exportByProjectId(String projectId, HttpServletResponse response) {
//查询出来的对象
ProjectOrderExcelVO projectOrderExcelVO = getProjectOrderExcelVO(projectId);
//使用模板
//获取模板
ClassPathResource classPathResource = new ClassPathResource("/templates/专案执行单.xlsx");
//输入流
InputStream inputStream = null;
//输出流
ServletOutputStream outputStream = null;
//Excel对象
ExcelWriter excelWriter = null;
try {
//输入流
inputStream = classPathResource.getInputStream();
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("专案执行单", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
outputStream = response.getOutputStream();
//设置输出流和模板信息
excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
//开启自动换行,自动换行表示每次写入一条list数据是都会重新生成一行空行,此选项默认是关闭的,需要提前设置为true
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
//列表
excelWriter.fill(projectOrderExcelVO.getProjectOrderContentExcelList(), fillConfig, writeSheet);
//对象
excelWriter.fill(projectOrderExcelVO, writeSheet);
excelWriter.finish();
} catch (Exception e) {
e.printStackTrace();
}finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
//关闭流
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
在模板上添加 单个对象 {属性名} 或 多条数据 {.属性名} (可以使用map)
中途遇到的bug
excelgenerateexception create workbook failure //没有图片了,就这一句话或是往下滑
Unexpected record signature: 0X9 //这一句
可以先看下target的classes文件下有没有把模板编译进去,没有的话就重新编译(pom.xml文件下得有这个配置)
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.xlsx</exclude>
<exclude>**/*.xls</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.xlsx</include>
<include>**/*.xls</include>
</includes>
</resource>
</resources>
</build>
成功的效果图
写的初版
//service层
public void exportByProjectId(String projectId, HttpServletResponse response) {
//查询出来的对象
ProjectOrderExcelVO projectOrderExcelVO = getProjectOrderExcelVO(projectId);
List<ProjectOrderExcelVO> projectOrderExcelList = new ArrayList<>();
projectOrderExcelList.add(projectOrderExcelVO);
//初版
try {
// 方法1 如果写到同一个sheet
String fileName = "tableWrite" + System.currentTimeMillis() + ".xlsx";
// 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例
ExcelWriter excelWriter = null;
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// 背景色
headWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
//内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
//设置 自动换行
//contentWriteCellStyle.setWrapped(true);
//设置 垂直居中
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//设置 水平居中
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
//设置边框样式
contentWriteCellStyle.setBorderLeft(THIN);
contentWriteCellStyle.setBorderTop(THIN);
contentWriteCellStyle.setBorderRight(THIN);
contentWriteCellStyle.setBorderBottom(THIN);
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
try {
// 这里不指定class
excelWriter = EasyExcel.write(fileName).build();
// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
WriteSheet writeSheet = EasyExcel.writerSheet("专案执行单").needHead(Boolean.FALSE)
.registerWriteHandler(horizontalCellStyleStrategy)
.build();
// 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
WriteTable writeTable0 = EasyExcel.writerTable(0).head(ProjectOrderExcelVO.class).needHead(Boolean.TRUE).build();
// 第二个对象 读取对象的excel实体类中的标题
WriteTable writeTable1 = EasyExcel.writerTable(1).head(ProjectOrderContentExcelVO.class).needHead(Boolean.TRUE).relativeHeadRowIndex(1).build();
// 第一次写入会创建头
excelWriter.write(projectOrderExcelList, writeSheet, writeTable0);
// 第二次写如也会创建头,然后在第一次的后面写入数据
excelWriter.write(projectOrderExcelVO.getProjectOrderContentExcelList(), writeSheet, writeTable1);
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
半成品 实现两个列表(table)
//service层
public void exportByProjectId(String projectId, HttpServletResponse response) {
//查询出来的对象
ProjectOrderExcelVO projectOrderExcelVO = getProjectOrderExcelVO(projectId);
List<ProjectOrderExcelVO> projectOrderExcelList = new ArrayList<>();
projectOrderExcelList.add(projectOrderExcelVO);
//半成品 没有实现单个列折叠
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// 背景色
headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
//内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
//设置 自动换行
contentWriteCellStyle.setWrapped(true);
//设置 垂直居中
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//设置 水平居中
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
//设置边框样式
contentWriteCellStyle.setBorderLeft(THIN);
contentWriteCellStyle.setBorderTop(THIN);
contentWriteCellStyle.setBorderRight(THIN);
contentWriteCellStyle.setBorderBottom(THIN);
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
ServletOutputStream outputStream = null;
// 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例
ExcelWriter excelWriter = null;
try {
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("专案执行单", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
outputStream = response.getOutputStream();
// 这里不指定class
excelWriter = EasyExcel.write(outputStream).build();
// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
WriteSheet writeSheet = EasyExcel.writerSheet("专案执行单").needHead(Boolean.FALSE)
.registerWriteHandler(horizontalCellStyleStrategy)
.build();
// 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
WriteTable writeTable0 = EasyExcel.writerTable(0).head(ProjectOrderExcelVO.class).needHead(Boolean.TRUE).build();
// 第二个对象 读取对象的excel实体类中的标题
WriteTable writeTable1 = EasyExcel.writerTable(1).head(ProjectOrderContentExcelVO.class).needHead(Boolean.TRUE).relativeHeadRowIndex(1).build();
// 第一次写入会创建头
excelWriter.write(projectOrderExcelList, writeSheet, writeTable0);
// 第二次写如也会创建头,然后在第一次的后面写入数据
excelWriter.write(projectOrderExcelVO.getProjectOrderContentExcelList(), writeSheet, writeTable1);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
//关闭流
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//成品