EasyExcel简单使用

EasyExcel简单使用

​ 之前一直用的Apache POI来做数据的导入导出,但听说阿里的EasyExcel也拥有POI的功能的同时,在处理大数据量的导入导出的时候性能上比POI更好,所以就来尝试使用一下

导入Maven依赖:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.2.1</version> <!-- 请检查并使用最新稳定版本 -->
</dependency>
导出数据功能
导出模型类

​ 定义一个导出数据模型类,用于设置excel文件的格式,通过注解的方式可以定义excel中的格式
@ColumnWidth(20) 设置excel中列的宽度为20;

@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER) 设置文本内容是否居中;

@HeadFontStyle(bold = BooleanEnum.FALSE) 设置字体是否加粗;

@ExcelProperty(value = “电话”, index = 0) 设置了excel中的标题,value则是标题内容,index则是内容所在的列的位置

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@ColumnWidth(20)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
@HeadFontStyle(bold = BooleanEnum.FALSE)
public class PmembersExportVO {

    @ColumnWidth(15)
    @ExcelProperty(value = "电话", index = 0)
    private String mobile;

    @ColumnWidth(15)
    @ExcelProperty(value = "姓名", index = 1)
    private String realname;

    @ColumnWidth(10)
    @ExcelProperty(value = "性别", index = 2)
    private String gender;

    @ColumnWidth(10)
    @ExcelProperty(value = "省份", index = 3)
    private String resideprovince;

    @ColumnWidth(10)
    @ExcelProperty(value = "城市", index = 4)
    private String residecity;

    @ColumnWidth(10)
    @ExcelProperty(value = "区/县", index = 5)
    private String residedist;

    @ColumnWidth(20)
    @ExcelProperty(value = "地址", index = 6)
    private String address;

    @ColumnWidth(12)
    @ExcelProperty(value = "公历生日", index = 7)
    private String birth;

    @ColumnWidth(12)
    @ExcelProperty(value = "农历生日", index = 8)
    private String yinlibirth;

    @ColumnWidth(12)
    @ExcelProperty(value = "是否闰月", index = 9)
    private String isLeapMonth;

}
controller代码
    @ApiOperation("导出居士信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "weiqingview_backend_token", value = "token", required = true, dataType = "String", paramType = "header"),
            @ApiImplicitParam(name = "uniacid", value = "Unicid", required = true, dataType = "Integer", paramType = "query")
    })
    @GetMapping("/export")
    public void export(@RequestParam Map<String, Object> params, HttpServletResponse response) {
        mcMembersService.exportExcel(params, response);
    }
service代码

​ 通过查询数据库中的数据,并封装到List集合中,调用EasyExcel的write方法即可将集合中的数据写入生成excel文件供下载

public void export(Map<String, Object> params, HttpServletResponse response) {

        Integer uniacid = Integer.valueOf(params.get("uniacid").toString());

        List<McMembers> mcMembersList = this.list(new QueryWrapper<McMembers>().eq("isBeliever", 1).eq("uniacid", uniacid));

        List<PmembersExportVO> pmembersExportVOList = mcMembersList.stream().map(m -> {
            PmembersExportVO pmembersExportVO = new PmembersExportVO();
            pmembersExportVO.setAddress(m.getAddress());
            pmembersExportVO.setMobile(m.getMobile());
            pmembersExportVO.setGender(ObjectUtils.isEmpty(m.getGender()) ? "" : m.getGender().equals(0) ? "女" : "男");
            pmembersExportVO.setBirth(m.getBirth());
            pmembersExportVO.setYinlibirth(m.getYinlibirth());
            pmembersExportVO.setRealname(m.getRealname());
            pmembersExportVO.setResidedist(m.getResidedist());
            pmembersExportVO.setResidecity(m.getResidecity());
            pmembersExportVO.setResideprovince(m.getResideprovince());
            pmembersExportVO.setIsLeapMonth(ObjectUtils.isEmpty(m.getIsLeapMonth()) ? "否" : m.getIsLeapMonth() == 1 ? "是" : "否");

            return pmembersExportVO;
        }).collect(Collectors.toList());


//        // 导出Excel
//        EasyExcel.write("居士信息数据.xls", PmembersExportVO.class)
                .head(headersList) // 设置表头
//                .sheet("用户信息")
//                .doWrite(pmembersExportVOList);

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = null;
        try {
            fileName = URLEncoder.encode("居士信息数据.xlsx", "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            EasyExcel.write(response.getOutputStream(), PmembersExportVO.class)
                    .sheet("用户信息")
                    .doWrite(pmembersExportVOList);
        } catch (UnsupportedEncodingException e) {
            log.error("导出居士信息报错 UnsupportedEncodingException:{}", e);
        } catch (IOException e) {
            log.error("导出居士信息报错 IOException:{}", e);
        }

    }

image-20240511105026375

导入数据功能:
导入数据模型类

​ 我这里用的跟导出数据类基本一致,所以也就改了个类名

​ 只要用@ExcelProperty指定对应列的信息就行,其他指定格式的注解其实可以忽略

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@ColumnWidth(20)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
@HeadFontStyle(bold = BooleanEnum.FALSE)
public class ImportPmcMembersDTO {

    @ColumnWidth(15)
    @ExcelProperty(value = "电话", index = 0)
    private String mobile;

    @ColumnWidth(15)
    @ExcelProperty(value = "姓名", index = 1)
    private String realname;

    @ColumnWidth(10)
    @ExcelProperty(value = "性别", index = 2)
    private String gender;

    @ColumnWidth(10)
    @ExcelProperty(value = "省份", index = 3)
    private String resideprovince;

    @ColumnWidth(10)
    @ExcelProperty(value = "城市", index = 4)
    private String residecity;

    @ColumnWidth(10)
    @ExcelProperty(value = "区/县", index = 5)
    private String residedist;

    @ColumnWidth(20)
    @ExcelProperty(value = "地址", index = 6)
    private String address;

    @ColumnWidth(12)
    @ExcelProperty(value = "公历生日", index = 7)
    private String birth;

    @ColumnWidth(12)
    @ExcelProperty(value = "农历生日", index = 8)
    private String yinlibirth;


    @ColumnWidth(12)
    @ExcelProperty(value = "是否闰月", index = 9)
    private String isLeapMonth;

}
controller代码

​ 前端页面上传一个name是file的文件

    @ApiOperation("导入居士信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "weiqingview_backend_token", value = "token", required = true, dataType = "String", paramType = "header"),
            @ApiImplicitParam(name = "uniacid", value = "Unicid", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "file", value = "file", required = true, dataType = "MultipartFile", paramType = "query")
    })
    @PostMapping("/uploadExcel")
    public R uploadExcel(@RequestParam("file") MultipartFile file, @RequestParam Map<String, Object> params) {
        return mcMembersService.importExcel(file, params);
    }
service代码

​ 下面是接收controller传来的文件后,通过调用EasyExcel的read方法,直接进行导入操作

    public R importExcel(MultipartFile file, Map<String, Object> params) {
        // 检查文件是否为空
        if (file.isEmpty()) {
            return R.error("没有检测到文件"); // 返回错误页面
        }

        try {

            // 执行导入操作
            EasyExcel.read(file.getInputStream(), ImportPmcMembersDTO.class, new ImportPmcMembersListener(this, params)).sheet().doRead();

            // 返回上传成功页面
            return R.ok("导入excel成功");

        } catch (IOException e) {
            e.printStackTrace();
            return R.error("导入excel失败");
        }
    }

​ 下面是service中基本的添加数据的操作方法,导入数据插库的时候也直接调用,就不写新的插库方法了

public R pAdd(AddPmcMembersDTO addPmcMembersDTO, Map<String, Object> params) {
        McMembers mcMembers = new McMembers();
        BeanUtils.copyProperties(addPmcMembersDTO, mcMembers);
        mcMembers.setIsBeliever((byte) 1);

        Integer uniacid = Integer.parseInt(params.get("uniacid").toString());
        mcMembers.setUniacid(uniacid);

        if (this.save(mcMembers)) {
            return R.ok("添加成功");
        }

        return R.error("添加失败");
    }
listener代码

​ 上传的话需要定义一个listener,并继承AnalysisEventListener,这里的T类型就是上面定义的模型类的类型。

​ 如果是在listener中进行插库操作,那需要把service注入进来,但是在listener中不能用@Autowired,所以重写一个带参的构造方法,把注入好的service直接传进来使用即可,我下面将注入好的mcMembersService传递了进来,执行插库操作。下面的AddPmcMembersDTO是我另外定义的一个模型类,是用于界面上添加数据用的,这里直接转换后调用进行插库操作了。

​ 当然也可以在listener中先将excel中的数据都封装到List集合中,再统一将List中的数据插库也行。

public class ImportPmcMembersListener extends AnalysisEventListener<ImportPmcMembersDTO> {

    private McMembersService mcMembersService;

    private Map<String, Object> params;
    
	//通过构造方法,得到注入好的mcMembersService
    public ImportPmcMembersListener(McMembersService mcMembersService, Map<String, Object> params) {
        this.mcMembersService = mcMembersService;
        this.params = params;
    }

    @Override
    public void invoke(ImportPmcMembersDTO data, AnalysisContext context) {
        // 处理读取到的每行数据,例如保存到数据库
        System.out.println("读取到一行数据: " + data.toString());
        // 这里可以添加保存到数据库的逻辑

        AddPmcMembersDTO addPmcMembersDTO = new AddPmcMembersDTO();
        addPmcMembersDTO.setMobile(data.getMobile());
        addPmcMembersDTO.setRealname(data.getRealname());
        addPmcMembersDTO.setGender((byte) (ObjectUtils.isEmpty(data.getGender()) ? 0 : data.getGender().equals("男") ? 1 : 2));

        addPmcMembersDTO.setAddress(data.getAddress());
        addPmcMembersDTO.setBirth(data.getBirth());
        addPmcMembersDTO.setYinlibirth(data.getYinlibirth());
        addPmcMembersDTO.setResidedist(data.getResidedist());
        addPmcMembersDTO.setResidecity(data.getResidecity());
        addPmcMembersDTO.setResideprovince(data.getResideprovince());
        addPmcMembersDTO.setIsLeapMonth((byte) (ObjectUtils.isEmpty(data.getIsLeapMonth()) ? 0 : data.getIsLeapMonth().equals("是") ? 1 : 0));

        // 进行插库操作
        mcMembersService.pAdd(addPmcMembersDTO, params);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 所有数据解析完毕后的回调
        System.out.println("所有数据解析完成");
    }

将一下excel数据进行导入操作

image-20240511112040930

用Api工具测试了下,上传成功

image-20240511112220656

查看数据库,数据也成功导入

image-20240511112302526

整体感觉挺好用的,对于不同的数据进行导入的话,其实可以再封装成通用的listener,这样不用每一个功能导入都去定义一个listener,这个等后面有空再折腾吧。

结束

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值