Java导出Excel并合并单元格

需求:需要在导出excel时合并指定的单元格

 ruoyi excel

项目基于若伊框架二次开发,本着能用现成的就不自己写的原则,先是尝试了@Excel注解中needMerge属性

     /**
     * 是否需要纵向合并单元格,应对需求:含有list集合单元格)
     */
    public boolean needMerge() default false;

查了一圈别人的使用,大致是需要定义一个List集合,集合元素为对象,对象中的属性标注@Excel注解,并表明name属性

照葫芦画瓢

@Getter
@Setter
@ToString
public class CutterControlVO {

    /** 主键 */
    private Long id;

    /** 工厂编码 */
    @Excel(name = "工厂编码",needMerge = true)
    private String factoryCode;

    /** 产线编码 */
    @Excel(name = "产线编码",needMerge = true)
    private String productionLineCode;

    /** 设备编号 */
    @Excel(name = "设备编号",needMerge = true)
    private String deviceNumber;

    /** 设备名称 */
    @Excel(name = "设备名称",needMerge = true)
    private String deviceName;

    @Excel(name = "检测刀具编码",needMerge = true)
    private String cutterCode;

    /** 换刀时间 */
    @JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @Excel(name = "换刀时间",dateFormat = "yyyy-MM-dd HH:mm:ss",needMerge = true)
    private Date cutterChangeTime;

    /** 上刀数 */
    @Excel(name = "上刀数",needMerge = true)
    private Integer upperKnifeNumber;

    /** 下刀数 */
    @Excel(name = "下刀数",needMerge = true)
    private Integer lowerKnifeNumber;

    @Excel(name = "更换人员",needMerge = true)
    private String modifyUser;

    /** 备注 */
    @Excel(name = "备注",needMerge = true)
    private String remark;

    @Excel(name = "换刀位置")
    private List cutterChangePosition;

    @Excel(name = "累计分切米数")
    private List accumulatedCuttingMeters;


}
@Getter
@Setter
@ToString
public class CutterVO {

    @Excel(name = "上刀左")
    private Integer upperKnifeLeft;

    @Excel(name = "上刀中")
    private Integer upperKnifeCenter;

    @Excel(name = "上刀右")
    private Integer upperKnifeRight;

    @Excel(name = "下刀左")
    private Integer lowerKnifeLeft;

    @Excel(name = "下刀中")
    private Integer lowerKnifeCenter;

    @Excel(name = "下刀右")
    private Integer lowerKnifeRight;
}
@PostMapping("/export")
public void export(HttpServletResponse response) throws Exception{
    List cutterControlList = cutterControlService.getCutterControlList();
    //设置导出的数据表格式
    List cutterControlVOList = new ArrayList<>();
    CutterControlVO cutterControlVO = null;
    for (CutterControl cutterControl : cutterControlList) {
        cutterControlVO = new CutterControlVO();
        CutterVO cutterPosition = new CutterVO();
        cutterPosition.setUpperKnifeLeft(cutterControl.getCutterChangePositionUpperKnifeLeft());
        cutterPosition.setUpperKnifeCenter(cutterControl.getCutterChangePositionUpperKnifeCenter());
        cutterPosition.setUpperKnifeRight(cutterControl.getCutterChangePositionUpperKnifeRight());
        cutterPosition.setLowerKnifeLeft(cutterControl.getCutterChangePositionLowerKnifeLeft());
        cutterPosition.setLowerKnifeCenter(cutterControl.getCutterChangePositionLowerKnifeCenter());
        cutterPosition.setLowerKnifeRight(cutterControl.getCutterChangePositionLowerKnifeRight());

        CutterVO accumulatedCuttingMeters = new CutterVO();
        accumulatedCuttingMeters.setUpperKnifeLeft(cutterControl.getAccumulatedCuttingMetersUpperKnifeLeft());
        accumulatedCuttingMeters.setUpperKnifeCenter(cutterControl.getAccumulatedCuttingMetersUpperKnifeCenter());
        accumulatedCuttingMeters.setUpperKnifeRight(cutterControl.getAccumulatedCuttingMetersUpperKnifeRight());
        accumulatedCuttingMeters.setLowerKnifeLeft(cutterControl.getAccumulatedCuttingMetersLowerKnifeLeft());
        accumulatedCuttingMeters.setLowerKnifeCenter(cutterControl.getAccumulatedCuttingMetersLowerKnifeCenter());
        accumulatedCuttingMeters.setLowerKnifeRight(cutterControl.getAccumulatedCuttingMetersLowerKnifeRight());

        BeanUtils.copyProperties(cutterControl,cutterControlVO);
        cutterControlVO.setCutterChangePosition(Arrays.asList(cutterPosition));
        cutterControlVO.setAccumulatedCuttingMeters(Arrays.asList(accumulatedCuttingMeters));
        cutterControlVOList.add(cutterControlVO);
    }

    ExcelUtil util = new ExcelUtil(CutterControlVO.class);

    util.exportExcel(response,cutterControlVOList,"切刀管控台账数据");
}

查看导出效果:

黑人问号脸?

突然想到别人都是采用的是一个List集合,于是我注释了一个List,此时效果如下:

Java导出Excel并合并单元格_第1张图片

 可以看到,一个List效果是正常显示的,数据获取和显示也是正常的。

若伊使用的Excel导出工具类底层采用apache poi ,只能导出简单的excel表格,涉及复杂excel表格或者需要自定义表格时就比较难操作

使用阿里的easyExcel来实现复杂excel表格的导出

easyExcel

首先引入POM依赖

    
      com.alibaba
      easyexcel
      2.2.7
    

1、不合并单元格的写法

实体类

@Getter
@Setter
public class CutterControl {

    /** 主键 */
    @ExcelIgnore
    private Long id;

    /** 工厂编码 */
    @ExcelProperty(value = "工厂编码")
    private String factoryCode;

    /** 产线编码 */
    @ExcelProperty(value = "产线编码")
    private String productionLineCode;

    /** 设备编号 */
    @ExcelProperty(value = "设备编号")
    private String deviceNumber;

    /** 设备名称 */
    @ExcelProperty(value = "设备名称")
    private String deviceName;

    @ExcelProperty(value = "检测刀具编码")
    private String cutterCode;

    @ExcelProperty(value = "上刀左")
    private Integer cutterChangePositionUpperKnifeLeft;

    @ExcelProperty(value = "上刀中")
    private Integer cutterChangePositionUpperKnifeCenter;

    @ExcelProperty(value = "上刀右")
    private Integer cutterChangePositionUpperKnifeRight;

    @ExcelProperty(value = "下刀左")
    private Integer cutterChangePositionLowerKnifeLeft;

    @ExcelProperty(value = "下刀中")
    private Integer cutterChangePositionLowerKnifeCenter;

    @ExcelProperty(value = "下刀右")
    private Integer cutterChangePositionLowerKnifeRight;

    @ExcelProperty(value = "上刀左")
    private Integer accumulatedCuttingMetersUpperKnifeLeft;

    @ExcelProperty(value = "上刀中")
    private Integer accumulatedCuttingMetersUpperKnifeCenter;

    @ExcelProperty(value = "上刀右")
    private Integer accumulatedCuttingMetersUpperKnifeRight;

    @ExcelProperty(value = "下刀左")
    private Integer accumulatedCuttingMetersLowerKnifeLeft;

    @ExcelProperty(value = "下刀中")
    private Integer accumulatedCuttingMetersLowerKnifeCenter;

    @ExcelProperty(value = "下刀右")
    private Integer accumulatedCuttingMetersLowerKnifeRight;

    /** 换刀时间 */
    @JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @ExcelProperty(value = "换刀时间")
    @ColumnWidth(20)
    private Date cutterChangeTime;

    /** 上刀数 */
    @ExcelProperty(value = "上刀数")
    private Integer upperKnifeNumber;

    /** 下刀数 */
    @ExcelProperty(value = "下刀数")
    private Integer lowerKnifeNumber;

    @ExcelProperty(value = "更换人员")
    private String modifyUser;

    /** 备注 */
    @ExcelProperty(value = "备注")
    private String remark;

}

@ExcelIgnore :设置表格忽略该属性

@ColumnWidth(20): 设置列宽

controller代码

  @PostMapping("/export")
    public void export(HttpServletResponse response) throws Exception{
        List cutterControlList = cutterControlService.getCutterControlList();
        String fileName = System.getProperty("user.dir") + "/" + System.currentTimeMillis() + ".xlsx";
        // 构建ExcelWriter
        ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();
        // 构建sheet
        WriteSheet writeSheet = EasyExcel.writerSheet("切刀管控台账数据").head(CutterControl.class).build();
        // 写sheet
        excelWriter.write(cutterControlList, writeSheet);
        excelWriter.finish();
    }
结果:

2、自定义列合并策略

参考eastExcel文档可知,在实体类上添加属性即可实现我想要的效果

写Excel | Easy Excel

@Getter
@Setter
@EqualsAndHashCode
public class ComplexHeadData {
    @ExcelProperty({"主标题", "字符串标题"})
    private String string;
    @ExcelProperty({"主标题", "日期标题"})
    private Date date;
    @ExcelProperty({"主标题", "数字标题"})
    private Double doubleData;
}

再次照葫芦画瓢

@Getter
@Setter
public class CutterControl {

    /** 主键 */
    @ExcelIgnore
    private Long id;

    /** 工厂编码 */
    @ExcelProperty(value = "工厂编码")
    private String factoryCode;

    /** 产线编码 */
    @ExcelProperty(value = "产线编码")
    private String productionLineCode;

    /** 设备编号 */
    @ExcelProperty(value = "设备编号")
    private String deviceNumber;

    /** 设备名称 */
    @ExcelProperty(value = "设备名称")
    private String deviceName;

    @ExcelProperty(value = "检测刀具编码")
    private String cutterCode;

    @ExcelProperty({"换刀位置", "上刀左"})
    private Integer cutterChangePositionUpperKnifeLeft;

    @ExcelProperty({"换刀位置", "上刀中"})
    private Integer cutterChangePositionUpperKnifeCenter;

    @ExcelProperty({"换刀位置", "上刀右"})
    private Integer cutterChangePositionUpperKnifeRight;

    @ExcelProperty({"换刀位置", "下刀左"})
    private Integer cutterChangePositionLowerKnifeLeft;

    @ExcelProperty({"换刀位置", "下刀中"})
    private Integer cutterChangePositionLowerKnifeCenter;

    @ExcelProperty({"换刀位置", "下刀右"})
    private Integer cutterChangePositionLowerKnifeRight;

    @ExcelProperty({"累计分切米数", "上刀左"})
    private Integer accumulatedCuttingMetersUpperKnifeLeft;

    @ExcelProperty({"累计分切米数", "上刀中"})
    private Integer accumulatedCuttingMetersUpperKnifeCenter;

    @ExcelProperty({"累计分切米数", "上刀右"})
    private Integer accumulatedCuttingMetersUpperKnifeRight;

    @ExcelProperty({"累计分切米数", "下刀左"})
    private Integer accumulatedCuttingMetersLowerKnifeLeft;

    @ExcelProperty({"累计分切米数", "下刀中"})
    private Integer accumulatedCuttingMetersLowerKnifeCenter;

    @ExcelProperty({"累计分切米数", "下刀右"})
    private Integer accumulatedCuttingMetersLowerKnifeRight;

    /** 换刀时间 */
    @JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @ExcelProperty(value = "换刀时间")
    @ColumnWidth(20)
    private Date cutterChangeTime;

    /** 上刀数 */
    @ExcelProperty(value = "上刀数")
    private Integer upperKnifeNumber;

    /** 下刀数 */
    @ExcelProperty(value = "下刀数")
    private Integer lowerKnifeNumber;

    @ExcelProperty(value = "更换人员")
    private String modifyUser;

    /** 备注 */
    @ExcelProperty(value = "备注")
    private String remark;

}

其余不用修改

效果如下:

若需要导出excel在浏览器,修改Controller代码如下:

 @GetMapping("/export")
    public void export(HttpServletResponse response) throws Exception{
        List cutterControlList = cutterControlService.getCutterControlList();
        String fileName = new String("切刀管控台账数据.xlsx");
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName );

        EasyExcel.write(response.getOutputStream(),CutterControl.class)
                .sheet("切刀管控台账数据")
                .doWrite(cutterControlList);
    }

3、自定义行合并策略

具体业务暂时用不到,需要的可参考这个博客

https://www.cnblogs.com/monianxd/p/16359369.html

导入excel并处理同名列

由于实体类中存在excel列名重复的情况,所以如果不进行处理,会出现只有一个有值的情况,最简单的处理方式如下:

同名列添加所在位置的索引,默认从0开始

@Getter
@Setter
public class CutterControl {

    /** 主键 */
    @ExcelIgnore
    private Long id;

    /** 工厂编码 */
    @ExcelProperty(value = "工厂编码")
    private String factoryCode;

    /** 产线编码 */
    @ExcelProperty(value = "产线编码")
    private String productionLineCode;

    /** 设备编号 */
    @ExcelProperty(value = "设备编号")
    private String deviceNumber;

    /** 设备名称 */
    @ExcelProperty(value = "设备名称")
    private String deviceName;

    @ExcelProperty(value = "检测刀具编码")
    private String cutterCode;

    @ExcelProperty(value = {"换刀位置", "上刀左"},index = 5)
    private Integer cutterChangePositionUpperKnifeLeft;

    @ExcelProperty(value = {"换刀位置", "上刀中"},index = 6)
    private Integer cutterChangePositionUpperKnifeCenter;

    @ExcelProperty(value = {"换刀位置", "上刀右"},index = 7)
    private Integer cutterChangePositionUpperKnifeRight;

    @ExcelProperty(value = {"换刀位置", "下刀左"},index = 8)
    private Integer cutterChangePositionLowerKnifeLeft;

    @ExcelProperty(value = {"换刀位置", "下刀中"},index = 9)
    private Integer cutterChangePositionLowerKnifeCenter;

    @ExcelProperty(value = {"换刀位置", "下刀右"},index = 10)
    private Integer cutterChangePositionLowerKnifeRight;

    @ExcelProperty(value = {"累计分切米数", "上刀左"},index = 11)
    private Integer accumulatedCuttingMetersUpperKnifeLeft;

    @ExcelProperty(value = {"累计分切米数", "上刀中"},index = 12)
    private Integer accumulatedCuttingMetersUpperKnifeCenter;

    @ExcelProperty(value = {"累计分切米数", "上刀右"},index = 13)
    private Integer accumulatedCuttingMetersUpperKnifeRight;

    @ExcelProperty(value = {"累计分切米数", "下刀左"},index = 14)
    private Integer accumulatedCuttingMetersLowerKnifeLeft;

    @ExcelProperty(value = {"累计分切米数", "下刀中"},index = 15)
    private Integer accumulatedCuttingMetersLowerKnifeCenter;

    @ExcelProperty(value = {"累计分切米数", "下刀右"},index = 16)
    private Integer accumulatedCuttingMetersLowerKnifeRight;

    /** 换刀时间 */
    @JsonFormat(timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    @ExcelProperty(value = "换刀时间")
    @ColumnWidth(20)
    private Date cutterChangeTime;

    /** 上刀数 */
    @ExcelProperty(value = "上刀数")
    private Integer upperKnifeNumber;

    /** 下刀数 */
    @ExcelProperty(value = "下刀数")
    private Integer lowerKnifeNumber;

    @ExcelProperty(value = "更换人员")
    private String modifyUser;

    /** 备注 */
    @ExcelProperty(value = "备注")
    private String remark;

}

导入Controller代码

@PostMapping("/import")
    public R importData(@RequestParam(value = "file") MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        if (!(suffixName.equals(".xlsx"))) {
            return R.fail("请上传xlsx格式文件");
        }

        EasyExcel.read(file.getInputStream(), CutterControl.class, new ReadListener() {
            /**
             * 单次缓存的数据量
             */
            public static final int BATCH_COUNT = 100;
            /**
             *临时存储
             */
            private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

            @Override
            public void invoke(CutterControl data, AnalysisContext context) {
                cachedDataList.add(data);
                if (cachedDataList.size() >= BATCH_COUNT) {
                    saveData();
                    // 存储完成清理 list
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                saveData();
            }

            /**
             * 加上存储数据库
             */
            private void saveData() {
                cutterControlService.batchInsertCutterControl(cachedDataList);
                log.info("{}条数据,开始存储数据库!", cachedDataList.size());
                log.info("存储数据库成功!");
            }
        }).sheet().doRead();
        return R.ok();
    }

你可能感兴趣的:(java,excel,java,easyExcel)