java怎么导出poi报表

用Java导出POI报表需引入Apache POI依赖,通过Workbook/Sheet操作单元格写入数据,设置样式后调用Write方法输出至本地/流,支持.xls/.

以下是关于 Java 使用 Apache POI 导出报表 的详细教程,涵盖核心概念、完整代码示例、最佳实践及常见问题解决方案:

java怎么导出poi报表


技术选型与基础准备

1 为什么选择 Apache POI?

Apache POI 是 Java 操作 Microsoft Office 文档的标准库,支持以下特性:
| 组件 | 描述 | 适用场景 |
|————|——————————-|————————|
| XSSF | .xlsx (Excel 2007+) | 新项目首选 |
| HSSF | .xls (Excel 97-2003) | 兼容旧版Office |
| HWPF | Word 文档 | 复杂排版需求 |
| HSLF | PowerPoint 幻灯片 | 演示文稿自动化 |

2 环境配置

Maven 依赖(推荐):

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version> <!-最新稳定版 -->
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

⚠️ 注意:若需支持 .xls 格式,需额外添加 poi 依赖。

java怎么导出poi报表


核心开发流程详解

1 创建 Excel 文件骨架

import org.apache.poi.ss.usermodel.;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.util.Date;
public class ExcelExporter {
    public static void main(String[] args) throws Exception {
        // 1. 创建工作簿(XSSF=xlsx, HSSF=xls)
        Workbook workbook = new XSSFWorkbook(); // 默认生成xlsx格式
        // 2. 创建工作表并命名
        Sheet sheet = workbook.createSheet("销售统计");
        // 3. 定义表头样式
        CellStyle headerStyle = workbook.createCellStyle();
        Font headerFont = workbook.createFont();
        headerFont.setBold(true);          // 加粗
        headerFont.setColor(IndexedColors.BLACK.getIndex()); // 字体颜色
        headerStyle.setFont(headerFont);   // 应用字体
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 背景色
        headerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        // 4. 写入表头数据
        Row headerRow = sheet.createRow(0); // 第1行(索引从0开始)
        String[] headers = {"ID", "产品名称", "单价", "销量", "总金额", "下单日期"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle); // 应用样式
        }
        // 5. 填充动态数据(模拟数据库查询结果)
        Object[][] data = {
            {1, "笔记本电脑", 5999.0, 120, 719880.0, new Date()},
            {2, "智能手机", 2999.0, 350, 1049650.0, new Date()},
            {3, "平板电脑", 1999.0, 80, 159920.0, new Date()}
        };
        // 6. 数据行样式配置
        CellStyle dataStyle = workbook.createCellStyle();
        dataStyle.setAlignment(HorizontalAlignment.CENTER);
        dataStyle.setDataFormat(workbook.getCreationHelper().createDataFormat().getFormat("#,##0.00")); // 数值格式化
        // 7. 遍历数据写入行
        for (int rowNum = 0; rowNum < data.length; rowNum++) {
            Row row = sheet.createRow(rowNum + 1); // 跳过表头行
            Object[] colData = data[rowNum];
            for (int colNum = 0; colNum < colData.length; colNum++) {
                Cell cell = row.createCell(colNum);
                if (colData[colNum] instanceof Date) {
                    cell.setCellValue((Date) colData[colNum]);
                    // 设置日期格式
                    CellStyle dateStyle = workbook.createCellStyle();
                    dateStyle.cloneStyleFrom(dataStyle);
                    dateStyle.setDataFormat(workbook.getCreationHelper().createDataFormat().getFormat("yyyy-MM-dd"));
                    cell.setCellStyle(dateStyle);
                } else if (colData[colNum] instanceof Number) {
                    cell.setCellValue((Double) colData[colNum]);
                    cell.setCellStyle(dataStyle); // 应用数值格式
                } else {
                    cell.setCellValue(colData[colNum].toString());
                }
            }
        }
        // 8. 自动调整列宽(根据内容自适应)
        for (int i = 0; i < headers.length; i++) {
            sheet.autoSizeColumn(i); // 逐列调整宽度
        }
        // 9. 冻结窗格(固定表头)
        sheet.createFreezePane(0, 1); // 冻结首行+首列
        // 10. 写入到文件系统
        try (FileOutputStream outputStream = new FileOutputStream("销售报表_" + System.currentTimeMillis() + ".xlsx")) {
            workbook.write(outputStream);
        } finally {
            workbook.close(); // 释放资源
        }
    }
}

2 关键功能解析表

功能 实现方式 作用
单元格样式 CellStyle + Font + Color 控制字体、颜色、对齐方式等
数值格式化 DataFormat + createDataFormat() 货币/百分比/日期等专业显示
自动换行 cell.setWrapText(true) 长文本自动换行
合并单元格 sheet.addMergedRegion(new CellRangeAddress(startRow, endRow, startCol, endCol)) 跨行/列合并
插入图片 Drawing drawing = sheet.createDrawingPatriarch(); + Picture pict = drawing.addPicture(...) 嵌入公司Logo等图片
添加批注 CreationHelper helper = workbook.getCreationHelper(); Comment comment = sheet.createCellComment(cell); 单元格注释
保护工作表 sheet.protectSheet(password); 限制编辑权限

进阶技巧与最佳实践

1 大数据量处理优化

  • SXSSFEventUserModel:流式API,适合百万级数据(内存占用降低90%)
    import org.apache.poi.ss.util.StreamingReader;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;

// 创建流式工作簿(最多保留100行内存)
SXSSFWorkbook wb = new SXSSFWorkbook(100);
Sheet sh = wb.createSheet();
// …写入数据…
wb.write(outputStream); // 直接写入输出流
wb.dispose(); // 清理临时文件

分页导出:按固定行数拆分多个Sheet,避免单个文件过大。
# 3.2 动态列宽计算
```java最大宽度调整列宽(单位:磅)
for (int i = 0; i < maxColumns; i++) {
    sheet.trackColumnForAutoSizing(i); // 标记需要自动调整的列
    sheet.autoSizeColumn(i, true);    // true表示基于所有行的宽度计算
}

3 复杂表头设计

通过多层嵌套实现三级表头:

// 第一层表头(大分类)
Row catRow = sheet.createRow(currentRow++);
catRow.createCell(0).setCellValue("电子产品");
catRow.createCell(3).setCellValue("家居用品");
// 第二层子分类(合并单元格)
sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow, 0, 2)); // 合并A-C列
Row subCatRow = sheet.createRow(currentRow);
subCatRow.createCell(0).setCellValue("数码设备");

典型错误及解决方案

错误现象 原因分析 解决方案
中文显示为方框 缺少中文字体包 下载微软雅黑字体文件,通过Font类加载:font.setFontName("Microsoft YaHei")
数字显示科学计数法 未设置数值格式 使用DataFormat指定格式:”#,##0.00″
文件无法打开 写入时未关闭流 确保workbook.write()后调用workbook.close()
内存溢出(OOM) 一次性加载过多数据 改用SXSSFWorkbook流式处理,或分批次写入
时间显示不正确 未设置日期格式 使用createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss")

相关问答FAQs

Q1: 导出的Excel文件中中文显示乱码怎么办?

A: 这是由于默认使用的字体不支持中文导致的,解决方法有两种:

java怎么导出poi报表

  1. 指定中文字体:在创建Font对象时设置字体名称为系统中存在的中文字体(如”宋体”、”微软雅黑”)。
    Font font = workbook.createFont();
    font.setFontName("微软雅黑"); // Windows系统常用字体
    font.setCharSet(FontCharSet.DEFAULT_CHARSET); // 确保字符集正确
  2. 嵌入字体文件:将TTF字体文件打包到项目中,通过InputStream加载:
    InputStream is = new FileInputStream("simhei.ttf");
    Font font = workbook.createFont();
    font.setFontName("SiHei"); // 字体名称需与文件名一致
    font.setFontCharSet(FontCharSet.UTF_8); // 强制使用UTF-8编码

Q2: 如何动态设置每列的不同宽度?

A: 可以通过两种方式实现:

  1. 精确像素控制:使用sheet.setColumnWidth(columnIndex, widthUnits),其中widthUnits的单位是1/256个字符宽度。
    // 设置第2列(B列)宽度为30个字符宽度
    sheet.setColumnWidth(1, 30  256); // 1代表B列(索引从0开始)
  2. 自动适配内容:调用sheet.autoSizeColumn(columnIndex),该方法会根据该列中最宽的内容自动调整宽度,注意:此方法应在所有数据写入完成后调用。
    // 在所有数据写入完成后调用
    for (int i = 0; i < maxColumns; i++) {
        sheet.autoSizeColumn(i); // 逐列自动调整宽度
    }

    ⚠️ 提示:autoSizeColumn会影响性能,建议仅

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/96384.html

(0)
酷盾叔的头像酷盾叔
上一篇 2025年8月7日 15:05
下一篇 2025年8月7日 15:11

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN