杰瑞科技汇

Java如何导出Excel2007?

核心依赖 (Maven)

你需要在你的 pom.xml 文件中添加 Apache POI 的依赖,对于 Excel 2007 (.xlsx),你需要使用 poi-ooxml 模块。

<dependencies>
    <!-- 核心依赖 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.4</version> <!-- 建议使用较新版本 -->
    </dependency>
    <!-- 用于处理 .xlsx 格式的依赖 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.4</version>
    </dependency>
    <!-- 为了支持 XML 和其他格式,可能还需要这个 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-lite</artifactId>
        <version>5.2.4</version>
    </dependency>
</dependencies>

基础示例:创建一个简单的 .xlsx 文件

这个示例将演示如何创建一个工作簿,添加一个工作表,写入数据,并保存到本地文件。

代码实现

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class BasicExcelExport {
    public static void main(String[] args) {
        // 1. 创建一个新的 XSSFWorkbook 对象,代表一个 .xlsx 文件
        Workbook workbook = new XSSFWorkbook();
        try {
            // 2. 创建一个工作表,命名为 "员工信息"
            Sheet sheet = workbook.createSheet("员工信息");
            // 3. 创建标题行(第0行)
            Row headerRow = sheet.createRow(0);
            // 设置标题
            headerRow.createCell(0).setCellValue("ID");
            headerRow.createCell(1).setCellValue("姓名");
            headerRow.createCell(2).setCellValue("部门");
            headerRow.createCell(3).setCellValue("入职日期");
            // 4. 创建数据行
            // 第一行数据
            Row dataRow1 = sheet.createRow(1);
            dataRow1.createCell(0).setCellValue(1);
            dataRow1.createCell(1).setCellValue("张三");
            dataRow1.createCell(2).setCellValue("研发部");
            dataRow1.createCell(3).setCellValue(setDateValue(workbook, "2025-01-15")); // 设置日期格式
            // 第二行数据
            Row dataRow2 = sheet.createRow(2);
            dataRow2.createCell(0).setCellValue(2);
            dataRow2.createCell(1).setCellValue("李四");
            dataRow2.createCell(2).setCellValue("市场部");
            dataRow2.createCell(3).setCellValue(setDateValue(workbook, "2025-05-20"));
            // 5. 自动调整列宽,使内容显示完整
            for (int i = 0; i < 4; i++) {
                sheet.autoSizeColumn(i);
            }
            // 6. 定义文件输出路径
            String filePath = "D:/temp/员工信息.xlsx";
            // 7. 将工作簿写入到文件
            try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
                workbook.write(fileOut);
                System.out.println("Excel 文件生成成功!路径: " + filePath);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 8. 关闭工作簿,释放资源
            try {
                if (workbook != null) {
                    workbook.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 设置单元格为日期格式
     * @param workbook 工作簿对象
     * @param dateString 日期字符串 (yyyy-MM-dd)
     * @return CellStyle 设置好样式的单元格
     */
    private static CellStyle setDateValue(Workbook workbook, String dateString) {
        // 创建单元格样式
        CellStyle dateStyle = workbook.createCellStyle();
        // 创建数据格式
        CreationHelper createHelper = workbook.getCreationHelper();
        // 设置日期格式为 "yyyy-MM-dd"
        dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd"));
        // 创建一个临时单元格来应用样式
        // 注意:这个单元格不会被写入最终文件,仅用于样式设置
        Cell tempCell = workbook.createSheet("temp").createRow(0).createCell(0);
        tempCell.setCellStyle(dateStyle);
        // 设置日期值,POI会自动处理
        tempCell.setCellValue(java.sql.Date.valueOf(dateString));
        // 返回创建好的样式
        return dateStyle;
    }
}

代码解释

  1. Workbook workbook = new XSSFWorkbook();

    • Workbook 是 POI 中表示 Excel 文件的顶级接口。
    • XSSFWorkbook 是专门用于操作 .xlsx (Excel 2007+) 格式的实现类。
  2. Sheet sheet = workbook.createSheet("员工信息");

    • Sheet 代表 Excel 文件中的一个工作表(Sheet)。
    • createSheet() 方法用于创建一个新的工作表,并可以指定其名称。
  3. Row row = sheet.createRow(0);

    • Row 代表工作表中的一行。
    • createRow() 用于创建一行,参数是行索引(从 0 开始)。
  4. Cell cell = row.createCell(0);

    • Cell 代表行中的一个单元格。
    • createCell() 用于创建一个单元格,参数是列索引(从 0 开始)。
  5. cell.setCellValue("张三");

    • setCellValue() 方法用于向单元格中设置值,POI 支持多种数据类型,如 String, Integer, Double, Date 等。
  6. CellStyleDataFormat

    • CellStyle 用于定义单元格的样式,如字体、颜色、边框、对齐方式以及数据格式
    • 要设置日期格式,需要先获取 CreationHelper,然后创建 DataFormat 对象,并调用 getFormat() 方法传入格式字符串(如 "yyyy-MM-dd")。
    • 最后将创建的 CellStyle 应用到单元格上。
  7. sheet.autoSizeColumn(i);

    这是一个非常实用的方法,可以根据列内容自动调整列宽,避免内容被截断。

  8. FileOutputStreamworkbook.write()

    • 使用 FileOutputStream 指定一个输出路径。
    • 调用 workbook.write(fileOut) 将内存中的 Workbook 对象写入到文件流中。
  9. try-with-resourcesworkbook.close()

    • 最佳实践Workbook 对象会占用大量内存,使用完毕后必须关闭以释放资源。
    • 推荐使用 try-with-resources 语句(如 try (FileOutputStream ...)),它可以自动关闭实现了 AutoCloseable 接口(如 FileOutputStreamXSSFWorkbook)的资源,即使在发生异常时也能确保关闭。

进阶示例:Web 项目中下载 Excel

在实际的 Web 应用(如 Spring Boot 项目)中,我们通常不是将文件保存到服务器磁盘,而是直接通过 HTTP 响应让用户下载。

代码实现 (以 Spring Boot 为例)

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@RestController
public class ExcelDownloadController {
    @GetMapping("/download-excel")
    public void downloadExcel(HttpServletResponse response) throws IOException {
        // 1. 创建工作簿和工作表
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("产品列表");
        // 2. 创建标题行
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("产品ID");
        headerRow.createCell(1).setCellValue("产品名称");
        headerRow.createCell(2).setCellValue("价格");
        // 3. 创建数据行
        for (int i = 1; i <= 10; i++) {
            Row row = sheet.createRow(i);
            row.createCell(0).setCellValue(i);
            row.createCell(1).setCellValue("产品 " + i);
            row.createCell(2).setCellValue(10.0 * i);
        }
        // 4. 自动调整列宽
        for (int i = 0; i < 3; i++) {
            sheet.autoSizeColumn(i);
        }
        // 5. 设置响应头
        // 设置 Content-Type,告诉浏览器这是一个要下载的文件
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 设置 Content-Disposition,指定文件名和下载方式
        String fileName = "产品列表_" + System.currentTimeMillis() + ".xlsx";
        // 对文件名进行 URL 编码,防止中文乱码
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=utf-8''" + encodedFileName);
        // 6. 写入响应输出流
        try (OutputStream out = response.getOutputStream()) {
            workbook.write(out);
            workbook.close();
        }
    }
}

Web 下载关键点

  1. response.setContentType(...)

    • 必须设置为 Excel 2007 的 MIME 类型:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  2. response.setHeader("Content-Disposition", ...)

    • attachment:表示这是一个附件,浏览器会触发下载对话框而不是直接在浏览器中打开。
    • filename="...":指定下载时显示的文件名。
    • URLEncoder.encode():如果文件名包含中文,必须进行 URL 编码,否则在不同浏览器下可能会出现乱码。
  3. response.getOutputStream()

    • 获取 HttpServletResponse 的输出流,将 Workbook 写入这个流中,数据就会直接发送给浏览器。

高级功能与最佳实践

1 使用样式美化单元格

// 在创建 Workbook 后
CellStyle style = workbook.createCellStyle();
// 1. 设置字体
Font font = workbook.createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 12);
font.setBold(true);
style.setFont(font);
// 2. 设置背景色
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 3. 设置边框
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
// 4. 设置对齐方式
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
// 应用样式到单元格
Cell cell = sheet.createRow(0).createCell(0);
cell.setCellValue("这是一个标题");
cell.setCellStyle(style);

2 合并单元格

// 合并从 (0, 0) 到 (4, 0) 的区域
sheet.addMergedRegion(new CellRangeAddress(0, 4, 0, 0));

3 性能优化(大数据量导出)

当导出数据量非常大(例如几十万行)时,将所有数据一次性加载到内存中的 XSSFWorkbook 会导致 OutOfMemoryError,这时,应使用 SXSSFWorkbook(流 API)。

SXSSFWorkbook 是基于 XSSFWorkbook 的,它会在写入磁盘后,将不活跃的行从内存中移除,从而保持一个较小的内存占用。

示例代码:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFRow;
import java.io.FileOutputStream;
import java.io.IOException;
public class LargeDataExport {
    public static void main(String[] args) throws IOException {
        // 1. 创建 SXSSFWorkbook,参数 100 表示在内存中保留的行数
        Workbook workbook = new SXSSFWorkbook(100);
        Sheet sheet = workbook.createSheet("大数据量");
        // 2. 写入 100,000 行数据
        for (int rownum = 0; rownum < 100000; rownum++) {
            Row row = sheet.createRow(rownum);
            for (int cellnum = 0; cellnum < 10; cellnum++) {
                Cell cell = row.createCell(cellnum);
                cell.setCellValue("Row " + rownum + ", Cell " + cellnum);
            }
            // 每 1000 行刷新一次,写入临时文件
            if (rownum % 1000 == 0) {
                ((SXSSFSheet) sheet).flushRows();
            }
        }
        // 3. 写入文件
        try (FileOutputStream out = new FileOutputStream("D:/temp/large_data.xlsx")) {
            workbook.write(out);
        }
        // 4. 关闭 workbook,会清理掉临时文件
        ((SXSSFWorkbook) workbook).dispose();
    }
}

注意:SXSSFWorkbook 不支持所有 XSSFWorkbook 的功能(例如部分图表和公式),但在处理纯数据导出时,它是性能最优的选择。


功能 核心类 适用场景
基础创建 XSSFWorkbook 创建 .xlsx 文件,写入少量到中等量数据。
Web 下载 XSSFWorkbook + HttpServletResponse 在 Web 应用中提供文件下载功能。
样式美化 CellStyle, Font, Border 对 Excel 的外观进行定制。
大数据量 SXSSFWorkbook 导出海量数据(万行以上),防止内存溢出。
旧版 Excel HSSFWorkbook 用于导出 .xls (Excel 97-2003) 格式。

对于绝大多数 Java 项目,Apache POI 是导出 Excel 的首选,掌握 XSSFWorkbookSXSSFWorkbook 的用法,以及样式和 Web 下载的技巧,就能应对绝大多数导出需求。

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