Excel模板引擎库JXLS简单介绍

386 阅读6分钟

前言

JAVA开发的后端同学们经常会实际开发场景中遇到需要操作或者导出Excel的情况,那么对于不同的情况场景下该怎么选择不同的库达到最快最好的效果呢?

首先先介绍下使用Java操作Excel文件的几个常用的库以及简单的对比:

  1. Apache POI: Apache POI 是最流行的Java库之一,支持对Excel文件(包括 .xls 和 .xlsx)的读写操作。它提供了全面的API,可以操作Excel中的几乎所有内容,如单元格、格式、公式等。然而,Apache POI 的学习曲线较陡,需要编写大量代码来实现复杂功能。
  2. EasyExcel: 阿里巴巴开源的 EasyExcel 专注于高性能读写,特别适用于处理大数据量的Excel文件。它的API设计简洁,但对于复杂的格式化操作支持有限。(特别说明:EasyExcel不久前阿里巴巴宣布停止维护,原 EasyExcel 作者新开发了FastExcel做替代,详情可见:FastExcel
  3. JXLS: JXLS 是一个基于 Apache POI 的模板驱动库,提供了更高层次的抽象,适合需要频繁生成格式化报表的场景。它使用模板设计,使得代码更加简洁并易于维护。

各个库的对比

功能/特点Apache POIEasyExcelJXLS
文件格式支持.xls, .xlsx.xls, .xlsx.xls, .xlsx
性能较高较高(依赖POI)
模板支持支持
API复杂度
动态逻辑处理手动实现部分支持支持

那么什么是JXLS?

JXLS 是一个轻量级的Java库,用于从Java应用程序生成和处理Excel文件。它的核心功能是通过模板的方式将数据导出到Excel中,同时支持对Excel文件的读取和解析。JXLS 的设计理念是让用户能够通过预定义的模板轻松操作复杂的Excel文件,而无需编写繁琐的代码

避免走错:

为什么选择JXLS?

在企业级开发中,Excel 是一种非常流行的数据交换和展示工具。然而,直接操作Excel文件往往会涉及到大量的低效代码,尤其是在处理复杂的格式或逻辑时。JXLS 通过以下特点解决了这些问题:

  1. 模板驱动: 使用JXLS,开发者可以通过设计直观的Excel模板,将样式和逻辑从代码中分离。这种方式提高了开发效率并减少了代码维护的复杂性。
  2. 轻量级依赖: JXLS 基于 Apache POI,继承了 POI 的强大功能,同时对其进行了封装,使开发变得更加简洁。
  3. 强大的表达式支持: JXLS 使用 JEXL 表达式语言,允许用户在模板中使用动态逻辑,比如条件判断、循环等。
  4. 灵活的数据绑定: JXLS 支持将 Java Bean 或集合轻松绑定到模板中的单元格,极大简化了数据与Excel的交互。

因此如果只是单纯的到处数据,请使用fastexcel或者easyexcel,如果excel中包含了大量的样式,且样式变动不大的话,你只需要做一个简单的模板,动态替换数据的情况下就可以使用JXLS。

什么人才需要选择JXLS

1. 需要频繁生成格式化报表的开发者
  • 如果你的应用涉及到财务报表、统计报表、销售分析、产品清单等格式化文档的生成,JXLS 能够帮助你快速创建和生成这些报表,且不需要手写大量的Excel操作代码。
  • 比如:财务团队需要定期生成月度或年度报表,开发者可以通过模板驱动方式快速生成,且模板可由非开发人员编辑。
2. 希望将Excel操作与业务逻辑分离的开发者
  • 如果你想将样式、格式、模板设计与业务逻辑代码分离,JXLS 的模板驱动方式非常适合。业务逻辑层可以专注于数据处理,而模板部分则由设计人员或业务人员负责。
  • 这样一来,开发人员无需每次修改报表格式时都修改代码,提高了项目的可维护性。
3. 中小型企业和团队
  • JXLS 通过简化Excel文件的读写操作,让中小型开发团队能够更高效地生成报告或导出数据。特别是在没有专门的Excel操作工具的情况下,JXLS 提供了一个高效、简洁的解决方案。
  • 小型团队或初创公司在报表、数据导出、打印等业务中,往往没有复杂的需求,可以通过 JXLS 高效地解决这些问题。
4. 对动态报表或模板驱动的需求较强的开发者
  • 如果你的应用中涉及到复杂的动态报表,比如根据不同条件展示不同的数据、格式或动态生成列数等,JXLS 的支持动态逻辑(例如使用JEXL表达式)非常有用。
  • 比如:需要根据不同的用户角色生成不同格式的报表,或者报表中的内容需要根据业务数据动态变化。

使用示例

以下是几个简单的数据导出示例:

jxls依赖导入:

Add jxls-poi.jar

使用maven:

<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls-poi</artifactId>
    <version>3.0.0</version>
</dependency>

使用Gradle:

implementation 'org.jxls:jxls-poi:3.0.0'

1. 最简单的替换

  1. 模板(template.xlsx)

    A1: Name
    B1: Age
    A2: ${person.name}
    B2: ${person.age}
    
  2. Java代码:

    import org.jxls.common.Context;
    import org.jxls.util.JxlsHelper;
    
    import java.io.FileOutputStream;
    import java.util.HashMap;
    import java.util.Map;
    
    public class JxlsExample {
        public static void main(String[] args) throws Exception {
            try (FileOutputStream outputStream = new FileOutputStream("output.xlsx")) {
                Map<String, Object> data = new HashMap<>();
                data.put("person", new Person("John", 25));
    
                Context context = new Context(data);
                JxlsHelper.getInstance().processTemplate(
                    JxlsExample.class.getResourceAsStream("/template.xlsx"),
                    outputStream,
                    context
                );
            }
        }
    }
    
    class Person {
        private String name;
        private int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    }
    
  3. 生成的 Excel 文件:

    NameAge
    John25

2. 带条件逻辑的动态报表

假设你需要根据条件(例如,价格大于 500)动态生成产品列表,并在模板中使用 JEXL 表达式实现逻辑。

模板(template.xlsx):

A1: Product Name
B1: Price
C1: Stock
${products}
A2: ${product.name}
B2: ${product.price}
C2: ${product.stock}
${/products}

Java代码:

import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ConditionalExportExample {
    public static void main(String[] args) throws Exception {
        try (FileOutputStream outputStream = new FileOutputStream("conditional_products_output.xlsx")) {
            List<Product> productList = new ArrayList<>();
            productList.add(new Product("Laptop", 1000, 50));
            productList.add(new Product("Smartphone", 800, 200));
            productList.add(new Product("Tablet", 400, 120));

            // 过滤出价格大于500的产品
            List<Product> filteredProducts = new ArrayList<>();
            for (Product product : productList) {
                if (product.getPrice() > 500) {
                    filteredProducts.add(product);
                }
            }

            Map<String, Object> data = new HashMap<>();
            data.put("products", filteredProducts);

            Context context = new Context(data);
            JxlsHelper.getInstance().processTemplate(
                ConditionalExportExample.class.getResourceAsStream("/template.xlsx"),
                outputStream,
                context
            );
        }
    }

    static class Product {
        private String name;
        private double price;
        private int stock;

        public Product(String name, double price, int stock) {
            this.name = name;
            this.price = price;
            this.stock = stock;
        }

        public String getName() {
            return name;
        }

        public double getPrice() {
            return price;
        }

        public int getStock() {
            return stock;
        }
    }
}

生成的 Excel 文件(只包括价格大于 500 的产品):

Product NamePriceStock
Laptop100050
Smartphone800200

3. 动态表头与列数

假设你的表格列数会根据数据动态变化,JXLS 可以通过循环来处理动态列数的情况。

模板(template.xlsx):


${columns}
A1: ${column}
${/columns}
${rows}
A2: ${row[0]}
B2: ${row[1]}
C2: ${row[2]}
${/rows}

Java代码:


import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DynamicColumnsExample {
    public static void main(String[] args) throws Exception {
        try (FileOutputStream outputStream = new FileOutputStream("dynamic_columns_output.xlsx")) {
            List<String> columns = new ArrayList<>();
            columns.add("Product Name");
            columns.add("Price");
            columns.add("Stock");

            List<List<Object>> rows = new ArrayList<>();
            rows.add(List.of("Laptop", 1000, 50));
            rows.add(List.of("Smartphone", 800, 200));
            rows.add(List.of("Tablet", 400, 120));

            Map<String, Object> data = new HashMap<>();
            data.put("columns", columns);
            data.put("rows", rows);

            Context context = new Context(data);
            JxlsHelper.getInstance().processTemplate(
                DynamicColumnsExample.class.getResourceAsStream("/template.xlsx"),
                outputStream,
                context
            );
        }
    }
}

生成的 Excel 文件:

Product NamePriceStock
Laptop100050
Smartphone800200
Tablet400120

注意事项

  1. 模板设计: 确保模板文件中的表达式与 Java 数据模型一致。
  2. 性能优化: 对于大数据量的处理,建议分批次生成 Excel 文件,以避免内存溢出。
  3. POI 依赖: 确保项目中正确配置了 Apache POI 的依赖版本。

总结

JXLS 是一个功能强大且高效的工具,适合需要频繁操作 Excel 文件的开发场景。通过模板驱动和灵活的数据绑定,JXLS 不仅简化了代码开发,还提升了系统的可维护性。如果你的项目中涉及到复杂的Excel操作,不妨试试 JXLS,这将为你节省大量时间和精力。