EasyExcel篇

快速入门

EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网

1.引入依赖

xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>4.0.3</version>
</dependency>

2.实体类映射

  • @ExcelIgnore:不映射此属性

  • @ExcelProperty(value=列头名, index=列排序:eg:value="姓名" index=2 : 将姓名的列头设置在Excel表格的第三列

  • @ExcelProperty({"主题","列头名"}):多级主题

    1. 第一个参数为一级主题(第一行), 第二个参数为二级主题(第二行)
    2. 如果一级主题名称相同,那么他们会合并单元格
java 复制代码
public class User implements Serializable {
    @ExcelProperty(value = {"基本信息","用户ID"},index = 0)
    private Long id;

    @ExcelProperty(value = {"基本信息","用户名"},index = 1)
    private String name;

    @ExcelProperty(value = "创建时间",index = 2)
    private Long time;
}

3.excel下载

java 复制代码
@RestController
@RequestMapping("/api/excel")
public class ExcelController {
    
    @Autowired
    private UserService userService;
    
    /**
     * 导出Excel给前端
     */
    @GetMapping("/export")
    public void exportUsers(HttpServletResponse response) throws IOException {
        // 设置响应头,响应体类型为excel
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("用户数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        
        // 查询数据
        List<User> userList = userService.list();
        
        // 写入Excel
        EasyExcel.write(response.getOutputStream(), User.class)
                .sheet("用户数据")
                .doWrite(userList);
    }
}

4.excel上传

java 复制代码
@RestController
@RequestMapping("/api/excel")
public class ExcelController {
    
    @Autowired
    private UserDataListener userDataListener;
    
    /**
     * 从Excel导入用户数据
     */
    @PostMapping("/import")
    public String importUsers(@RequestParam("file") MultipartFile file) throws IOException {
        String filename = Paths.get(file.getOriginalFilename()).getFileName().toString();
        Path targetPath = Paths.get("excel", filename);
        Files.copy(file.getInputStream(),targetPath);
        return "OK";
    }
}

5.写操作

java 复制代码
public class Main {
    /**
     * 导出Excel到指定文件
     */
    public static void main(String[] args) throws IOException {
        //准备数据
        List<User> userDataList = new ArrayList<>();
        userDataList.add(new User(3L, "张三", Instant.now().toEpochMilli()));
        userDataList.add(new User(4L, "李四", Instant.now().toEpochMilli()));
        //要排除的数据
        HashSet<String> set = new HashSet<>();
        excludeColumnSet.add("time");
        // 写入Excel
        String fileName = "excel/user.xlsx";
        //1 创建ExcelWriter对象,排除time字段
        try (ExcelWriter writer = EasyExcel.write(fileName, User.class).excludeColumnFieldNames(set).build()) {
            //2 创建Sheet(可以指定sheetNo和sheetName)
            WriteSheet writeSheet1 = EasyExcel.writerSheet(0, "用户信息表1").build();
            WriteSheet writeSheet2 = EasyExcel.writerSheet(1, "用户信息表2").build();
            //3 开始写入数据
            writer.write(userDataList, writeSheet1);
            writer.write(userDataList, writeSheet2);
            //4 关闭流
            //writer.finish();
        }
        
        // 快速写,排除time字段,适用于单sheet、一次性写,自动关闭流
        EasyExcel.write(fileName, User.class)
                .excludeColumnFieldNames(set)
                .sheet("用户信息")
                .doWrite(userDataList);
    }
}

4.读操作

java 复制代码
@Slf4j
public class Main {

    public static void main(String[] args) throws IOException {
        String fileName= "excel/wyh.xlsx";
        //1.监听器,用于设置处理数据的方式,不同的sheet可以创建多个对应监听器,这里演示统一监听器
        AnalysisEventListener<User> listener = new AnalysisEventListener<User>() {
            @Override
            public void invoke(User user, AnalysisContext context) {
                // 每解析一条数据被调用一次
                System.out.println("解析的数据为: " + user);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 数据解析完成之后被调用
                System.out.println("数据解析完成......");
            }
        };
        //2.创建Reader对象
        try(ExcelReader reader = EasyExcel.read(fileName, User.class, listener).build()){
            //3.指定sheet对象,这里指定读前二个sheet
            ReadSheet sheet1 = EasyExcel.readSheet(0).build();
            ReadSheet sheet2 = EasyExcel.readSheet(1).build();
            //4.开始读取数据
            reader.read(sheet1,sheet2);
            // 关闭流
            //reader.finish(); 
        }
       
        // doRead()快速异步读,适用于单sheet、一次性读,自动关闭流
        EasyExcel.read(fileName, User.class,listener).sheet().doRead();
        // 小数据量可以使用doReadSync()同步读还可以将读取的数据以集合保存
        List<Object> list = EasyExcel.read(fileName, User.class, listener).sheet().doReadSync();
    }
}

高级功能

追加写

  • EasyExcel默认每次开启流都会覆盖原有数据

  • 实现追加写的方式

    1. 指定 WriteSheetstartRow 参数,从指定行开始写入数据
    2. 先读取原sheet的所有数据,再合并为新数据
java 复制代码
public class AppendToExcel {
    public static void main(String[] args) {
        String fileName = "existing_file.xlsx";
        // 1. 准备要追加的数据(可以是 List<Map> 或 List<JavaBean>)
        List<Map<Integer, String>> newData = new ArrayList<>();
        Map<Integer, String> row1 = new HashMap<>();
        row1.put(0, "新增数据1");
        row1.put(1, "新增数据2");
        newData.add(row1);
        // 2. 创建 ExcelWriter(追加模式)
        try(ExcelWriter excelWriter = EasyExcel.write(fileName).build()){
            // 3. 获取 Sheet(假设追加到第一个 Sheet)
            WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
            // 4. 计算已有数据的行数(例如,已有 5 行数据,从第 5 行开始追加)
            int existingRowCount = EasyExcel.read(fileName)
                .sheet()
                .doReadSync().size();  // 读取所有数据,返回行数
            writeSheet.setStartRow(existingRowCount); // 设置起始行
            // 5. 执行追加写入
        	excelWriter.write(newData, writeSheet);
            // 6. 关闭 ExcelWriter
            //excelWriter.finish();          
        }
    }
}

遍历sheet读

java 复制代码
String fileName = "multi_sheet.xlsx";
AnalysisEventListener<User> listener = new AnalysisEventListener<User>() {
    @Override
    public void invoke(User user, AnalysisContext context) {
        // 每解析一条数据被调用一次
        System.out.println("解析的数据为: " + user);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 数据解析完成之后被调用
        System.out.println("数据解析完成......");
    }
};
try(ExcelReader excelReader = EasyExcel.read(fileName).build()) {
    // 获取所有Sheet
    List<ReadSheet> sheets = excelReader.excelExecutor().sheetList();
    for (ReadSheet sheet : sheets) {
        System.out.println("开始读取Sheet: " + sheet.getSheetName());
        excelReader.read(sheet, DemoData.class, listener);
    }
} 
相关推荐
老华带你飞几秒前
工会管理|基于springboot 工会管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
自在极意功。几秒前
MyBatis配置文件详解:environments、transactionManager与dataSource全面解析
java·数据库·tomcat·mybatis
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ5 分钟前
配置springdoc swagger开关
java
Echo flower8 分钟前
Spring Boot WebFlux 实现流式数据传输与断点续传
java·spring boot·后端
没有bug.的程序员14 分钟前
微服务中的数据一致性困局
java·jvm·微服务·架构·wpf·电商
鸽鸽程序猿19 分钟前
【Redis】Java客户端使用Redis
java·redis·github
悦悦子a啊19 分钟前
使用 Java 集合类中的 LinkedList 模拟栈以此判断字符串是否是回文
java·开发语言
Lucky小小吴21 分钟前
java代码审计入门篇——Hello-Java-Sec(完结)
java·开发语言
一个想打拳的程序员22 分钟前
无需复杂配置!用%20docker-webtop%20打造跨设备通用%20Linux%20桌面,加载cpolar远程访问就这么简单
java·人工智能·docker·容器
一起养小猫25 分钟前
LeetCode100天Day2-验证回文串与接雨水
java·leetcode