杰瑞科技汇

java excel 写入 poi

准备工作:添加 POI 依赖

你需要在你的项目中添加 Apache POI 的依赖,如果你使用 Maven,请在 pom.xml 文件中添加以下依赖:

java excel 写入 poi-图1
(图片来源网络,侵删)
<dependencies>
    <!-- POI Core 核心库 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.5</version> <!-- 建议使用最新稳定版 -->
    </dependency>
    <!-- POI OOXML 支持 .xlsx 格式 (推荐) -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.5</version>
    </dependency>
    <!-- 为了处理 XML 和其他格式,可能需要这个依赖 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-scratchpad</artifactId>
        <version>5.2.5</version>
    </dependency>
</dependencies>

注意: POI 支持 .xls (Excel 97-2003) 和 .xlsx (Excel 2007+) 两种格式。.xlsx 格式是现代标准,推荐使用。


核心概念

在开始写代码前,需要了解几个核心类:

类名 作用 备注
Workbook 代表整个 Excel 文件(工作簿)。 它是一个接口,具体实现类有 HSSFWorkbook (.xls) 和 XSSFWorkbook (.xlsx)。
Sheet 代表工作簿中的一个工作表(Sheet)。 "Sheet1", "Sheet2"。
Row 代表工作表中的一行。 行号从 0 开始。
Cell 代表一行中的一个单元格。 列号从 0 开始。
CellStyle 定义单元格的样式(如字体、颜色、边框、对齐方式等)。

基本流程:

  1. 创建一个 Workbook 对象。
  2. Workbook 中创建一个 Sheet 对象。
  3. Sheet 中创建一个或多个 Row 对象。
  4. Row 中创建一个或多个 Cell 对象。
  5. Cell 中设置值。
  6. Workbook 对象写入输出流(如文件输出流)。
  7. 关闭所有资源。

代码示例

示例 1:创建一个简单的 .xlsx 文件并写入数据

这个例子将创建一个名为 student_info.xlsx 的文件,并写入几行学生信息。

java excel 写入 poi-图2
(图片来源网络,侵删)
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class SimpleExcelWrite {
    public static void main(String[] args) {
        // 1. 定义文件输出路径
        String filePath = "D:/temp/student_info.xlsx";
        // try-with-resources 语句会自动关闭资源
        try (Workbook workbook = new XSSFWorkbook(); // 创建一个 .xlsx 格式的工作簿
             FileOutputStream outputStream = new FileOutputStream(filePath)) {
            // 2. 创建一个工作表,名为 "学生信息"
            Sheet sheet = workbook.createSheet("学生信息");
            // 3. 创建表头(第一行)
            Row headerRow = sheet.createRow(0);
            headerRow.createCell(0).setCellValue("学号");
            headerRow.createCell(1).setCellValue("姓名");
            headerRow.createCell(2).setCellValue("年龄");
            headerRow.createCell(3).setCellValue("专业");
            // 4. 创建数据行
            // 第二行
            Row row1 = sheet.createRow(1);
            row1.createCell(0).setCellValue(1001);
            row1.createCell(1).setCellValue("张三");
            row1.createCell(2).setCellValue(20);
            row1.createCell(3).setCellValue("计算机科学");
            // 第三行
            Row row2 = sheet.createRow(2);
            row2.createCell(0).setCellValue(1002);
            row2.createCell(1).setCellValue("李四");
            row2.createCell(2).setCellValue(21);
            row2.createCell(3).setCellValue("软件工程");
            // 第五行(故意跳过第四行,看看效果)
            Row row3 = sheet.createRow(4);
            row3.createCell(0).setCellValue(1003);
            row3.createCell(1).setCellValue("王五");
            row3.createCell(2).setCellValue(22);
            row3.createCell(3).setCellValue("数据科学");
            // 5. 将工作簿写入文件
            workbook.write(outputStream);
            System.out.println("Excel 文件创建成功!路径: " + filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行后,你会得到一个 student_info.xlsx 文件,内容如下: | 学号 | 姓名 | 年龄 | 专业 | | :--- | :--- | :--- | :--- | | 1001 | 张三 | 20 | 计算机科学 | | 1002 | 李四 | 21 | 软件工程 | | (空行) | | | | | 1003 | 王五 | 22 | 数据科学 |


示例 2:使用样式(字体、颜色、边框)

这个例子在示例1的基础上,为表头添加了样式,使其更醒目。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class StyledExcelWrite {
    public static void main(String[] args) {
        String filePath = "D:/temp/styled_student_info.xlsx";
        try (Workbook workbook = new XSSFWorkbook();
             FileOutputStream outputStream = new FileOutputStream(filePath)) {
            Sheet sheet = workbook.createSheet("带样式的学生信息");
            // --- 创建样式 ---
            // 1. 创建一个字体样式
            Font headerFont = workbook.createFont();
            headerFont.setBold(true); // 加粗
            headerFont.setFontHeightInPoints((short) 14); // 字体大小
            headerFont.setColor(IndexedColors.RED.getIndex()); // 字体颜色
            // 2. 创建一个单元格样式
            CellStyle headerCellStyle = workbook.createCellStyle();
            headerCellStyle.setFont(headerFont);
            headerCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
            headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
            // 设置边框
            headerStyle.setBorderTop(BorderStyle.THIN);
            headerStyle.setBorderBottom(BorderStyle.THIN);
            headerStyle.setBorderLeft(BorderStyle.THIN);
            headerStyle.setBorderRight(BorderStyle.THIN);
            // --- 应用样式到表头 ---
            Row headerRow = sheet.createRow(0);
            String[] headers = {"学号", "姓名", "年龄", "专业"};
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerCellStyle);
            }
            // --- 写入数据行 ---
            // 为了简单,这里只写一行数据
            Row dataRow = sheet.createRow(1);
            dataRow.createCell(0).setCellValue(1001);
            dataRow.createCell(1).setCellValue("张三");
            dataRow.createCell(2).setCellValue(20);
            dataRow.createCell(3).setCellValue("计算机科学");
            // --- 自动调整列宽 ---
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
            }
            workbook.write(outputStream);
            System.out.println("带样式的 Excel 文件创建成功!路径: " + filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

示例 3:写入大数据量(优化内存)

如果需要写入大量数据(例如数万行),直接使用 XSSFWorkbook 会导致内存溢出,因为它会将整个 Excel 文件加载到内存中,这时应该使用 SXSSFWorkbook,它是一个基于 XSSF 的流式 API,只在内存中保留一定数量的行,其他数据会临时写入磁盘,从而大大减少内存消耗。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class LargeDataExcelWrite {
    public static void main(String[] args) {
        String filePath = "D:/temp/large_data_report.xlsx";
        // SXSSFWorkbook 的参数是内存中保留的行数,超过的会被写入临时文件
        // -1 表示不限制,但会占用大量内存,1000 是一个比较合理的值。
        try (Workbook workbook = new SXSSFWorkbook(1000);
             FileOutputStream outputStream = new FileOutputStream(filePath)) {
            Sheet sheet = workbook.createSheet("大数据报表");
            // 假设有 10 万行数据
            int rowCount = 100000;
            for (int i = 0; i < rowCount; i++) {
                Row row = sheet.createRow(i);
                row.createCell(0).setCellValue("ID_" + i);
                row.createCell(1).setCellValue("用户_" + i);
                row.createCell(2).setCellValue(Math.random() * 10000); // 随机金额
                // 每写 1000 行,可以调用一下 flush() 来清理内存(可选)
                if (i % 1000 == 0) {
                    ((SXSSFWorkbook) workbook).flushRows();
                }
            }
            workbook.write(outputStream);
            System.out.println("大数据量 Excel 文件创建成功!路径: " + filePath);
            // 注意:SXSSFWorkbook 在关闭时会自动删除临时文件。
            // 如果你需要保留临时文件,可以在构造时传入一个临时文件目录。
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

最佳实践和注意事项

  1. 使用 try-with-resourcesWorkbook, FileOutputStream 等资源都需要被关闭。try-with-resources 语句可以确保它们在使用后被自动关闭,避免资源泄漏。
  2. 选择正确的 Workbook 实现
    • .xls 文件:HSSFWorkbook
    • .xlsx 文件:XSSFWorkbook (数据量小) 或 SXSSFWorkbook (数据量大)
  3. 处理日期:POI 对日期有特殊处理。
    • 写入时,使用 cell.setCellValue(new Date());
    • 必须为包含日期的单元格设置一个专门的日期格式样式,否则 Excel 可能无法正确识别。
      CellStyle dateStyle = workbook.createCellStyle();
      CreationHelper createHelper = workbook.getCreationHelper();
      dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
      Cell dateCell = row.createCell(4);
      dateCell.setCellValue(new Date());
      dateCell.setCellStyle(dateStyle);
  4. 自动调整列宽:在写入所有数据后,调用 sheet.autoSizeColumn(columnIndex); 可以根据内容自动调整列宽,使表格更美观,注意,这个方法在处理大数据量时可能会比较慢。
  5. 处理公式:和普通值一样,使用 cell.setFormula("A1+B1"); 来设置公式。
  6. 性能优化
    • 对于大数据量,务必使用 SXSSFWorkbook
    • 在循环中尽量避免重复创建样式和字体,最好在循环外创建好,然后在循环内复用。

希望这份详细的指南能帮助你熟练掌握使用 Java 和 POI 写入 Excel 文件!

分享:
扫描分享到社交APP
上一篇
下一篇