alibaba easyexcel 使用心得

项目中加了一个excel导入导出的功能,之前用过POI,但是听说easyexcel 很快!

所以想试试他到底有多快!

首先导入依赖,刚开始用的3.1.0版本的,但是新版本用的人比较少,官方的手册又不是很完美,之后又降为2.x版本的

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <version>2.2.6</version>
            </dependency>

首先咱们需要整一个监听

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

import java.util.ArrayList;
import java.util.List;



public class QdportReadListener extends AnalysisEventListener  {

    /**
     * 可以通过实例获取该值获取,之后可以实现直接把dataList 存到数据库等等操作
     */
    private List<Object> dataList = new ArrayList<>();

    @Override
    public void invoke(Object object, AnalysisContext context) {
        //每一条数据都会循环,可以实现空数据,重复数据的检查,不建议在这里做太复杂的逻辑,这里
        //不写也没关系
        //数据存储到list,供批量处理,或后续自己业务逻辑处理。
        dataList.add(object);
        handleBusinessLogic();
          /*
        如数据过大,可以进行定量分批处理
        if(dataList.size()>=200){
            handleBusinessLogic();
            dataList.clear();
        }
         */
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
    }

    //根据业务自行实现该方法,例如将解析好的dataList存储到数据库中
    private void handleBusinessLogic() {

    }

    public List<Object> getDataList() {
        return dataList;
    }

    public void setDataList(List<Object> dataList) {
        this.dataList = dataList;
    }
}

对应的实体类(只是举个栗子)

@Data//lombok
@ExcelIgnoreUnannotated//这个注解的作用是属性只有加了@ExcelProperty才会参与读写。
public class Info {

    /**
     * 主键
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 名字
     */
    @ExcelProperty(value = "名字")
    private String name;

    /**
     * 类型
     */
    @ExcelProperty(value = "类型", converter = CustomStringStringConverter.class)
    private Integer type;

    /**
     * 是否
     */
    @ExcelProperty(value = "是否", converter = CustomStringStringConverter.class)
    private Integer status;
}

然后写接口

这是导出:因为用的是微服务gateway网关,不能用servlet ,只能用

import org.springframework.http.server.reactive.ServerHttpResponse;包下的ServerHttpResponse来代替
    /**
     * 导出查询数据
     */
    @GetMapping("/export")
    public Mono<Void> export(ServerHttpResponse response, Info info) {
        response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
        response.getHeaders().set(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=这里拼上文件的名字.xlsx");
        //spring webflux文件下载零拷贝(Zero-copy)
        ZeroCopyHttpOutputMessage zeroCopyResponse = (ZeroCopyHttpOutputMessage) response;
        File file = new File("../文件先暂时放在本地.xlsx");//应该有文件流的方法,但我懒
        // 分页查询数据
        EasyExcel.write(file, DockInfo.class)
                .sheet("这里是excel里面分页的名字")
                .doWrite(infoService.getList(info));//这里放的就是需要处理的数据
        return zeroCopyResponse.writeWith(file, 0, file.length()).doFinally(a -> {
            boolean delete = file.delete();//处理完成之后把本地文件删除,这里建议做一下空值判断
        });
    }

这样,一个导出就完成了

然后做导入:

    /**
     * 导入数据
     */
    @PostMapping(value = "/import")
    public Result<Integer> importInfo(@RequestPart("file") FilePart filePart) throws IOException {
        String strFileName = filePart.filename();
        File file = new File("../" + strFileName);//文件暂时存到本地,应该有文件流的方法,但我懒
        List<info> infos;
        try {
            filePart.transferTo(file);
            ExcelReaderBuilder read = EasyExcel.read(file, Info.class, new QdportReadListener());
            dockInfos = read.doReadAllSync();
        } catch (Exception ignored) {
            throw new ServerException("文件读取发生异常");
        } finally {
            boolean delete = file.delete();//读完了文件之后做删除
        }
        return infoService.addInfoList(infos);
    }

之后加了一个导出模板的功能,要求导出的模板,字典类型的列是下拉列表选择的那种

就是这里让我放弃的3.1.0,没有文档,网上也没有资源,对于我这种菜狗来说不合适。

 首先实现一个 写表的接口

import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;

import java.util.HashMap;
import java.util.Map;


public class MySheetWriteHandler implements SheetWriteHandler {

    /**
     * 创建sheet页前的操作
     * @param writeWorkbookHolder
     * @param writeSheetHolder
     */
    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {

    }

    /**
     * 创建sheet页后的操作
     * @param writeWorkbookHolder
     * @param writeSheetHolder
     */
    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        //定义选值范围
        String[] strings1 = new String[]{"类型1","类型2"};
        String[] strings2 = new String[]{"否","是"};
        //根据index,形成map,可插入多个
        Map<Integer,String []> mapDropDown = new HashMap<>();
        mapDropDown.put(2,strings1);//第一个参数是在那一列加入,从0开始
        mapDropDown.put(3,strings2);
        //获取sheet页
        Sheet sheet = writeSheetHolder.getSheet();
        ///开始设置下拉框
        DataValidationHelper helper = sheet.getDataValidationHelper();
        for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
            /***起始行、终止行、起始列、终止列**/
            CellRangeAddressList addressList = new CellRangeAddressList(1, 9999, entry.getKey(), entry.getKey());
            /***设置下拉框数据**/
            DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
            DataValidation dataValidation = helper.createValidation(constraint, addressList);
            /***处理Excel兼容性问题**/
            if (dataValidation instanceof XSSFDataValidation) {
                dataValidation.setSuppressDropDownArrow(true);
                dataValidation.setShowErrorBox(true);
            } else {
                dataValidation.setSuppressDropDownArrow(false);
            }
            sheet.addValidationData(dataValidation);
        }
    }
}

写接口:

    /**
     * 导出模板
     */
    @GetMapping("/exportTemplate")
    public Mono<Void> exportTemplate(ServerHttpResponse response) {
        response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
        response.getHeaders().set(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=模板.xlsx");
        //spring webflux文件下载零拷贝(Zero-copy)
        File file1 = new File("../模板.xlsx");
        ZeroCopyHttpOutputMessage zeroCopyResponse = (ZeroCopyHttpOutputMessage) response;
        EasyExcel.write(file1, DockInfo.class)
                .sheet("模板")
                .registerWriteHandler(new MySheetWriteHandler())//刚才实现的类在这个地方用上了
                .doWrite(new ArrayList<>());

        return zeroCopyResponse.writeWith(file1, 0, file1.length()).doFinally(a -> {
            boolean delete = file1.delete();
        });
    }

这样,功能就完成了!

如果有什么问题,欢迎在评论区讨论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值