【JAVA】阿里巴巴 EasyExcel:高效的Excel处理解决方案

在这里插入图片描述


更多相关内容可查看

附官网地址:https://easyexcel.opensource.alibaba.com/docs/current/api/

EasyExcel

在现代企业的业务处理中,Excel 文件常常被用来进行数据交换、报告生成和数据分析等任务。然而,处理 Excel 文件可能会变得十分复杂,特别是当数据量很大时。阿里巴巴的 EasyExcel 提供了一个高效、简便的解决方案,用于处理大规模的 Excel 文件。本博客将详细介绍 EasyExcel 的特性、使用方法,并提供具体的业务开发示例和代码。

1. EasyExcel 简介

EasyExcel 是阿里巴巴开源的一个 Java 库,旨在提高 Excel 文件处理的性能。它是基于 POI 的封装,主要用于简化 Excel 文件的读写操作,并且在处理大数据量时表现出色。

1.1 主要特点
  • 高性能:能够处理百万级数据而不占用大量内存。
  • 易用性:提供简单易用的 API,降低使用门槛。
  • 支持大数据量:通过逐行读取和写入,避免一次性加载全部数据到内存中。
  • 注解驱动:通过注解配置简化代码编写,增强可读性。
1.2 依赖配置

要使用 EasyExcel,需要在 Maven 或 Gradle 配置相应的依赖。

Maven 依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.6</version>
</dependency>

Gradle 依赖:

implementation 'com.alibaba:easyexcel:3.0.6'

2. EasyExcel 核心功能

EasyExcel 提供了读写 Excel 文件的基本功能,我们将通过以下示例来深入了解。

2.1 写入 Excel 文件

使用 EasyExcel 写入 Excel 文件非常简单。首先,我们需要定义一个数据模型,并通过注解配置 Excel 文件的表头。

示例数据模型:

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import java.util.Date;

public class UserData {
    @ExcelProperty("用户ID")
    private Long id;
    
    @ExcelProperty("用户姓名")
    private String name;
    
    @ExcelProperty("创建时间")
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    // Getters and Setters
}

写入 Excel 文件代码示例:

import com.alibaba.excel.EasyExcel;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ExcelWriteExample {
    public static void main(String[] args) {
        String fileName = "user_data.xlsx";
        
        List<UserData> dataList = new ArrayList<>();
        dataList.add(new UserData(1L, "Alice", new Date()));
        dataList.add(new UserData(2L, "Bob", new Date()));

        EasyExcel.write(fileName, UserData.class).sheet("用户数据").doWrite(dataList);
    }
}
2.2 读取 Excel 文件

读取 Excel 文件同样直观。我们需要定义一个监听器来处理每一行的数据。

示例数据模型(与写入示例相同):

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import java.util.Date;

public class UserData {
    @ExcelProperty("用户ID")
    private Long id;
    
    @ExcelProperty("用户姓名")
    private String name;
    
    @ExcelProperty("创建时间")
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    // Getters and Setters
}

读取 Excel 文件代码示例:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;

public class ExcelReadExample {
    public static void main(String[] args) {
        String fileName = "user_data.xlsx";
        
        EasyExcel.read(fileName, UserData.class, new AnalysisEventListener<UserData>() {
            private List<UserData> dataList = new ArrayList<>();
            
            @Override
            public void invoke(UserData data, AnalysisContext context) {
                dataList.add(data);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // Process the dataList or persist it to the database
                dataList.forEach(System.out::println);
            }
        }).sheet().doRead();
    }
}

3. 业务开发示例

让我们通过一个实际的业务场景来展示 EasyExcel 的应用。例如,假设我们需要处理一个用户数据的导入导出功能,其中包括从 Excel 文件中读取用户数据并保存到数据库中,或将数据库中的用户数据导出到 Excel 文件中。

3.1 用户数据导出

我们需要从数据库中获取用户数据,然后将其导出到 Excel 文件中。假设我们有一个用户服务类 UserService 和对应的数据库访问层 UserRepository

用户数据服务:

import java.util.List;

public interface UserService {
    List<UserData> getAllUsers();
}

用户数据实现:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Override
    public List<UserData> getAllUsers() {
        return userRepository.findAll();
    }
}

导出功能实现:

import com.alibaba.excel.EasyExcel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UserDataExporter {

    @Autowired
    private UserService userService;

    public void exportUserData() {
        List<UserData> users = userService.getAllUsers();
        String fileName = "exported_user_data.xlsx";
        EasyExcel.write(fileName, UserData.class).sheet("用户数据").doWrite(users);
    }
}
3.2 用户数据导入

同样,我们需要实现一个从 Excel 文件中读取用户数据并保存到数据库中的功能。

导入功能实现:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.event.AnalysisEventListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UserDataImporter {

    @Autowired
    private UserService userService;

    public void importUserData(String fileName) {
        EasyExcel.read(fileName, UserData.class, new AnalysisEventListener<UserData>() {
            @Override
            public void invoke(UserData userData, AnalysisContext context) {
                // Save user data to the database
                userService.save(userData);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // Optional: Log completion or further processing
            }
        }).sheet().doRead();
    }
}

4. 进阶用法

除了基本的读写功能,EasyExcel 还提供了一些进阶用法,例如支持不同的数据格式、自定义转换器等。

4.1 自定义转换器

我们可以实现自定义转换器来处理特殊的数据格式,例如将日期格式化为特定的字符串格式。

自定义日期格式转换器:

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.DateUtils;
import java.util.Date;

public class CustomDateConverter implements Converter<Date> {

    @Override
    public Class supportJavaTypeKey() {
        return Date.class;
    }

    @Override
    public CellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        // Format the date as a string
        String formattedDate = DateUtils.formatDate(value, "yyyy-MM-dd");
        return new CellData<>(formattedDate);
    }

    @Override
    public Date convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        // Parse the date string back to Date object
        return DateUtils.parseDate(cellData.getStringValue(), "yyyy-MM-dd");
    }
}

在数据模型中使用自定义转换器:

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;

public class UserData {
    @ExcelProperty("用户ID")
    private Long id;

    @ExcelProperty("用户姓名")
    private String name;

    @ExcelProperty("创建时间")
    @DateTimeFormat("yyyy-MM-dd")
    private Date createTime;

    // Getters and Setters
}
4.2 自定义格式

基础概念

在 EasyExcel 中,设置单元格格式主要涉及以下几个类和接口:

  • WriteCellStyle:用于定义写操作中的单元格样式。
  • ReadCellStyle:用于定义读操作中的单元格样式。
  • AbstractCellStyleStrategy:抽象类,通过继承这个类可以实现自定义的单元格样式策略。

自定义单元格格式示例

以下是一个如何设置单元格字体、颜色和边框的示例。我们将创建一个自定义的 AbstractCellStyleStrategy,来定义写入 Excel 文件时的单元格样式。

import com.alibaba.excel.write.style.AbstractCellStyleStrategy;
import com.alibaba.excel.write.style.cell.WriteCellStyle;
import org.apache.poi.ss.usermodel.*;

public class CustomCellStyleStrategy extends AbstractCellStyleStrategy {

    private final WriteCellStyle writeCellStyle;

    public CustomCellStyleStrategy() {
        // 初始化 WriteCellStyle
        this.writeCellStyle = new WriteCellStyle();
        Font font = writeCellStyle.getFont();
        font.setFontName("Arial");
        font.setFontHeightInPoints((short) 12);
        font.setColor(IndexedColors.BLUE.getIndex());

        CellStyle cellStyle = writeCellStyle.getCellStyle();
        cellStyle.setFont(font);
        cellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
    }

    @Override
    protected void initCellStyle(CellStyle cellStyle, CellData cellData) {
        // Apply custom cell style
        cellStyle.cloneStyleFrom(this.writeCellStyle.getCellStyle());
    }
}

使用自定义单元格格式

在编写 Excel 文件时,将自定义单元格格式应用到数据写入的过程中。以下代码演示如何使用 CustomCellStyleStrategy 来设置 Excel 文件的样式。

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;

import java.util.Arrays;
import java.util.List;

public class EasyExcelDemo {
    public static void main(String[] args) {
        // 创建数据
        List<List<String>> data = Arrays.asList(
            Arrays.asList("Name", "Age", "City"),
            Arrays.asList("Alice", "30", "New York"),
            Arrays.asList("Bob", "25", "Los Angeles")
        );

        // 创建 ExcelWriter
        ExcelWriterBuilder writerBuilder = EasyExcel.write("demo.xlsx");
        writerBuilder.registerWriteHandler(new CustomCellStyleStrategy());

        // 创建 Sheet
        WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();

        // 写入数据
        EasyExcel.write("demo.xlsx")
                .registerWriteHandler(new CustomCellStyleStrategy())
                .sheet("Sheet1")
                .doWrite(data);
    }
}

业务开发示例

在实际业务开发中,自定义单元格格式可能用于以下场景:

  • 财务报表:需要突出显示特定的数值或计算结果(例如,利润或亏损)。
  • 数据导出:生成的报告需要特定的格式以便于阅读和分析。
  • 统计报告:数据表格中的不同部分需要不同的样式以区分重要信息。

例如,在财务报表中,可以通过不同颜色突出显示负数和正数。或在销售数据中,通过字体加粗来标记重点销售人员。

public class FinancialReportCellStyleStrategy extends AbstractCellStyleStrategy {

    @Override
    protected void initCellStyle(CellStyle cellStyle, CellData cellData) {
        if (cellData.getStringValue().startsWith("-")) {
            cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
        } else {
            cellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
        }
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来一杯龙舌兰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值