Springboot 使用POI导出Excel文件

Springboot 使用POI导出Excel文件

本文使用 POI导出 xlsx后缀的Excel文件。

继上一次使用EasyExcel导出Excel文件实现功能后还有遗留问题,这次我试着用POI来重新实现,复刻EasyExcel导出文件的效果。

引入依赖

xml 复制代码
<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

数据查询

java 复制代码
@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文件内容处理

java 复制代码
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;
}

样式封装

java 复制代码
/**
 * 内容居中样式
 * @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;
}

导出效果

  1. 【照片】列中的照片内边距已经设置成功
  2. 成功复刻上一篇使用EasyExcel导出的Excel文件

思考

  1. 为什么不导出.xls后缀的文件?
  2. POI导出与EasyExcel导出相比哪种方式最优呢?
  3. POI导出与EasyExcel导出两种方式有没有需要注意的坑呢?

这些问题我会在下一篇来详细解答。

相关推荐
uzong3 小时前
技术故障复盘模版
后端
GetcharZp4 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程4 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研4 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi4 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
一只爱撸猫的程序猿5 小时前
使用Spring AI配合MCP(Model Context Protocol)构建一个"智能代码审查助手"
spring boot·aigc·ai编程
甄超锋5 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
阿华的代码王国6 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy6 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
AntBlack6 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt