headRowNumber(1):从第几行开始读
准备工作
导入依赖
<!--easyexcel--> <dependency> <groupId>com.alibaba</groupId>x <artifactId>easyexcel</artifactId> <version>2.2.6</version> </dependency> <!--文件上传--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
创建实体类
@HeadRowHeight():设置导出的Excle表格标题的行高
@ExcelProperty():对当前列的操作
value:设置列的名字
value = {"value1","value2"}:一级标题,二级标题
index = 2:这个字段放在第几列,默认从0开始
@ExcelIgnore:不导入导出这个字段
@Data @AllArgsConstructor @NoArgsConstructor @TableName("user") @HeadRowHeight(30) // 标题行高 public class User { /** * @ExcelProperty * value:列名称 * index:写:写内容到第几列,读:第几列的内容放到这个字段 * {}:给头在加一个头,所有都加,就会合并 * * @ExcelIgnore * 导入或导出时候,不要这个字段 * */ @TableId(value = "id", type = IdType.AUTO) @ExcelProperty(value = {"用户信息表","ID"},index = 5) @ExcelIgnore private Integer id; @ExcelProperty(value = {"用户信息表","姓名"},index = 1) @ColumnWidth(20) private String name; @ExcelProperty(value = {"用户信息表","年龄"},index = 2) private Integer age; @ExcelProperty(value = {"用户信息表","性别"},index = 3) private Integer sex; @ExcelProperty(value = {"用户信息表","日期"},index = 4) @ColumnWidth(20) private Date dateTime; }
第二个实体类
package com.zsh.esayexcel.domain.po; @Data @AllArgsConstructor @NoArgsConstructor public class UserVO { private Integer sum; private Integer avg; }
Mapper
package com.zsh.esayexcel.mapper; /** * <p> * Mapper 接口 * </p> * * @author KaiLangJiaoJiao * @since 2024-02-12 */ @Mapper public interface UserMapper extends BaseMapper<User> { }
Service
package com.zsh.esayexcel.service; /** * <p> * 服务类 * </p> * * @author KaiLangJiaoJiao * @since 2024-02-12 */ public interface IUserService extends IService<User> { }
ServiceImpl
package com.zsh.esayexcel.service.impl; /** * <p> * 服务实现类 * </p> * * @author KaiLangJiaoJiao * @since 2024-02-12 */ @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { }
Controller
package com.zsh.esayexcel.controller; /** * <p> * 前端控制器 * </p> * * @author KaiLangJiaoJiao * @since 2024-02-12 */ @RestController @RequestMapping("/user") public class UserController { }
监听器类
创建listener包
UserListener
package com.zsh.esayexcel.listener; /** * 读取文档的监听器类 */ public class UserListener extends AnalysisEventListener<User> { /** * 读监听器,每读一行内容,都会调用一次该对象的invoke,在invoke可以操作使用读取到的数据 * @param user * @param analysisContext */ @Override public void invoke(User user, AnalysisContext analysisContext) { System.out.println("user = " + user); } /** * 读取完整个文档之后调用的方法 * @param analysisContext */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }
WebUserListener
package com.zsh.esayexcel.listener; @Scope("prototype") // 官方要求,这个类需要是多例对象,不能是单例 public class WebUserListener extends AnalysisEventListener<User> { // @Autowired // private IUserService userService; List<User> userList = new ArrayList<>(); @Override public void invoke(User user, AnalysisContext analysisContext) { userList.add(user); // 判断条数为5时添加一次 if (userList.size() % 5 == 0) { IUserService userService = new UserServiceImpl(); // 添加 userService.saveBatch(userList); // 添加完清空数组 userList.clear(); } } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { // 剩下数据不足5条时添加 if (userList.size() != 0) { IUserService userService = new UserServiceImpl(); // 添加 userService.saveBatch(userList); // 添加完清空数组 userList.clear(); } } }
导入测试
这是一个Test测试类
package com.zsh.esayexcel; @SpringBootTest public class ExcelTest { /** * 读excel */ @Test public void test(){ /** * pathName:要读取的文件路径 * * head:文件中每一行数据要存储到的实体类行的class * * readListener:读监听器,每读一行内容,都会调用一次该对象的invoke,在invoke可以操作使用读取到的数据 */ // 获得一个工作簿对象 ExcelReaderBuilder readWorkBook = EasyExcel.read("C:\\Users\\开朗觉觉\\Desktop\\用户表.xlsx", User.class, new UserListener()); // 获得工作簿对象 ExcelReaderSheetBuilder sheet = readWorkBook.sheet(); /** * headRowNumber() * 从第几行开始读,默认是1 */ // 读取工作表中内容 sheet.headRowNumber(1).doRead(); } }
导出测试
这是一个测试类
package com.zsh.esayexcel; @SpringBootTest public class ExcelTest { /** * 写excel */ @Test public void test2(){ // 工作簿对象 // .xml会直接放到Module里 ExcelWriterBuilder writeWorkBook = EasyExcel.write("学生表的写操作.xlsx", User.class); // 工作表对象 ExcelWriterSheetBuilder sheet = writeWorkBook.sheet(); // 准备数据 List<User> userList = new ArrayList<>(); for (int i = 0; i < 5; i++) { User user = new User(i,"张三"+i,10,2,new Date()); userList.add(user); } // 写 sheet.doWrite(userList); } }
上传Excel
package com.zsh.esayexcel.controller; /** * <p> * 前端控制器 * </p> * * @author KaiLangJiaoJiao * @since 2024-02-12 */ @RestController @RequestMapping("/user") public class UserController { @Autowired private IUserService userService; /** * 测试 * @return */ @GetMapping("/test") private String test(){ return "ok"; } /** * Excel导入 * @param uploadExcel * @return */ @PostMapping("/read") public String readExcel(@RequestBody MultipartFile uploadExcel){ try { // 工作簿 ExcelReaderBuilder readWorkBook = EasyExcel.read(uploadExcel.getInputStream(), User.class, new WebUserListener()); // 工作表 ExcelReaderSheetBuilder sheet = readWorkBook.sheet(); // 读 sheet.doRead(); return "success"; } catch (IOException e) { e.printStackTrace(); return "fail"; } } }
下载Excel
package com.zsh.esayexcel.controller; /** * <p> * 前端控制器 * </p> * * @author KaiLangJiaoJiao * @since 2024-02-12 */ @RestController @RequestMapping("/user") public class UserController { @Autowired private IUserService userService; /** * Excel导出 * @param response */ @GetMapping("/write") @ResponseBody public void writeExcel(HttpServletResponse response) throws IOException { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); // 防止中文乱码 String fileName = URLEncoder.encode("学生表测试", "UTF-8"); response.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + fileName + ".xlsx"); // 收集要写的数据装进一个工作簿中 ServletOutputStream outputStream = response.getOutputStream(); // 获取工作簿 ExcelWriterBuilder writeWrokBook = EasyExcel.write(outputStream, User.class); // 获取工作表 ExcelWriterSheetBuilder sheet = writeWrokBook.sheet(); // 获取数据 List<User> userList = userService.list(null); // 写 sheet.doWrite(userList); } }
混合导出+模板导出
模板设计
编辑
{.xxxx}:填充多行
{xxxx}:填充单行
代码开发
package com.zsh.esayexcel; @SpringBootTest public class ExcelTest { @Autowired private IUserService userService; /** * 混合导出 */ @Test public void test3(){ // 准备模板 String tempalte = "用户表模板.xlsx"; /** * withTemplate() * 使用模板创建表 */ // 创建一个工作簿对象 ExcelWriter workBook = EasyExcel.write("用户信息表.xlsx", User.class).withTemplate(tempalte).build(); // 创建工作表对象 WriteSheet sheet = EasyExcel.writerSheet().build(); // 准备数据 // IUserService userService = new UserServiceImpl(); List<User> userList = userService.list(null); UserVO userVO = new UserVO(); // 总人数 userVO.setSum(userList.size()); // 年龄总和 Integer agesum = userList.stream() .map(user -> user.getAge()) .reduce(0, (result, element) -> result + element); // 平均年龄 userVO.setAvg(agesum / userList.size()); // 数据填充 FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();// 因为多组填充的数据不确定,需要在多组数据填充完之后另起一行 // 多组填充 workBook.fill(userList,fillConfig,sheet); // 单组填充 workBook.fill(userVO,sheet); // 关闭流 workBook.finish(); } }