Springboot 使用POI导出Excel文件
- Excel导出系列目录:
- 引入依赖
- 逻辑处理
- controller
- service
- 数据查询
- Excel文件内容处理
- 样式封装
- 导出效果
- 思考
Excel导出系列目录:
【Springboot 使用EasyExcel导出Excel文件】
【Springboot 使用POI导出Excel文件】
【Springboot 导出Excel文件方式对比与注意事项】
本文使用POI
导出xlsx后缀
的Excel文件。
继上一次使用
EasyExcel导出Excel文件
实现功能后还有遗留问题,这次我试着用POI来重新实现,复刻EasyExcel导出文件的效果。
引入依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
逻辑处理
controller
@RestController
@Slf4j
@RequestMapping({"/v1/test"})
public class TestController {
@Resource
private TestService testService;
@PostMapping("/export_record")
public void exportRecord(HttpServletResponse response, @RequestBody GetRecordDto dto) {
testService.exportRecord(response, dto);
log.info("/export_record 导出记录完毕");
}
}
service
数据查询
@Override
public void exportRecord(HttpServletResponse response, GetRecordDto dto) {
OutputStream out = null;
try {
XSSFWorkbook XSSFWorkbook = new XSSFWorkbook();
// 查询数据
List<GetRecordVo> recordInfoList = ...;
// excel内容准备
XSSFWorkbook = dataPrepare(recordVoPageInfo.getRecords());
// 响应信息设置
String fileName = UUID.randomUUID().toString().replace("-", "") + "_抓拍记录.xlsx" ;
response.setContentType("application/OCTET-STREAM;charset=UTF-8");
String file = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename=" + file);
out = response.getOutputStream();
XSSFWorkbook.write(out);
}catch (MixException e){
throw e;
}catch (Exception e){
log.error("导出记录失败:", e);
} finally {
IOUtils.closeQuietly(out);
}
}
Excel文件内容处理
private XSSFWorkbook dataPrepare(List<GetRecordVo> recordVoList) {
XSSFWorkbook wb = new XSSFWorkbook();
// 创建sheet
XSSFSheet sheet1 = wb.createSheet("sheet1");
// 设置表头行高
short headHeight = 400;
// 设置内容行高
short contentHeight = 140;
// 设置内容单元格居中样式
CellStyle contentCenterStyle = getContentCenterStyle(wb);
// 设置内容单元格左靠样式
CellStyle contentLeftStyle = getContentLeftStyle(wb);
// 设置标题单元格样式
CellStyle headStyle = getHeadStyle(wb);
// 创建表头
XSSFRow row = sheet1.createRow(0);
row.setHeight(headHeight);
Cell cell = null;
// 标题内容
String[] headStr = {"序号", "时间", "照片", "姓名", "手机号码", "备注信息"};
for(int i = 0; i < headStr.length; i++){
cell = row.createCell(i);
cell.setCellValue(headStr[i]);
cell.setCellStyle(headStyle);
}
for (int i = 1; i < recordVoList.size() + 1; i++) {
try {
row = sheet1.createRow(i);
row.setHeight((short) (100 * 70));
row.setHeightInPoints(contentHeight);
// 写入数据
sheet1.setColumnWidth(0, 100 * 30);
cell = row.createCell(0);
cell.setCellValue(i);
cell.setCellStyle(contentCenterStyle);
sheet1.setColumnWidth(1, 100 * 70);
cell = row.createCell(1);
cell.setCellValue(recordVoList.get(i - 1).getAlarmTime());
cell.setCellStyle(contentCenterStyle);
sheet1.setColumnWidth(2, 100 * 50);
cell = row.createCell(2);
cell.setCellStyle(contentCenterStyle);
byte[] faceImage = null;
//画图的顶级管理器
XSSFDrawing patriarch = sheet1.createDrawingPatriarch();
//anchor主要用于设置图片的属性
XSSFClientAnchor anchor = new XSSFClientAnchor(100000, 100000, -100000, -100000, (short) 3, i, (short) 3 + 1, i + 1);
anchor.setAnchorType(ClientAnchor.AnchorType.byId(3));
try {
// 将图片转换成byte[]类型数据
faceImage = ...;
//插入图片
if(ObjectUtils.isNotEmpty(faceImage)) {
patriarch.createPicture(anchor, wb.addPicture(faceImage, Workbook.PICTURE_TYPE_JPEG));
}
} catch (Exception e) {
log.error("=== log: getbyteArray timeout url: {} error:", recordVoList.get(i - 1).getFaceImageUrl(), e);
}
sheet1.setColumnWidth(3, 100 * 70);
cell = row.createCell(3);
cell.setCellValue(recordVoList.get(i - 1).getStaffName());
cell.setCellStyle(contentLeftStyle);
sheet1.setColumnWidth(4, 100 * 70);
cell = row.createCell(4);
cell.setCellValue(recordVoList.get(i - 1).getStaffPhone());
cell.setCellStyle(contentCenterStyle);
sheet1.setColumnWidth(5, 100 * 70);
cell = row.createCell(5);
cell.setCellValue(recordVoList.get(i - 1).getStaffRemark());
cell.setCellStyle(contentLeftStyle);
} catch (Exception e) {
e.printStackTrace();
}
}
// 写入excel文件
log.info("-------------------导出文件已经准备完毕---------------");
return wb;
}
样式封装
/**
* 内容居中样式
* @param wb
* @return
*/
private CellStyle getContentCenterStyle(XSSFWorkbook wb){
CellStyle contentCenterStyle = wb.createCellStyle();
contentCenterStyle.setBorderBottom(BorderStyle.THIN);
contentCenterStyle.setBorderLeft(BorderStyle.THIN);
contentCenterStyle.setBorderRight(BorderStyle.THIN);
contentCenterStyle.setBorderTop(BorderStyle.THIN);
contentCenterStyle.setAlignment(HorizontalAlignment.CENTER);
contentCenterStyle.setVerticalAlignment(VerticalAlignment.CENTER);
contentCenterStyle.setFont(getFontStyle(wb));
return contentCenterStyle;
}
/**
* 内容左靠样式
* @param wb
* @return
*/
private CellStyle getContentLeftStyle(XSSFWorkbook wb){
CellStyle contentCenterStyle = wb.createCellStyle();
contentCenterStyle.setBorderBottom(BorderStyle.THIN);
contentCenterStyle.setBorderLeft(BorderStyle.THIN);
contentCenterStyle.setBorderRight(BorderStyle.THIN);
contentCenterStyle.setBorderTop(BorderStyle.THIN);
contentCenterStyle.setVerticalAlignment(VerticalAlignment.CENTER);
contentCenterStyle.setFont(getFontStyle(wb));
return contentCenterStyle;
}
/**
* 标题居中样式
* @param wb
* @return
*/
private CellStyle getHeadStyle(XSSFWorkbook wb){
CellStyle headStyle = wb.createCellStyle();
headStyle.setBorderBottom(BorderStyle.THIN);
headStyle.setBorderLeft(BorderStyle.THIN);
headStyle.setBorderRight(BorderStyle.THIN);
headStyle.setBorderTop(BorderStyle.THIN);
headStyle.setAlignment(HorizontalAlignment.CENTER);
headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headStyle.setFont(getBoldFontStyle(wb));
headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
return headStyle;
}
/**
* 普通文字样式
* @param wb
* @return
*/
private Font getFontStyle(XSSFWorkbook wb){
Font contentFont = wb.createFont();
contentFont.setFontName("仿宋");
contentFont.setFontHeightInPoints((short) 12);
return contentFont;
}
/**
* 加粗文字样式
* @param wb
* @return
*/
private Font getBoldFontStyle(XSSFWorkbook wb){
Font contentFont = wb.createFont();
contentFont.setFontName("仿宋");
contentFont.setFontHeightInPoints((short) 12);
contentFont.setBold(true);
return contentFont;
}
导出效果
- 【照片】列中的照片内边距已经设置成功
- 成功复刻上一篇使用EasyExcel导出的Excel文件
思考
- 为什么不导出
.xls后缀
的文件? - POI导出与EasyExcel导出相比哪种方式最优呢?
- POI导出与EasyExcel导出两种方式有没有需要注意的坑呢?
这些问题我会在下一篇来详细解答。