文章目录
- EasyExcel
- 1. EasyExcel 简介
- 1.1 主要特点
- 1.2 依赖配置
- 2. EasyExcel 核心功能
- 2.1 写入 Excel 文件
- 2.2 读取 Excel 文件
- 3. 业务开发示例
- 3.1 用户数据导出
- 3.2 用户数据导入
- 4. 进阶用法
- 4.1 自定义转换器
- 4.2 自定义格式
更多相关内容可查看
附官网地址: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);
}
}