网站维护的重要性,WordPress桌面,合肥网页设计哪家服务好,山东建设银行招聘网站Excel处理基础知识
1.1 为什么需要在应用中处理Excel文件#xff1f;
在企业应用开发中#xff0c;Excel文件处理是一个非常常见的需求#xff0c;主要用于以下场景#xff1a;
数据导入#xff1a;允许用户通过Excel上传批量数据到系统 数据导出#xff1a;将系统数据…Excel处理基础知识
1.1 为什么需要在应用中处理Excel文件
在企业应用开发中Excel文件处理是一个非常常见的需求主要用于以下场景
数据导入允许用户通过Excel上传批量数据到系统 数据导出将系统数据导出为Excel供用户下载分析 报表生成生成复杂的报表并格式化为Excel 数据交换作为不同系统间交换数据的媒介 批量数据处理处理大量结构化数据
1.2 Java中的Excel处理库介绍
Java中处理Excel文件的主要库有以下几种
1.2.1 Apache POI
Apache POI是Java中使用最广泛的Excel处理库提供了全面的API来创建、读取和修改Office文档。
优点
功能全面支持Excel所有功能 支持.xls (HSSF - Excel 97-2003)和.xlsx (XSSF - Excel 2007)格式 社区活跃文档丰富 支持公式计算、图表、合并单元格等高级功能 缺点
API相对复杂 处理大文件时内存消耗大尤其是XSSF
1.2.2 EasyExcel
EasyExcel是阿里巴巴开源的Excel处理库基于POI但做了大量优化。
优点
内存占用低使用SAX模式读取避免OOM API简单易用注解驱动 读写速度快 适合处理大型Excel文件 缺点
功能不如POI全面 灵活性相对较低
1.2.3 JExcel
JExcel是另一个处理Excel的Java库。
优点
API较简单 速度较快 缺点
仅支持旧版Excel (.xls)格式 不再积极维护 功能有限
1.2.4 Apache POI SXSSF
SXSSF是POI提供的一种流式处理模式专为处理大型Excel文件设计。
优点
大大降低内存占用 适合生成大型Excel文件 缺点
仅支持写入操作不支持读取 功能比XSSF受限
1.3 Spring Boot中集成Excel处理
Spring Boot本身不提供Excel处理功能但可以轻松集成上述各种Excel处理库。本指南将主要介绍
如何在Spring Boot项目中集成Apache POI和EasyExcel 如何实现Excel导入导出的常见功能 如何处理常见问题和优化性能
Spring Boot中Excel处理完全指南从基础到高级实践 在数据驱动的现代应用中Excel处理能力是后端开发的必备技能。本文全面解析Spring Boot中Excel操作的12种核心技术方案。 一、基础方案Apache POI原生集成
1. 添加依赖
dependencygroupIdorg.apache.poi/groupIdartifactIdpoi/artifactIdversion5.2.3/version
/dependency
dependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml/artifactIdversion5.2.3/version
/dependency2. 基础读写操作
// 写入Excel
public void writeExcel(ListUser users, String filePath) throws IOException {try (Workbook workbook new XSSFWorkbook()) {Sheet sheet workbook.createSheet(用户表);// 创建表头Row headerRow sheet.createRow(0);headerRow.createCell(0).setCellValue(ID);headerRow.createCell(1).setCellValue(姓名);headerRow.createCell(2).setCellValue(年龄);// 填充数据int rowNum 1;for (User user : users) {Row row sheet.createRow(rowNum);row.createCell(0).setCellValue(user.getId());row.createCell(1).setCellValue(user.getName());row.createCell(2).setCellValue(user.getAge());}// 自动调整列宽for (int i 0; i 3; i) {sheet.autoSizeColumn(i);}try (FileOutputStream fos new FileOutputStream(filePath)) {workbook.write(fos);}}
}// 读取Excel
public ListUser readExcel(String filePath) throws IOException {ListUser users new ArrayList();try (Workbook workbook new XSSFWorkbook(new File(filePath))) {Sheet sheet workbook.getSheetAt(0);IteratorRow rowIterator sheet.iterator();// 跳过表头if (rowIterator.hasNext()) rowIterator.next();while (rowIterator.hasNext()) {Row row rowIterator.next();User user new User();user.setId((long) row.getCell(0).getNumericCellValue());user.setName(row.getCell(1).getStringCellValue());user.setAge((int) row.getCell(2).getNumericCellValue());users.add(user);}}return users;
}二、高效方案EasyExcel处理百万级数据
1. 添加依赖
dependencygroupIdcom.alibaba/groupIdartifactIdeasyexcel/artifactIdversion3.3.2/version
/dependency2. 基于注解的实体映射
Data
public class UserExcel {ExcelProperty(ID)private Long id;ExcelProperty(姓名)private String name;ExcelProperty(年龄)private Integer age;ExcelProperty(value 创建时间, converter LocalDateTimeConverter.class)private LocalDateTime createTime;
}// 自定义日期转换器
public class LocalDateTimeConverter implements ConverterLocalDateTime {Overridepublic LocalDateTime convertToJavaData(ReadCellData? cellData) {return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss));}
}3. 百万数据导出避免OOM
GetMapping(/exportBigData)
public void exportBigData(HttpServletResponse response) {response.setContentType(application/vnd.ms-excel);response.setCharacterEncoding(utf-8);String fileName URLEncoder.encode(百万用户数据, UTF-8);response.setHeader(Content-disposition, attachment;filename fileName .xlsx);EasyExcel.write(response.getOutputStream(), UserExcel.class).sheet(用户数据).doWrite(() - {// 分页查询数据每次查询10000条int page 0;while (true) {Pageable pageable PageRequest.of(page, 10000);PageUser userPage userRepository.findAll(pageable);if (userPage.isEmpty()) break;// 转换数据ListUserExcel data userPage.getContent().stream().map(user - {UserExcel excel new UserExcel();BeanUtils.copyProperties(user, excel);return excel;}).collect(Collectors.toList());page;return data;}return null;});
}三、Web集成方案文件上传下载
1. 文件上传解析
PostMapping(/upload)
public String upload(RequestParam(file) MultipartFile file) {if (file.isEmpty()) {return 请选择文件;}try {ListUser users EasyExcel.read(file.getInputStream()).head(User.class).sheet().doReadSync();userRepository.saveAll(users);return 导入成功共处理数据: users.size() 条;} catch (IOException e) {return 文件处理失败: e.getMessage();}
}2. 模板下载
GetMapping(/downloadTemplate)
public void downloadTemplate(HttpServletResponse response) throws IOException {response.setContentType(application/vnd.ms-excel);response.setCharacterEncoding(utf-8);String fileName URLEncoder.encode(用户导入模板, UTF-8);response.setHeader(Content-disposition, attachment;filename fileName .xlsx);// 创建模板数据带下拉菜单ListString headers Arrays.asList(ID, 姓名, 年龄, 部门);ListExcelSelect selects Collections.singletonList(new ExcelSelect(3, Arrays.asList(研发部, 市场部, 财务部)));EasyExcel.write(response.getOutputStream()).head(headers).registerWriteHandler(new DropDownHandler(selects)) // 添加下拉菜单.sheet(模板).doWrite(Collections.emptyList());
}// 下拉菜单处理器
public class DropDownHandler implements SheetWriteHandler {private final ListExcelSelect selects;public DropDownHandler(ListExcelSelect selects) {this.selects selects;}Overridepublic void afterSheetCreate(WriteWorkbookContext context) {Sheet sheet context.getWriteSheetHolder().getSheet();DataValidationHelper helper sheet.getDataValidationHelper();for (ExcelSelect select : selects) {// 创建下拉数据源String range D2:D1048576; // 示例D列所有行CellRangeAddressList addressList new CellRangeAddressList(1, 65535, select.getColIndex(), select.getColIndex());// 设置下拉选项DataValidationConstraint constraint helper.createExplicitListConstraint(select.getOptions().toArray(new String[0]));DataValidation validation helper.createValidation(constraint, addressList);// 应用验证sheet.addValidationData(validation);}}
}四、高级技巧动态模板与复杂报表
1. 动态表头生成
public void exportDynamicColumns(HttpServletResponse response, ListString columns) {// 动态构建表头ListListString head new ArrayList();for (String col : columns) {head.add(Collections.singletonList(col));}// 动态数据填充ListListObject data new ArrayList();for (User user : userRepository.findAll()) {ListObject row new ArrayList();for (String col : columns) {switch (col) {case ID: row.add(user.getId()); break;case 姓名: row.add(user.getName()); break;case 部门: row.add(user.getDepartment()); break;// 更多字段处理...}}data.add(row);}// 导出EasyExcel.write(response.getOutputStream()).head(head).sheet(动态报表).doWrite(data);
}2. 复杂报表合并单元格
public void exportComplexReport() {String fileName 复杂报表.xlsx;try (ExcelWriter excelWriter EasyExcel.write(fileName).build()) {WriteSheet writeSheet EasyExcel.writerSheet(部门统计).build();// 设置合并策略excelWriter.registerWriteHandler(new CellMergeStrategy(Arrays.asList(new MergeRange(0, 0, 0, 3), // 第一行合并4列new MergeRange(1, 1, 0, 0), // 第二行第一列new MergeRange(1, 1, 1, 3) // 第二行后三列合并)));// 构建表头ListListString head Arrays.asList(Collections.singletonList(公司年度报表),Arrays.asList(部门, Q1, Q2, Q3, Q4));// 填充数据ListListObject data new ArrayList();data.add(Arrays.asList(研发部, 150, 180, 200, 220));data.add(Arrays.asList(市场部, 120, 150, 180, 210));excelWriter.write(head, writeSheet);excelWriter.write(data, writeSheet);}
}// 自定义合并策略
public class CellMergeStrategy implements RowWriteHandler {private final ListMergeRange mergeRanges;Overridepublic void afterRowDispose(WriteSheetContext context) {Sheet sheet context.getWriteSheetHolder().getSheet();for (MergeRange range : mergeRanges) {sheet.addMergedRegion(new CellRangeAddress(range.getFirstRow(), range.getLastRow(),range.getFirstCol(), range.getLastCol()));}}
}五、性能优化与问题解决方案
1. 内存溢出解决方案
// 使用SXSSFWorkbook处理大数据
try (Workbook workbook new SXSSFWorkbook(100)) { // 保持100行在内存中Sheet sheet workbook.createSheet();// 写入数据for (int i 0; i 1000000; i) {Row row sheet.createRow(i);// 填充单元格...// 定期刷新磁盘if (i % 1000 0) {((SXSSFSheet) sheet).flushRows(100);}}
}2. 常见问题处理方案
问题类型解决方案日期格式不一致自定义Converter统一处理日期格式大文件导出超时分页查询异步导出前端轮询结果特殊字符(emoji)乱码使用String sanitized StringEscapeUtils.escapeHtml4(rawString)处理公式计算使用FormulaEvaluator预处理公式结果样式丢失定义CellStyle缓存池避免重复创建下拉菜单动态数据源使用DVConstraint.createFormulaListConstraint引用隐藏Sheet数据
3. Excel操作最佳实践 读写分离原则 读操作使用EasyExcel的监听器模式ReadListener写操作大数据用分页写入小数据用全量写入 资源管理三要素 try (Workbook workbook ...;InputStream is ...) {// 操作逻辑
} // 自动关闭资源样式复用技巧 private CellStyle createHeaderStyle(Workbook workbook) {CellStyle style workbook.createCellStyle();Font font workbook.createFont();font.setBold(true);style.setFont(font);style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);return style;
}六、扩展方案集成第三方库
1. JExcelAPI适合.xls格式
dependencygroupIdnet.sourceforge.jexcelapi/groupIdartifactIdjxl/artifactIdversion2.6.12/version
/dependency2. Apache POI JXLS模板引擎
dependencygroupIdorg.jxls/groupIdartifactIdjxls-poi/artifactIdversion2.12.0/version
/dependency
dependencygroupIdorg.jxls/groupIdartifactIdjxls-jexcel/artifactIdversion1.0.9/version
/dependency模板示例template.xlsx
| 姓名 | 年龄 | 部门 |
|------|------|----------|
| ${u.name} | ${u.age} | ${u.department} |Java代码
public void exportWithTemplate(HttpServletResponse response) throws IOException {try (InputStream is getClass().getResourceAsStream(/template.xlsx);OutputStream os response.getOutputStream()) {Context context new Context();context.putVar(users, userRepository.findAll());JxlsHelper.getInstance().processTemplate(is, os, context);}
}最佳实践总结对于中小数据量10万行推荐使用EasyExcel注解方案大数据场景采用POI的SXSSF模式需要复杂报表时选择JXLS模板引擎。始终记住在Spring Boot中处理Excel资源关闭和内存管理是成败关键 扩展学习
POI官方文档EasyExcel GitHubJXLS模板语法