杰瑞科技汇

Java Excel导出用jxl如何实现?

jxl (Java Excel API) 是一个比较老牌的 Java 操作 Excel 的库,它支持 .xls 格式(即 Excel 97-2003 版本),对于新项目,更推荐使用 Apache POI,因为它功能更强大、社区更活跃,并且支持 .xlsx 格式,如果你需要维护旧项目或者对 .xls 格式有特定需求,jxl 仍然是一个简单易用的选择。

Java Excel导出用jxl如何实现?-图1
(图片来源网络,侵删)

准备工作:添加 JXL 依赖

你需要在你的项目中添加 jxl 的依赖。

Maven 方式

在你的 pom.xml 文件中添加以下依赖:

<dependency>
    <groupId>net.sourceforge.jexcelapi</groupId>
    <artifactId>jxl</artifactId>
    <version>2.6.12</version>
</dependency>

Gradle 方式

在你的 build.gradle 文件中添加:

implementation 'net.sourceforge.jexcelapi:jxl:2.6.12'

手动添加 JAR

如果你不使用构建工具,可以 从官网下载 JAR 包,然后将其添加到你的项目类路径中。

Java Excel导出用jxl如何实现?-图2
(图片来源网络,侵删)

JXL 核心概念

在开始编码前,先了解几个核心类:

  • WritableWorkbook: 代表一个可写入的 Excel 工作簿,在创建新 Excel 文件或修改现有文件时使用。
  • WritableSheet: 代表 WritableWorkbook 中的一个工作表。
  • Label: 代表 Excel 中的一个单元格,用于写入字符串类型的数据。
  • Number: 代表 Excel 中的一个单元格,用于写入数字类型的数据。
  • DateTime: 代表 Excel 中的一个单元格,用于写入日期类型的数据。
  • WritableCellFormat: 用于设置单元格的样式,如字体、颜色、对齐方式、边框等。

完整示例:导出数据到 Excel

下面是一个完整的、可直接运行的 Java 示例,演示如何将一个用户列表数据导出到一个名为 users.xls 的文件中。

import jxl.*;
import jxl.write.*;
import jxl.write.Number;
import jxl.write.biff.RowsExceededException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class JxlExportExample {
    public static void main(String[] args) {
        // 1. 准备要导出的数据
        List<User> userList = prepareData();
        // 2. 定义要导出的文件路径
        String filePath = "D:/temp/users.xls";
        // 3. 调用导出方法
        exportUsersToExcel(userList, filePath);
        System.out.println("Excel 文件导出成功!路径: " + filePath);
    }
    /**
     * 导出用户数据到 Excel 文件
     * @param userList 用户数据列表
     * @param filePath 导出文件路径
     */
    public static void exportUsersToExcel(List<User> userList, String filePath) {
        // 使用 try-with-resources 语句,确保资源被自动关闭
        try (WritableWorkbook workbook = Workbook.createWorkbook(new File(filePath))) {
            // 4. 创建一个工作表
            WritableSheet sheet = workbook.createSheet("用户信息", 0); // "用户信息"是工作表名, 0是工作表索引
            // 5. 设置表头(使用 Label 对象)
            WritableCellFormat headerFormat = new WritableCellFormat();
            // 设置字体为粗体
            WritableFont headerFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD);
            headerFormat.setFont(headerFont);
            // 设置背景色(浅灰色)
            jxl.format.Pattern headerPattern = new jxl.format.Pattern(jxl.format.Colour.GRAY_25);
            headerFormat.setBackground(headerPattern);
            // 添加表头单元格
            sheet.addCell(new Label(0, 0, "ID", headerFormat));
            sheet.addCell(new Label(1, 0, "姓名", headerFormat));
            sheet.addCell(new Label(2, 0, "年龄", headerFormat));
            sheet.addCell(new Label(3, 0, "创建日期", headerFormat));
            // 6. 写入数据行
            for (int i = 0; i < userList.size(); i++) {
                User user = userList.get(i);
                int rowNum = i + 1; // Excel 行号从 0 开始,数据行从 1 开始(因为第 0 行是表头)
                // 写入ID (使用 Number 类型)
                sheet.addCell(new Number(0, rowNum, user.getId()));
                // 写入姓名 (使用 Label 类型)
                sheet.addCell(new Label(1, rowNum, user.getName()));
                // 写入年龄 (使用 Number 类型)
                sheet.addCell(new Number(2, rowNum, user.getAge()));
                // 写入创建日期 (使用 DateTime 类型)
                sheet.addCell(new DateTime(3, rowNum, user.getCreateDate()));
            }
            // 7. 写入文件并关闭
            // write() 方法会将所有在内存中的操作写入到指定的文件中
            workbook.write();
        } catch (IOException e) {
            System.err.println("创建或写入文件时发生IO异常: " + e.getMessage());
            e.printStackTrace();
        } catch (WriteException e) {
            System.err.println("写入Excel数据时发生异常: " + e.getMessage());
            e.printStackTrace();
        }
    }
    /**
     * 模拟准备用户数据
     */
    private static List<User> prepareData() {
        List<User> users = new ArrayList<>();
        users.add(new User(1L, "张三", 28, new Date()));
        users.add(new User(2L, "李四", 32, new Date()));
        users.add(new User(3L, "王五", 25, new Date()));
        users.add(new User(4L, "赵六", 45, new Date()));
        return users;
    }
    /**
     * 用户实体类
     */
    static class User {
        private Long id;
        private String name;
        private int age;
        private Date createDate;
        public User(Long id, String name, int age, Date createDate) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.createDate = createDate;
        }
        // Getters
        public Long getId() { return id; }
        public String getName() { return name; }
        public int getAge() { return age; }
        public Date getCreateDate() { return createDate; }
    }
}

代码解析:

  1. 准备数据:创建一个 User 对象列表,这是我们要导出的源数据。
  2. 创建 WritableWorkbookWorkbook.createWorkbook(new File(filePath)) 会创建一个新的、空的 Excel 工作簿,如果文件已存在,它将被覆盖。
  3. 创建 WritableSheetworkbook.createSheet() 在工作簿中创建一个新的工作表。
  4. 设置表头
    • 创建 WritableCellFormatWritableFont 来定义表头的样式(粗体、灰色背景)。
    • 使用 new Label(column, row, "内容", format) 来创建表头单元格。Label 用于文本。
  5. 写入数据行
    • 遍历数据列表,为每个用户对象创建一行。
    • 注意:Excel 的行列索引都是从 0 开始的,表头在第 0 行,所以数据行从 1 开始。
    • 根据数据类型选择合适的单元格对象:
      • 数字用 Number(column, row, value)
      • 字符串用 Label(column, row, value)
      • 日期用 DateTime(column, row, value)
  6. 写入并关闭:调用 workbook.write() 将内存中的 Excel 对象持久化到磁盘文件。try-with-resources 会自动调用 workbook.close(),确保资源被正确释放。

常用功能与技巧

1 设置单元格样式

除了表头的样式,你还可以为数据单元格设置样式。

// 创建一个单元格格式
WritableCellFormat numberFormat = new WritableCellFormat();
// 设置字体
WritableFont font = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.BLACK);
numberFormat.setFont(font);
// 设置对齐方式(水平居中)
numberFormat.setAlignment(jxl.format.Alignment.CENTRE);
// 设置垂直居中
numberFormat.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
// 设置边框
numberFormat.setBorder(Border.ALL, BorderLineStyle.THIN, Colour.BLACK);
// 应用样式
sheet.addCell(new Number(0, 1, 100, numberFormat));

2 合并单元格

使用 WritableSheet.mergeCells() 方法。

// 合并从 (0, 0) 到 (2, 0) 的区域,即第 0 行,第 0 列到第 2 列
sheet.mergeCells(0, 0, 2, 0);
// 在合并后的区域的左上角单元格写入内容
sheet.addCell(new Label(0, 0, "合并的标题"));

3 设置列宽

使用 WritableSheet.setColumnWidth() 方法。

// 设置第 1 列(索引为 1)的宽度,宽度是字符数
sheet.setColumnWidth(1, 20); // 设置姓名列宽度为 20 个字符
sheet.setColumnWidth(2, 5);  // 设置年龄列宽度为 5 个字符

4 在 Web 应用中导出(Servlet 示例)

在 Web 应用中,通常需要将 Excel 文件作为附件直接提供给用户下载,而不是保存到服务器磁盘。

// 在 Servlet 的 doGet 或 doPost 方法中
response.setContentType("application/vnd.ms-excel"); // 设置正确的 MIME 类型
response.setHeader("Content-Disposition", "attachment; filename=user_list.xls"); // 设置下载文件名
// 获取输出流
OutputStream out = response.getOutputStream();
try (WritableWorkbook workbook = Workbook.createWorkbook(out)) {
    // ... (和上面示例中一样,创建 sheet 和写入数据)
    // 写入数据
    workbook.write();
} catch (Exception e) {
    // 处理异常
    e.printStackTrace();
} finally {
    // 确保输出流被关闭
    if (out != null) {
        try {
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

JXL 的局限性

尽管 jxl 简单易用,但它也存在一些明显的缺点:

  1. 不支持 .xlsx 格式:这是最致命的缺点。.xlsx 是目前 Excel 的标准格式,而 jxl 只能处理旧版的 .xls 格式。
  2. 停止更新jxl 项目已经很多年没有更新了,对于 Excel 的新特性(如复杂的图表、公式、数据透视表等)完全不支持。
  3. 功能有限:在样式、图片插入、复杂公式等方面的功能远不如 Apache POI 强大。
特性 JXL Apache POI
格式支持 .xls .xls.xlsx
社区活跃度 低,已停止更新 高,持续更新
功能丰富度 基础功能(读、写、简单样式) 非常强大(样式、图表、公式、图片等)
API 易用性 简单直观 相对复杂,但功能更全面
推荐场景 旧项目维护、对 .xls 有简单需求的新项目 所有新项目,特别是需要 .xlsx 或复杂功能的场景

对于新项目,强烈建议直接使用 Apache POI,如果你正在维护一个旧的 jxl 项目,或者只需要做一个非常简单的 .xls 导出功能,jxl 仍然是一个可以快速完成任务的选择。

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