导入导出Excel

一、Springboot + Easyexcel读取写入数据,多头行数,多sheet,复杂表头简单实现

1. 导入依赖,阿里的easyexcel插件

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

创建一个用来 读取 excel的实体类

实体类的属性可以用

  • @ExcelProperty(index = 0),index=0,找的是上图 A列(第一列)

  • @ExcelProperty(value = "标号")

两种都可以用,但是不要两个一起用

实体类:

实体类中可以使用@DateFormat(阿里包下的)注解:

要使用String类型来接收数据才有用

复制代码
@Data 
public class TemplateEntity {

    @ExcelProperty("标号")
    private Integer label;

    @ExcelProperty("字符串")
    private String str;

    @ExcelProperty("数字")
    private Integer num;
 	
    @ExcelProperty("时间")
    // 这里需要用string接收才会格式化
    @DateTimeFormat("yyyy-MM-dd")
    private String date;
    
}
------------------------------------------------

定义一个 监听类:

复制代码
public class TemplateListener extends AnalysisEventListener<TemplateEntity> {

    private List<TemplateEntity> list = new ArrayList<>();

    // 一条一条读取数据,全部添加到list集合里
    @Override
    public void invoke(TemplateEntity data, AnalysisContext analysisContext) {
        list.add(data);
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {}

    public List<TemplateEntity> getData() {
        return list;
    }
}
service:
复制代码
public interface TemplateService {

    /**
     * 导入excel
     */
    Result importExcel(MultipartFile file) throws IOException;
}

@Service
public class TemplateServiceImpl implements TemplateService {
    @Override
    public Result importExcel(MultipartFile file) throws IOException{
        List<TemplateEntity> entities = getTemplateEntities(file);
        // 处理数据
        System.out.println(entities);
        return Result.success(entities);
    }
    // 读取 excel 数据
    private List<TemplateEntity> getTemplateEntities(MultipartFile file) throws IOException {
        TemplateListener listener = new TemplateListener();	// 定义的 listener
        EasyExcel.read(file.getInputStream(), TemplateEntity.class, listener).sheet().doRead();
        
        // 返回 所有数据
        return listener.getData();
    }
}

Controller 上传文件接口

复制代码
@RestController
@RequestMapping("/sys")
public class TemplateController {

    @Autowired
    private TemplateService templateService;

    @RequestMapping("/import")
    public Result importData(@RequestPart("file") MultipartFile file) throws IOException{
        return templateService.importExcel(file);
    }
}

Postman测试

复制代码
{
    "code": 200,
    "msg": "处理成功",
    "data": [
        {
            "label": 1,
            "str": "a",
            "num": 20
        },
        {
            "label": 2,
            "str": "b",
            "num": 30
        },
        {
            "label": 3,
            "str": "c",
            "num": 40
        },
       ...
}
------------------------------------------------

多sheet

两sheet表头数据不一致

这里为了演示效果,sheet1和sheet3是不同表头的,sheet2目前是空的数据表

思路:需要定义各自的excel接收数据的实体类,然后创建各自的监听类,重写方法

读取时,指定不同的监听类,excel接收数据的实体类对象,然后放入map中返回即可

具体实现

实体类

TemplateEntity接收sheet1

复制代码
@Data
public class TemplateEntity {
    @ExcelProperty("标号")
    private Integer label;
    @ExcelProperty("字符串")
    private String str;
    @ExcelProperty("数字")
    private Integer num;
    @ExcelProperty(value = "时间")
    @DateTimeFormat("yyyy-MM-dd")
    private String date;
}

OtherTemplateEntity接收sheet3

复制代码
@Data
public class OtherTemplateEntity {
    @ExcelProperty("标号")
    private String label;
    @ExcelProperty("名称")
    private String name;
    @ExcelProperty("类型")
    private String type;
    @ExcelProperty(value = "时间")
    @DateTimeFormat("yyyy-MM-dd")
    private String date;
}
监听类

同上,只是写两个各自的

controller层
复制代码
@PostMapping("/importMany")
public R importMany(@RequestPart("file") MultipartFile file) throws IOException {
    return easyExcelService.importManyExcel(file);
}
service实现层
复制代码
public R importManyExcel(MultipartFile file) throws IOException {
    Map<String, Object> map = getTemplateEntitiesMany(file);
    List<TemplateEntity> data1 = (List<TemplateEntity>) map.get("data1");
    List<OtherTemplateEntity> data2 = (List<OtherTemplateEntity>) map.get("data2");
    log.info("data1数据=={}", data1);
    log.info("data2数据=={}", data2);
    return R.success(map);
}

private Map<String, Object> getTemplateEntitiesMany(MultipartFile file) throws IOException {
        Map<String,Object> map = new HashMap<>();
        TemplateListener listener = new TemplateListener();	// 定义的 listener
        OtherTemplateListener otherListener = new OtherTemplateListener();

        ExcelReader excelReader = EasyExcel.read(file.getInputStream()).build();
        // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener
        // readSheet参数设置读取sheet的序号
    	// 读取sheet1
        ReadSheet readSheet1 =
               EasyExcel.readSheet(0).head(TemplateEntity.class).registerReadListener(listener).build();
    	// 读取sheet3
        ReadSheet readSheet2 =
                EasyExcel.readSheet(2).head(OtherTemplateEntity.class).registerReadListener(otherListener).build();

        excelReader.read(readSheet1, readSheet2);
        // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
        excelReader.finish();

    	// 取出数据放入map中,然后返回
        List<TemplateEntity> data1 = listener.getData();
        List<OtherTemplateEntity> data2 = otherListener.getData();
        map.put("data1", data1);
        map.put("data2", data2);

        return map;
    }

{
    "code": 200,
    "msg": "OK",
    "message": null,
    "data": {
        "data2": [
            {
                "label": "a",
                "name": "a1",
                "type": "t1",
                "date": "2022-01-07"
            },
            {
                "label": "b",
                "name": "b1",
                "type": "t2",
                "date": "2022-01-07"
            }
            ......
        ],
        "data1": [
            {
                "label": 1,
                "str": "a",
                "num": 20,
                "date": "2021-12-20"
            },
            {
                "label": 2,
                "str": "b",
                "num": 30,
                "date": "2021-12-20"
            }
            ......
        ]
    }
}

多行头

读取时设置头行数即可

headRowNumber是头行数,如下是设置头行数2,那么读取时会从第三行开始读取数据

复制代码
private List<TemplateEntity> getTemplateEntities(MultipartFile file) throws IOException {
        TemplateListener listener = new TemplateListener();	// 定义的 listener
        EasyExcel.read(file.getInputStream(), TemplateEntity.class, listener).sheet(0).headRowNumber(2).doRead();
        // 返回 所有数据
        return listener.getData();
    }
读取表头数据

在监听类中重写invokeHeadMap方法,将表头数据也添加即可

复制代码
public class TemplateListener extends AnalysisEventListener<TemplateEntity> {

    private List<TemplateEntity> list = new ArrayList<>();
    @Override
    public void invoke(TemplateEntity data, AnalysisContext context) {
        list.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {}

    public List<TemplateEntity> getData() {
        return list;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        // 读取到头数据
        LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap))
    }
------------------------------------------------

Springboot + Easyexcel 导出数据

简单导出excel

实体类省略,还是上面的TemplateEntity

导出excel数据,这里有两种写法,拟定好文件名称直接传入方法,会自动创建一个文件

模拟数据 10条数据
复制代码
// 模拟数据
private List<TemplateEntity> exportData() {
    List<TemplateEntity> entities = new ArrayList<>();
    for (int i = 0; i< 10; i++) {
        TemplateEntity entity = new TemplateEntity();
        entity.setStr("字符串" + i);
        entity.setDate("数据" + i);
        entity.setLabel(i+1);
        entity.setNum(i);
        entities.add(entity);
    }
    return entities;
}
导出程序
复制代码
public R export() {
    String path = "C:\\Users\\EDZ\\Desktop\\";

    // 写法1
    String fileName = path + System.currentTimeMillis() + ".xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    // 如果这里想使用03 则 传入excelType参数即可
    EasyExcel.write(fileName, TemplateEntity.class).sheet("模板").doWrite(exportData());

    // 写法2
    // 这里 需要指定写用哪个class去写
    ExcelWriter excelWriter = EasyExcel.write(fileName, TemplateEntity.class).build();
    WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
    excelWriter.write(exportData(), writeSheet);
    // 千万别忘记finish 会帮忙关闭流
    excelWriter.finish();

    return R.success();
}
------------------------------------------------
过滤导出列
复制代码
public R export() {
    String path = "C:\\Users\\EDZ\\Desktop\\";
    
    String fileName = path + System.currentTimeMillis() + ".xlsx";
    
    // 加入要忽略date字段
    Set<String> excludeColumnFiledNames = new HashSet<String>();
    excludeColumnFiledNames.add("date");
	EasyExcel.write(fileName,TemplateEntity.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板").doWrite(exportData());   
    
}

复杂头写入 合并表头

实体类
复制代码
@Data
public class TemplateEntity {

    @ExcelProperty({"主标题", "标号"})
    private Integer label;

    @ExcelProperty({"主标题", "字符串"})
    private String str;

    @ExcelProperty({"主标题", "数字"})
    private Integer num;

    @ExcelProperty({"主标题", "时间"})
    @DateTimeFormat("yyyy-MM-dd")
    private String date;
}
相关推荐
hikktn15 分钟前
Excel 日期格式统一治理:从“显示不全“到“自动兼容“的完整方案
windows·python·excel
霸道流氓气质2 小时前
Spring Boot 大数据量 Excel 导入导出功能实现指南
spring boot·后端·excel
霸道流氓气质3 小时前
Java 单元测试生成大量 Excel 测试数据实战指南
java·单元测试·excel
IT WorryFree3 小时前
FortiGate常用资产 OID 清单,配套 Excel 台账模板字段
网络·人工智能·excel
MyFreeIT4 小时前
Excel Enable Content
excel
E_ICEBLUE4 小时前
将 Excel 表格插入 Word 文档的三种实用方案(Python 自动化)
python·word·excel
俊哥工具4 小时前
027免费开源硬盘检测工具,一键查看健康度,杜绝数据丢失
pdf·电脑·word·excel·音视频
不恋水的雨1 天前
easyexcel快速填充大数据量不覆盖后面的行解决方式
java·excel·poi
靖待1 天前
【解决方法】python写Excel单元格截断长文本
python·excel·解决方法
Curvatureflight1 天前
大数据量 Excel 导出怎么优化?一套可落地的异步化方案
java·后端·excel·状态模式