需求1:能够导出1个Excel文件,能够导入一个Excel文件;
需求2:导出的文件,能实现第1行,第123列的合并单元格:也就是会写注册处理器;知道sheet和cell是什么;
需求3:能实现合并的单元格设置单元格宽高,背景颜色,内容居中,字体大小;
需求4:能控制从任意行开始写入,并让要输出的字段居中;
需求5:导出能实现从任意行开始读入;
导出Excel文件
java
<!-- EasyExcel 核心依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.4</version>
</dependency>
java
// 用 @Data 简化 getter/setter(需引入 lombok 依赖,也可手动写)
@Data
@NoArgsConstructor
@AllArgsConstructor
// 表头居中 + 内容居中(核心注解)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER)
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER)
public class UserData {
// @ExcelProperty 注解指定 Excel 列名
@ExcelProperty("用户ID")
private Long id;
@ExcelProperty("姓名")
private String name;
@ExcelProperty("年龄")
private Integer age;
}
java
@RestController
public class ExcelExportController {
@PostMapping("/excelExport")
public void excelExport() throws IOException {
// 1.获取当前时间,作文件名拼接使用
String formattedNow = getFormattedNow();
// 2. 指定生成的 Excel 文件路径和名称
String filePath = "C:\\Users\\59742\\Desktop\\IdeaProjects\\ExcelImportExport\\excelFiles/excel_" + formattedNow + ".xlsx";
// 3. 准备要写入的数据
List<UserData> dataList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
UserData user = new UserData();
user.setId((long) i);
user.setName("用户" + i);
user.setAge(20 + i);
dataList.add(user);
}
// 4.写入Excel文件
EasyExcel.write(filePath, UserData.class)
.sheet("用户信息表")
.relativeHeadRowIndex(1) // 默认为0行,这里从第一行开始写入
// 有什么要对表格进行的操作,可以使用注册自定义的处理器
.registerWriteHandler(new MergeCellWriteHandler())//合并单元格
.doWrite(dataList);
System.out.println("Excel 文件生成成功!路径为:" + filePath);
}
/**
* 获取当前时间,格式化输出
* @return
*/
private static String getFormattedNow() {
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
// 格式化输出(推荐使用 DateTimeFormatter,取代 SimpleDateFormat)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss");
return now.format(formatter);
}
}
java
/**
* 自定义单元格合并处理器(核心)
* 实现 SheetWriteHandler接口,拦截单元格写入事件
*/
public class MergeCellWriteHandler implements SheetWriteHandler {
@Override
public void afterSheetCreate(SheetWriteHandlerContext context) {
// 1.想操作excel表,第一步是拿到表里的sheet
Sheet sheet = context.getWriteSheetHolder().getSheet();
// 2.拿到sheet,然后操作里面的每一个格子(CELL),然后调用合并单元格方法:addMergedRegion(),然后new一个范围性的cellRangeAddress()
// 在 sheet 创建后立即合并 A1:C1(第0行,列0~2)
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 2));
sheet.createRow(0)
.createCell(0)
.setCellValue("提示:姓名和年龄是必填的");
// 样式设置
// 1.设置合并单元格的宽和高
sheet.setColumnWidth(0, 30 * 256);
sheet.setColumnWidth(1, 30 * 256);
sheet.setColumnWidth(2, 30 * 256);
sheet.getRow(0).setHeightInPoints(200);
// 设置单元格的背景颜色
// 1. 先创建样式对象并设置属性(必须分步,无法纯链式)
CellStyle style = sheet.getWorkbook().createCellStyle();
style.setFillForegroundColor(IndexedColors.BRIGHT_GREEN1.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 2. 设置单元格内容居中
style.setAlignment(HorizontalAlignment.CENTER); // 水平居中
style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
// 3. 设置单元格字体大小
Font font = sheet.getWorkbook().createFont();
font.setFontHeightInPoints((short) 32);
style.setFont(font);
// 4. 给单元格绑定样式
sheet.getRow(0).getCell(0).setCellStyle(style);
}
}

导入Excel文件
java
@RestController
public class ImportExcelController {
@PostMapping("/excelImport")
public void excelImport(MultipartFile file) throws IOException {
System.out.println("开始导入");
ExcelImportListener listener = new ExcelImportListener();
// 核心:读取 Excel
EasyExcel.read(file.getInputStream(), UserData.class, listener)
.sheet("用户信息表") // 指定要读取的工作表
.headRowNumber(2) // 这里代表索引2,第3行开始读取
.doRead(); // 执行读取
// 获取读取到的数据并打印
System.out.println("最终读取到的数据:" + listener.getDataList());
}
}
成功读取到数据


- 每读取一行,调用invoke一次!!!!
java
// 加Slf4j方便打印日志(也可以用System.out)
@Slf4j
public class ExcelImportListener extends AnalysisEventListener<UserData> {
// 存储读取到的所有数据(适合小文件,大文件建议批量处理)
private List<UserData> dataList = new ArrayList<>();
/**
* 核心方法:每读取一行Excel数据,就会调用这个方法
* @param userData 一行数据对应的实体类对象
* @param context 读取上下文(包含sheet、行号等信息)
*/
@Override
public void invoke(UserData userData, AnalysisContext context) {
log.info("读取到第{}行数据:{}", context.readRowHolder().getRowIndex(), userData);
// 2. 将数据加入集合
dataList.add(userData);
}
/**
* 所有数据读取完成后调用的方法
* 适合做最终处理(比如批量入库、数据汇总)
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("Excel读取完成!共读取{}行有效数据", dataList.size());
System.out.println("dataList = " + dataList);
// 这里可以写后续逻辑:比如调用service批量保存到数据库
// userService.batchSave(dataList);
}
// 提供getter方法,方便外部获取读取到的数据
public List<UserData> getDataList() {
return dataList;
}
}