JAVA Apache POI实战:从基础Excel导出入门到高级功能拓展

一、Apache POI简介

Apache POI是Apache软件基金会的开源项目,全称"Poor Obfuscation Implementation"(简陋模糊化实现),主要用于Java程序对Microsoft Office格式文件(如Excel、Word、PowerPoint等)进行读写操作。

核心组件:

  • HSSF:操作Excel 97-2003格式(.xls)
  • XSSF:操作Excel 2007+格式(.xlsx)
  • SXSSF:XSSF的流式API,适合大数据量
  • HWPF:操作Word文档
  • HSLF:操作PowerPoint

二、基础Excel导出实战

2.1 最小化示例(导出.xls)

java 复制代码
// 创建Excel工作簿(HSSF对应.xls格式)
Workbook workbook = new HSSFWorkbook();
// 创建工作表
Sheet sheet = workbook.createSheet("员工表");

// 创建表头行(第0行)
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("姓名");
headerRow.createCell(1).setCellValue("年龄");
headerRow.createCell(2).setCellValue("部门");

// 添加数据行(第1行)
Row dataRow = sheet.createRow(1);
dataRow.createCell(0).setCellValue("张三");
dataRow.createCell(1).setCellValue(28);
dataRow.createCell(2).setCellValue("研发部");

// 写入到文件
try (FileOutputStream fos = new FileOutputStream("员工表.xls")) {
    workbook.write(fos);
}

2.2 新版Excel导出(.xlsx)

java 复制代码
// 使用XSSFWorkbook创建.xlsx文件
Workbook workbook = new XSSFWorkbook();
// 其余操作与HSSF完全相同

2.3 添加简单样式

java 复制代码
// 创建单元格样式
CellStyle headerStyle = workbook.createCellStyle();
Font headerFont = workbook.createFont();
headerFont.setBold(true);                 // 加粗
headerFont.setFontHeightInPoints((short)12); // 字号
headerStyle.setFont(headerFont);
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 背景色
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

// 应用样式到表头
for (int i = 0; i < headerRow.getLastCellNum(); i++) {
    headerRow.getCell(i).setCellStyle(headerStyle);
}

三、中级功能进阶

3.1 大数据量导出(SXSSF)

java 复制代码
// 创建SXSSF工作簿(保留100行在内存中)
Workbook workbook = new SXSSFWorkbook(100); 

try {
    Sheet sheet = workbook.createSheet("大数据表");
    
    // 写入10万行数据
    for (int i = 0; i < 100000; i++) {
        Row row = sheet.createRow(i);
        row.createCell(0).setCellValue("数据" + i);
        row.createCell(1).setCellValue(Math.random() * 100);
        
        // 每1000行手动flush一次
        if (i % 1000 == 0) {
            ((SXSSFSheet)sheet).flushRows(100); // 保留最近100行
        }
    }
    
    // 写入文件
    workbook.write(new FileOutputStream("大数据.xlsx"));
} finally {
    // 必须显式清理临时文件
    if (workbook instanceof SXSSFWorkbook) {
        ((SXSSFWorkbook)workbook).dispose();
    }
}

3.2 合并单元格

java 复制代码
// 合并A1到D1单元格
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3));

// 创建合并单元格
Row mergedRow = sheet.createRow(0);
Cell mergedCell = mergedRow.createCell(0);
mergedCell.setCellValue("季度销售报表");

// 设置合并单元格样式
CellStyle mergedStyle = workbook.createCellStyle();
mergedStyle.setAlignment(HorizontalAlignment.CENTER);
mergedCell.setCellStyle(mergedStyle);

3.3 添加公式

java 复制代码
// 添加SUM公式
Row formulaRow = sheet.createRow(sheet.getLastRowNum() + 1);
formulaRow.createCell(0).setCellValue("合计");
formulaRow.createCell(1).setCellFormula("SUM(B2:B" + (sheet.getLastRowNum()) + ")");

// 强制计算公式(可选)
workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();

四、高级功能拓展

4.1 条件格式

java 复制代码
// 创建条件格式规则
SheetConditionalFormatting scf = sheet.getSheetConditionalFormatting();

// 定义格式:数值大于90显示绿色背景
ConditionalFormattingRule rule = scf.createConditionalFormattingRule(
    "B2>90");
PatternFormatting fill = rule.createPatternFormatting();
fill.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.getIndex());
fill.setFillPattern(PatternFormatting.SOLID_FOREGROUND);

// 应用范围:B2到B100
CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:B100") };
scf.addConditionalFormatting(regions, rule);

4.2 数据验证(下拉列表)

java 复制代码
// 创建数据验证约束
DataValidationHelper dvHelper = sheet.getDataValidationHelper();
DataValidationConstraint dvConstraint = dvHelper.createExplicitListConstraint(
    new String[]{"研发部","市场部","财务部","人事部"});

// 设置验证范围(C列)
CellRangeAddressList addressList = new CellRangeAddressList(
    1, 100, 2, 2); // 从第2行到101行,第3列

// 创建数据验证
DataValidation validation = dvHelper.createValidation(dvConstraint, addressList);
validation.setShowErrorBox(true);
sheet.addValidationData(validation);

4.3 图表生成

java 复制代码
// 创建绘图对象
Drawing<?> drawing = sheet.createDrawingPatriarch();

// 定义图表位置
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 5, 1, 10, 15);

// 创建柱状图
Chart chart = drawing.createChart(anchor);
ChartLegend legend = chart.getOrCreateLegend();
legend.setPosition(LegendPosition.BOTTOM);

// 定义数据源
BarChartData data = chart.getChartDataFactory().createBarChartData(
    ChartAxisFactory.createValueAxis(chart), 
    ChartAxisFactory.createCategoryAxis(chart)
);

// 设置系列数据
ChartDataSource<String> cats = DataSources.fromStringCellRange(
    sheet, new CellRangeAddress(1, 4, 0, 0));
ChartDataSource<Number> values = DataSources.fromNumericCellRange(
    sheet, new CellRangeAddress(1, 4, 1, 1));
data.addSeries(cats, values, "部门业绩");

// 应用数据到图表
chart.plot(data);

五、实际应用技巧

5.1 性能优化建议

  1. 对象复用:重复使用CellStyle对象

    java 复制代码
    // 错误的做法:每次循环都创建新样式
    // 正确的做法:预先创建样式对象并复用
    CellStyle dataStyle = workbook.createCellStyle();
    for (Row row : sheet) {
        for (Cell cell : row) {
            cell.setCellStyle(dataStyle);
        }
    }
  2. 批量写入:使用SXSSF处理大数据

    java 复制代码
    // 设置窗口大小(内存中保留的行数)
    SXSSFWorkbook workbook = new SXSSFWorkbook(100); 
  3. 及时清理:处理完成后释放资源

    java 复制代码
    try {
        // 操作workbook...
    } finally {
        if (workbook instanceof SXSSFWorkbook) {
            ((SXSSFWorkbook)workbook).dispose();
        }
    }

5.2 常见问题解决方案

问题1:导出文件损坏

  • 确保正确关闭流
  • 使用try-with-resources语句块

问题2:内存溢出

  • 对于大数据量使用SXSSF
  • 设置合理的flush间隔

问题3:日期格式问题

java 复制代码
CellStyle dateStyle = workbook.createCellStyle();
CreationHelper createHelper = workbook.getCreationHelper();
dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd"));
cell.setCellValue(new Date());
cell.setCellStyle(dateStyle);

六、扩展应用场景

6.1 与Web集成(Spring Boot示例)

java 复制代码
@GetMapping("/export")
public void exportExcel(HttpServletResponse response) throws IOException {
    // 设置响应头
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setHeader("Content-Disposition", "attachment; filename=export.xlsx");
    
    // 创建Excel
    Workbook workbook = new XSSFWorkbook();
    // ...填充数据
    
    // 写入响应流
    workbook.write(response.getOutputStream());
    workbook.close();
}

6.2 读取Excel数据

java 复制代码
public List<Employee> readExcel(File file) throws IOException {
    List<Employee> employees = new ArrayList<>();
    
    try (Workbook workbook = WorkbookFactory.create(file)) {
        Sheet sheet = workbook.getSheetAt(0);
        
        for (Row row : sheet) {
            if (row.getRowNum() == 0) continue; // 跳过表头
            
            Employee emp = new Employee();
            emp.setName(row.getCell(0).getStringCellValue());
            emp.setAge((int)row.getCell(1).getNumericCellValue());
            emp.setDepartment(row.getCell(2).getStringCellValue());
            
            employees.add(emp);
        }
    }
    
    return employees;
}

6.3 模板导出(基于现有Excel模板)

java 复制代码
public void exportWithTemplate() throws IOException {
    // 加载模板文件
    try (InputStream is = new FileInputStream("template.xlsx");
         Workbook workbook = new XSSFWorkbook(is)) {
        
        Sheet sheet = workbook.getSheetAt(0);
        
        // 在模板指定位置填充数据
        sheet.getRow(5).getCell(3).setCellValue("张三");
        sheet.getRow(6).getCell(3).setCellValue(new Date());
        
        // 保存为新文件
        try (FileOutputStream fos = new FileOutputStream("output.xlsx")) {
            workbook.write(fos);
        }
    }
}

结语

Apache POI作为Java处理Office文档的事实标准,功能强大但学习曲线适中。本文从最简单的Excel导出开始,逐步深入到大数据处理、图表生成等高级功能,最后介绍了实际项目中的最佳实践。掌握这些技能后,你可以:

  1. 轻松实现各种报表导出需求
  2. 处理百万级数据的Excel操作
  3. 创建专业的数据可视化图表
  4. 与Web应用无缝集成

建议从简单示例开始实践,逐步挑战更复杂的功能。POI的官方文档(https://poi.apache.org/)是很好的深入学习资源。

相关推荐
武昌库里写JAVA38 分钟前
Quartus 开发可实现人工智能加速的 FPGA 系统
java·vue.js·spring boot·课程设计·宠物管理
xujinwei_gingko41 分钟前
服务发现Nacos
java·服务发现
心想好事成1 小时前
尚硅谷redis7 47-48 redis事务之理论简介
java·数据库·redis
bloglin999992 小时前
java的vscode扩展插件
java·开发语言·vscode
Clownseven2 小时前
HTTP/2与HTTP/3特性详解:为你的Nginx/Apache服务器开启下一代Web协议
nginx·http·apache
Magnum Lehar2 小时前
vulkan游戏引擎的pipeline管道实现
java·开发语言·游戏引擎
Magnum Lehar2 小时前
vulkan游戏引擎的vulkan/shaders下的image实现
java·前端·游戏引擎
shangjg32 小时前
Java网络编程性能优化
java·网络·性能优化
会敲键盘的猕猴桃很大胆2 小时前
Redis实战-缓存篇(万字总结)
java·数据库·spring boot·redis·缓存