2026.3.20 用EasyExcel实现excel报表的导入与导出
1.在自己模块创建一个实体类
@Data
public class User {
/**
* value表示该属性对应的表头名称, index表示该属性所处的列的位置
*/
//该注解能建立Java对象与表格列之间的映射关系
@ExcelProperty(value = "编号", index = 0)
private Integer id;
@ExcelProperty(value = "姓名", index = 1)
private String name;
@ExcelProperty(value = "电话", index = 2)
private String phone;
}
2.在组件扫描类中,扫描excel组件
@Configuration
@ComponentScan({
"com.zeroone.star.project.components.easyexcel",
})
public class UseCusComponents {
}
组件源码如下,了解即可
@Component
public class EasyExcelComponent {
/**
* 定义每个页签存储的数据量
*/
private static final int MAX_COUNT_PER_SHEET = 5000;
/**
* 导出到磁盘中
* @param path Excel 存储路径
* @param sheetName sheet名称
* @param clazz 存储的数据类型
* @param dataList 存储数据集合
* @param <T> 生成元素实体类类型
*/
public <T> void export(String path, String sheetName, Class<T> clazz, List<T> dataList) {
EasyExcel.write(path, clazz).sheet(sheetName).doWrite(dataList);
}
/**
* 解析Excel
* @param path 解析的Excel的路径
* @param sheetName 解析的Excel的sheet名称
* @param clazz 存储的数据类型
* @param <T> 解析元素实体类类型
* @return 解析后的数据集合
*/
public <T> List<T> parseExcel(String path, String sheetName, Class<T> clazz) {
ExcelReadListener<T> listener = new ExcelReadListener<>();
EasyExcel.read(path, clazz, listener).sheet(sheetName).doRead();
return listener.getDataList();
}
/**
* 导出到输出流
* @param sheetName sheet名称
* @param os 输出流
* @param clazz 导出数据类型
* @param dataList 导出的数据集
* @param <T> 生成元素实体类类型
* @throws IOException IO异常
*/
public <T> void export(String sheetName, OutputStream os, Class<T> clazz, List<T> dataList) throws IOException {
ExcelWriterBuilder builder = EasyExcel.write(os, clazz);
ExcelWriter writer = builder.build();
//计算总页数
int sheetCount = dataList.size() / MAX_COUNT_PER_SHEET;
sheetCount = dataList.size() % MAX_COUNT_PER_SHEET == 0 ? sheetCount : sheetCount + 1;
//循环构建分页
for (int i = 0; i < sheetCount; i++) {
//创建一个页签
WriteSheet sheet = new WriteSheet();
sheet.setSheetNo(i);
sheet.setSheetName(sheetName + (i + 1));
//设置数据起始位置
int start = i * MAX_COUNT_PER_SHEET;
int end = (i + 1) * MAX_COUNT_PER_SHEET;
end = Math.min(end, dataList.size());
//写入数据到页签
writer.write(dataList.subList(start, end), sheet);
}
writer.finish();
os.close();
}
/**
* 解析Excel
* @param inputStream 解析的Excel的输入流
* @param sheetName 解析的Excel的sheet名称
* @param clazz 存储的数据类型
* @param <T> 解析元素实体类类型
* @return 解析后的数据集合
*/
public <T> List<T> parseExcel(InputStream inputStream, String sheetName, Class<T> clazz) {
ExcelReadListener<T> listener = new ExcelReadListener<>();
EasyExcel.read(inputStream, clazz, listener).sheet(sheetName).doRead();
return listener.getDataList();
}
}
3.创建测试类
@Controller
@RequestMapping("/excel")
@Api(tags = "excel")
public class ExcelController {
//用以创建测试数据,在真实场景中,数据应从数据库中查询
private List<User> list;
@Resource
EasyExcelComponent excel;
}
1.创建测试数据
//用以声明该方法在依赖注入完成后立刻执行,能保证在运行其他方法之前list集合已被初始化
@PostConstruct
public void initData() {
list = new ArrayList<>();
// 测试数据
for (int i = 1; i < 11; i++) {
User user = new User();
user.setId(i);
user.setName("控制器用户" + i);
user.setPhone("1234567890" + i);
list.add(user);
}
}
2.导出Excel文件供用户下载
@SneakyThrows
//
@GetMapping(value = "export", produces = "application/octet-stream")
@ApiOperation("导出Excel")
public ResponseEntity<byte[]> exportExcel() {
// 导出到文件流中
ByteArrayOutputStream out = new ByteArrayOutputStream();
excel.export("test", out, User.class, list);
// 响应文件
HttpHeaders headers = new HttpHeaders();
String filename = "rep-" + DateTime.now().toString("yyyyMMddHHmmssS") + ".xlsx";
headers.setContentDispositionFormData("attachment", filename);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
byte[] bytes = out.toByteArray();
out.close();
return new ResponseEntity<>(bytes, headers, HttpStatus.CREATED);
}
3.导入Excel供管理人员业务调用
@SneakyThrows
@PostMapping("/import")
@ApiOperation("导入Excel")
@ResponseBody
public JsonVO<String> importExcel(MultipartFile file) {
// 解析Excel
InputStream input = file.getInputStream();
List<User> list = excel.parseExcel(input, "test1", User.class);
// 保存到数据库的业务调用,使用打印测试解析效果
if (list.size() > 0) {
list.forEach(System.out::println);
return JsonVO.success("导入成功");
}
return JsonVO.fail("导入失败");
}
}