文章目录
- 前言
- 一、创建项目
- 二、核心代码
- 2.1 org.feng.bean包中的类
- 2.1.1 Sex类
- 2.1.2 User类
 
- 2.2 org.feng.constant包中的类
- 2.2.1 Constant类
 
- 2.3 org.feng.converter包中的类
- 2.3.1 ListDataConverter类
- 2.3.2 SexConverter类
 
- 2.4 org.feng.listener包中的类
- 2.4.1 UserReadListener类
 
- 2.5 org.feng.client包中的类
- 2.6.1 ExcelClient 类
 
 
- 三、测试
- 3.1 表格写入后的内容
- 3.2 控制台的日志
 
前言
我们的业务场景中可能经常遇到需要保存数据到表格,或者从表格读取到数据,随后做一些操作。
本文将在Spring项目中做写入和读取操作。
一、创建项目
项目结构如下:
 
 其中test.xlsx文件是一个新创建的表格文件,里边是空的。
 执行操作是,先给该表格写入内容,随后从中读取。
引入Maven依赖:
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.28</version>
            <optional>true</optional>
        </dependency>
二、核心代码
2.1 org.feng.bean包中的类
2.1.1 Sex类
package org.feng.bean;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * 性别枚举
 */
@Getter
@AllArgsConstructor
public enum Sex {
    /**
     * 男
     */
    MALE(1),
    /**
     * 女
     */
    FEMALE(0);
    /**
     * 性别标识
     */
    private final Integer sexFlag;
}
2.1.2 User类
需要使用EasyExcel中的注解进行标注属性。
 集合,枚举等类型的属性还需要设置转换器。
package org.feng.bean;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Data;
import org.feng.constant.Constant;
import org.feng.converter.ListDataConverter;
import org.feng.converter.SexConvert;
import java.time.LocalDateTime;
import java.util.List;
/**
 * 用户
 *
 * @author fengjinsong
 * @date 2023-06-30 14:35:15
 * @version: 1.0
 */
@Data
public class User {
    @ExcelProperty(value = "编号", index = 0)
    private String id;
    @ExcelProperty(value = "姓名", index = 1)
    private String name;
    @ExcelProperty(value = "年龄", index = 2)
    private Integer age;
    @ExcelProperty(value = "性别", index = 3, converter = SexConvert.class)
    private Sex sex;
    @DateTimeFormat(Constant.TIME_FORMAT)
    @ExcelProperty(value = "生日", index = 4)
    private LocalDateTime birthday;
    @ExcelProperty(value = "电话", index = 5)
    private String phone;
    @ExcelProperty(value = "爱好", index = 6, converter = ListDataConverter.class)
    private List<String> hobbies;
}
2.2 org.feng.constant包中的类
2.2.1 Constant类
package org.feng.constant;
/**
 * 常量类
 *
 * @author fengjinsong
 * @date 2023-06-30 14:55:22
 * @version: 1.0
 */
public interface Constant {
    /**
     * 时间格式:写入到excel时的格式
     */
    String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
}
2.3 org.feng.converter包中的类
这里定义的是转换器,目前需要转换的有集合类型,枚举类型。
2.3.1 ListDataConverter类
package org.feng.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import java.util.List;
/**
 * list数据转字符串的转换器
 *
 * @author fengjinsong
 * @date 2023-06-30 14:57:50
 * @version: 1.0
 */
public class ListDataConverter implements Converter<List<String>> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return List.class;
    }
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
    @Override
    public WriteCellData<String> convertToExcelData(List<String> value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new WriteCellData<>(String.valueOf(value));
    }
    @Override
    public List<String> convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        String stringValue = cellData.getStringValue();
        // 去除中括号,并按照逗号切割
        String[] split = stringValue.substring(1, stringValue.length() - 1).split(", ");
        return List.of(split);
    }
}
2.3.2 SexConverter类
package org.feng.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import org.feng.bean.Sex;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
/**
 * 性别转换
 *
 * @author fengjinsong
 * @date 2023-06-30 15:13:57
 * @version: 1.0
 */
public class SexConvert implements Converter<Sex> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return Sex.class;
    }
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.NUMBER;
    }
    @Override
    public WriteCellData<BigDecimal> convertToExcelData(Sex value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new WriteCellData<>(BigDecimal.valueOf(value.getSexFlag()).setScale(0, RoundingMode.HALF_UP));
    }
    @Override
    public Sex convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        int sexFlag = cellData.getNumberValue().intValue();
        return Arrays.stream(Sex.values())
                .filter(sex -> sex.getSexFlag().equals(sexFlag))
                .findAny()
                .orElse(Sex.MALE);
    }
}
2.4 org.feng.listener包中的类
2.4.1 UserReadListener类
package org.feng.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import lombok.extern.slf4j.Slf4j;
import org.feng.bean.User;
/**
 * 对读表格时进行监听
 *
 * @author fengjinsong
 * @date 2023-06-30 15:59:01
 * @version: 1.0
 */
@Slf4j
public class UserReadListener implements ReadListener<User> {
    @Override
    public void invoke(User data, AnalysisContext context) {
        log.info("正在读取User数据的编号是:{}", data.getId());
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("表格读取完毕!");
    }
}
2.5 org.feng.client包中的类
也是执行的位置
2.6.1 ExcelClient 类
package org.feng.client;
import com.alibaba.excel.EasyExcel;
import org.feng.bean.Sex;
import org.feng.bean.User;
import org.feng.listener.UserReadListener;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
 * 执行读、写表格
 *
 * @author fengjinsong
 * @date 2023-06-30 15:18:25
 * @version: 1.0
 */
public class ExcelClient {
    public static void main(String[] args) throws FileNotFoundException {
        writeUser();
        readUser();
    }
    public static void readUser() throws FileNotFoundException {
        File file = ResourceUtils.getFile("classpath:excels/test.xlsx");
        List<User> users = EasyExcel.read(file, new UserReadListener())
                .head(User.class)
                .doReadAllSync();
        // 打印结果
        users.forEach(System.out::println);
    }
    public static void writeUser() throws FileNotFoundException {
        File file = ResourceUtils.getFile("classpath:excels/test.xlsx");
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            User user = new User();
            users.add(user);
            user.setAge(ThreadLocalRandom.current().nextInt(18, 40));
            user.setName("冯" + i);
            user.setSex(i % 2 == 0 ? Sex.FEMALE : Sex.MALE);
            user.setId(String.valueOf(i));
            user.setPhone("1811243556" + i);
            user.setBirthday(LocalDateTime.now());
            user.setHobbies(List.of("唱", "跳", "rap"));
        }
        EasyExcel.write(file, User.class)
                .sheet("用户信息")
                .doWrite(users);
    }
}
三、测试
3.1 表格写入后的内容

3.2 控制台的日志
16:24:19.543 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:0
16:24:19.545 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:1
16:24:19.546 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:2
16:24:19.547 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:3
16:24:19.548 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:4
16:24:19.549 [main] INFO org.feng.listener.UserReadListener - 表格读取完毕!
User(id=0, name=冯0, age=35, sex=FEMALE, birthday=2023-06-30T16:24:18, phone=18112435560, hobbies=[唱, 跳, rap])
User(id=1, name=冯1, age=26, sex=MALE, birthday=2023-06-30T16:24:18, phone=18112435561, hobbies=[唱, 跳, rap])
User(id=2, name=冯2, age=19, sex=FEMALE, birthday=2023-06-30T16:24:18, phone=18112435562, hobbies=[唱, 跳, rap])
User(id=3, name=冯3, age=20, sex=MALE, birthday=2023-06-30T16:24:18, phone=18112435563, hobbies=[唱, 跳, rap])
User(id=4, name=冯4, age=36, sex=FEMALE, birthday=2023-06-30T16:24:18, phone=18112435564, hobbies=[唱, 跳, rap])


















