EasyExcel复杂excel导入

简介: EasyExcel复杂excel导入

EasyExcel复杂excel导入

easyexcel官方都是一些简单的导入到处示例,复杂的excel文档导入,还得自己去慢慢琢磨、百度、思考、总结、学习、观察。

代码地址在文档的最后,如果你也遇到这种需求,不妨动动你的小拇指,点个关注,要是可以点个赞,那就更好咯,做人嘛,不要这么小气,不要吝啬你的赞美,哈哈。

要导入的excel格式,如下图:

第一个sheet内容:
图片.png
第二个sheet内容,一对多,一个阶段对应多个任务,一个任务对应多个动作:
图片.png
废话不多说,直接上代码,能看懂多少就看你自己的功力了

controller层
@RestController
@RequestMapping("/sakura/easyexcel")
@Api(value = "复杂excel导入", tags = {"复杂excel导入"})
public class ProjectExcelController {
@Autowired
ProjectEasyExcelService projectEasyExcelService;

@ApiOperation("复杂excel导入")
@PostMapping(value = "/complex/upload")
public CommonResult<Object> upload(@RequestParam("file") MultipartFile file){
    projectEasyExcelService.projectRead(file);
    return CommonResult.success();
}

}
service层

/**

  • 项目信息excel
    */
    @Transactional(rollbackFor = Exception.class)
    public void projectRead(MultipartFile file) {
    EasyExcelListener easyExcelListener = new EasyExcelListener();
    ExcelReader excelReader = null;
    try {

    excelReader = EasyExcelFactory.read(file.getInputStream(), easyExcelListener).build();
    

    } catch (IOException e) {

    throw new YErrorException("项目信息导入出错!");
    

    }
    // step2. 获取各个sheet页信息
    List sheets = excelReader.excelExecutor().sheetList();
    // step3. 获取各个Shhet页表格内容存于map
    Map>> sheetInfos = new HashMap<>(sheets.size());
    for (ReadSheet sheet : sheets) {

    Integer sheetNo = sheet.getSheetNo();
    excelReader.read(sheet);
    sheetInfos.put(sheetNo, easyExcelListener.getListMap());
    

    }
    //保存数据到数据库
    saveExcelInfo(sheetInfos);
    }
    上面projectRead方法用到的EasyExcelListener类
    @Slf4j
    public class EasyExcelListener extends AnalysisEventListener {

    // 创建list集合封装最终的数据
    private List list = new ArrayList<>();
    // sheet页索引
    private int sheetNo = 0;

    @Override
    public void invoke(Object t, AnalysisContext context) {

    // 读取excle内容
    int currentSheetNo = context.readSheetHolder().getSheetNo();
    if (currentSheetNo != sheetNo) {
        // 如果不根据sheet页索引更新状态重新创建list,list会反复添加前面的sheet页对象值
        list = new ArrayList<>();
        sheetNo = currentSheetNo;
    }
    list.add(t);
    

    }

    // 读取excel表头信息
    @Override
    public void invokeHeadMap(Map headMap, AnalysisContext context) {
    }

    // 读取完成后执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }

    /**

    • 将表格转化为map集合(复杂excel读取用此方法)
      *
    • @return map集合
      */
      public List> getListMap() {
      String jsonObj = JSON.toJSONString(list);
      return JSON.parseArray(jsonObj, LinkedHashMap.class);
      }

    }
    上面projectRead中的方法
    public void saveExcelInfo(Map>> sheetInfos) {
    for (Integer sheetNo : sheetInfos.keySet()) {
    List> maps = sheetInfos.get(sheetNo);
    // 不同sheet页数据处理方式不同
    switch (sheetNo) {
    case 0:
    saveProject(maps);
    break;
    case 1:
    saveTarget(maps);
    break;
    default:
    break;
    }
    }
    }
    保存第一个sheet的项目信息,并返回全局的项目id,代码很长,简化了一部分,全部代码可以看最后github的地址

    public void saveProject(List> maps) {
    ProjectManage projectManage = new ProjectManage();
    for (LinkedHashMap map : maps) {
    if (map.containsValue("项目名称")) {
    String projectName = map.getOrDefault("1", "");
    if (StringUtils.isBlank(projectName)) {
    throw new YWarmingException("项目名称不能为空!");
    }
    projectManage.setProjectName(projectName);
    }
    if (map.containsValue("项目编号")) {
    String projectCode = map.getOrDefault("4", "");
    projectManage.setProjectCode(projectCode);
    }
    if (map.containsValue("合同签订时间")) {
    String contractSignTimeStr = map.getOrDefault("1", "");
    if (StringUtils.isNotBlank(contractSignTimeStr)) {
    Date contractSignDate = DateUtil.parse(contractSignTimeStr);
    Instant instant = contractSignDate.toInstant();
    LocalDateTime contractSignTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
    projectManage.setContractSignTime(contractSignTime);
    }
    }
    if (map.containsValue("合同规定终验时间")) {
    String contractRuleFinalAcceptTimeStr = map.getOrDefault("3", "");
    if (StringUtils.isNotBlank(contractRuleFinalAcceptTimeStr)) {
    Date contractSignDate = DateUtil.parse(contractRuleFinalAcceptTimeStr);
    Instant instant = contractSignDate.toInstant();
    LocalDateTime contractRuleFinalAcceptTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
    projectManage.setContractRuleFinalAcceptTime(contractRuleFinalAcceptTime);
    }
    }
    if (map.containsValue("开工时间")) {
    String startTimeStr = map.getOrDefault("5", "");
    if (StringUtils.isNotBlank(startTimeStr)) {
    Date startDate = DateUtil.parse(startTimeStr);
    Instant instant = startDate.toInstant();
    LocalDateTime startTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
    projectManage.setStartTime(startTime);
    }
    }
    }
    //这里项目背景的行数,写死了,后面调整表格时,会影响这一块
    Map projectBackgroudMap = maps.get(8);
    String projectBackgroud = projectBackgroudMap.getOrDefault("0", "").toString();
    projectManage.setProjectBackgroud(projectBackgroud);

        projectManageService.save(projectManage);
        projectId = projectManage.getId();
    

    }

    保存第二个sheet的目标,将数据组装成多级嵌套的集合。有点绕,要花点时间去想想,项目赶工,瞎几把乱写了,没想到可以凑合着用。
    public void saveTarget(List> list) {
    if (projectId == 0) {
    throw new YErrorException("请先成功导入项目!");
    }

        FirstTarget firstTarget = new FirstTarget();
        SecondTarget secondTarget = new SecondTarget();
        List<FirstTarget> firstTargetList = new ArrayList<>();
        List<SecondTarget> secondTargetList = new ArrayList<>();
        List<ThirdTarget> thirdTargetList = new ArrayList<>();
    
        for (Map<String, String> map : list) {
            System.err.println(map);
            String firstTargetName = map.getOrDefault("0", "");
            String firstTargetType = map.getOrDefault("1", "");
            String secondTargetName = map.getOrDefault("2", "");
            String thirdTargetName = map.getOrDefault("3", "");
            String thirdTargetBudget = map.getOrDefault("4", "");
            String positions = map.getOrDefault("5", "");
    
            if (StringUtils.isNotBlank(firstTargetName)) {
                //第一阶段名称不为空时,二三阶段一定不为空
                if (StringUtils.isNotBlank(secondTargetName)) {
                    //第二阶段名称不为空
                    if (secondTargetList.size() != 0) {
                        List<SecondTarget> secondTargets = firstTarget.getSecondTargets();
                        secondTargets.addAll(secondTargetList);
                    }
    
                    secondTarget = new SecondTarget();
                    thirdTargetList = new ArrayList<>();
    
                    firstTarget = new FirstTarget();
                    secondTargetList = new ArrayList<>();
    
                    secondTarget.setSecondTargetName(secondTargetName);
    
                    ThirdTarget thirdTarget = new ThirdTarget();
                    thirdTarget.setThirdTargetName(thirdTargetName);
                    thirdTarget.setThirdTargetBudget(thirdTargetBudget);
                    thirdTargetList.add(thirdTarget);
    
                    secondTarget.setThirdTargets(thirdTargetList);
                    secondTargetList.add(secondTarget);
    
                    firstTarget.setSecondTargets(secondTargetList);
                    firstTarget.setFirstTargetName(firstTargetName);
                    firstTarget.setFirstTargetType(firstTargetType);
                    firstTargetList.add(firstTarget);
                }
            } else {
                //第一阶段名称为空,且第二阶段名称不为空
                if (StringUtils.isNotBlank(secondTargetName)) {
                    //去重
                    if (secondTargetList.size() != 0) {
                        SecondTarget st = secondTargetList.get(0);
                        List<SecondTarget> secondTargets = firstTarget.getSecondTargets();
                        SecondTarget secondT = secondTargets.get(0);
                        if (!st.getSecondTargetName().equals(secondT.getSecondTargetName())) {
                            secondTargets.addAll(secondTargetList);
                        }
                    }
    
                    secondTarget = new SecondTarget();
                    thirdTargetList = new ArrayList<>();
    
                    secondTargetList = new ArrayList<>();
    
                    secondTarget.setSecondTargetName(secondTargetName);
    
                    ThirdTarget thirdTarget = new ThirdTarget();
                    thirdTarget.setThirdTargetName(thirdTargetName);
                    thirdTarget.setThirdTargetBudget(thirdTargetBudget);
                    thirdTargetList.add(thirdTarget);
    
                    secondTarget.setSecondTargetName(secondTargetName);
                    secondTarget.setThirdTargets(thirdTargetList);
                    secondTargetList.add(secondTarget);
                } else {
                    //第一阶段名称为空,第二阶段名称为空,第三阶段不为空
                    ThirdTarget thirdTarget = new ThirdTarget();
                    thirdTarget.setThirdTargetBudget(thirdTargetBudget);
                    thirdTarget.setThirdTargetName(thirdTargetName);
                    thirdTargetList.add(thirdTarget);
                }
            }
        }
        // 保存最后一条数据
        if (secondTargetList.size() != 0) {
            List<SecondTarget> secondTargets = firstTarget.getSecondTargets();
            secondTargets.addAll(secondTargetList);
        }
        System.err.println(firstTargetList);
    }
    

    还有几个实体类就不放上来了,博客太长了,看完有一点点思路,可以帮助到你,我还是很开心的,全部代码和导入的excel放下面了,可以拿去看看,参考参考。

相关文章
|
1天前
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
1月前
|
前端开发
实现Excel文件和其他文件导出为压缩包,并导入
实现Excel文件和其他文件导出为压缩包,并导入
30 1
|
3月前
|
SQL C# 数据库
EPPlus库的安装和使用 C# 中 Excel的导入和导出
本文介绍了如何使用EPPlus库在C#中实现Excel的导入和导出功能。首先,通过NuGet包管理器安装EPPlus库,然后提供了将DataGridView数据导出到Excel的步骤和代码示例,包括将DataGridView转换为DataTable和使用EPPlus将DataTable导出为Excel文件。接着,介绍了如何将Excel数据导入到数据库中,包括读取Excel文件、解析数据、执行SQL插入操作。
EPPlus库的安装和使用 C# 中 Excel的导入和导出
|
2月前
|
easyexcel Java UED
SpringBoot中大量数据导出方案:使用EasyExcel并行导出多个excel文件并压缩zip后下载
在SpringBoot环境中,为了优化大量数据的Excel导出体验,可采用异步方式处理。具体做法是将数据拆分后利用`CompletableFuture`与`ThreadPoolTaskExecutor`并行导出,并使用EasyExcel生成多个Excel文件,最终将其压缩成ZIP文件供下载。此方案提升了导出效率,改善了用户体验。代码示例展示了如何实现这一过程,包括多线程处理、模板导出及资源清理等关键步骤。
|
4月前
|
easyexcel Java 关系型数据库
阿里巴巴-EasyExcel 基于Java的简单、省内存的读写Excel
该文章主要介绍了在Java应用中如何使用EasyExcel技术完成对Excel文件的导入和导出操作,包括环境搭建、基本概念、快速入门、进阶操作和综合应用等内容,并提供了相关代码示例和注意事项。
 阿里巴巴-EasyExcel 基于Java的简单、省内存的读写Excel
|
4月前
|
JavaScript 前端开发 easyexcel
基于SpringBoot + EasyExcel + Vue + Blob实现导出Excel文件的前后端完整过程
本文展示了基于SpringBoot + EasyExcel + Vue + Blob实现导出Excel文件的完整过程,包括后端使用EasyExcel生成Excel文件流,前端通过Blob对象接收并触发下载的操作步骤和代码示例。
849 0
基于SpringBoot + EasyExcel + Vue + Blob实现导出Excel文件的前后端完整过程
|
4月前
|
关系型数据库 MySQL Windows
MySQL数据导入:MySQL 导入 Excel 文件.md
MySQL数据导入:MySQL 导入 Excel 文件.md
|
5月前
|
存储 关系型数据库 MySQL
Excel 导入 sql3
【7月更文挑战第18天】
51 2
|
4月前
|
前端开发 easyexcel
SpringBoot+Vue3实现Excel导入
SpringBoot+Vue3实现Excel导入
147 0
|
6月前
|
Java easyexcel
java开发excel导入导出工具类基于EasyExcel
java开发excel导入导出工具类基于EasyExcel
331 1