easyExcel一对多模板导出合并

不羁的心 提交于 2020-11-06 17:55:42

    最近的项目做导出,说是简单的项目,就选了easyExcel,没想到后来做了一对多复杂导出。看了一下api发现复杂的填充Excel也只是没有一对多的填充。看到easyPOI导出可以一对多导出,引入项目,调了一天,最后发现只能一在前,多在后才能正常点合并单元格,但是模板被改了(不知道是不是因为同时引入easyExcel和easyPOI导致的冲突,我复原到原来的一对一导出,模板还是被改了,后来取消引入easyPOI才正常)。后来百度了一下easyExcel一对多导出的,都没有找到比较仔细的步骤,后来发现了可以easyExcel可以自定义合并单元格,于是就开始写了。可能比较low。但是还是记录一下,说不定能帮上谁的忙。    图一是导出结果,图二是导出模板

图一

图二

先说说思路,这是一次模板填充导出。导出的时候填充的List对象是没有子类的对象List<ResetStatiExportDto> exportDtos,我们从数据库获取的(这里我用for循环填充就好了)一对多的对象是包含子类集合的List集合List<ResetStatiDto> statiDtos。下面是步骤:

一、我们拿到statiDtos后,先转成exportDtos作为填充Excel的数据。

二、自定义合并单元格策略,合并的列已经固定好,合并的行从statiDtos获取,如果有子类集合,并且该子类超过2条包含2条就可以合并了。

三、就可以导出了。

下面是代码

测试类 

@org.junit.jupiter.api.Test
	public void testExport(){
		List<ResetStatiDto> statiDtos = new ArrayList<>();
		for(int i=0; i<5; i++){
			ResetStatiDto statiDto = new ResetStatiDto();
			statiDto.setContractCode("SD-202011050"+i);
			statiDto.setLevyMan("欧阳"+i);
			statiDto.setOldBuildingArea("1"+i+"0.00");
			statiDto.setPayMoeny("1"+i+".00");
			statiDto.setResetBuildingArea("9"+i+".00");
			statiDto.setHouseArea("8"+i+".00");
			statiDto.setIndex(i);
			if(i==0||i==1||i==3){
				statiDto.setCompensateWay("产权调换");
				int k = 4-i;
				List<ResetStatiSubDto> subs = new ArrayList<>();
				for(int z=0; z<k; z++){
					ResetStatiSubDto sub = new ResetStatiSubDto();
					sub.setResettlementName("小测安置"+z);
					sub.setTotalBuildingArea("2"+z+".00");
					sub.setTotalHouseArea("1"+z+".00");
					subs.add(sub);
				}
				statiDto.setStatisSub(subs);
			}else{
				statiDto.setCompensateWay("货币补偿");
			}
			statiDtos.add(statiDto);
		}
		new MyTestServiceImpl().exprot(statiDtos);
	}

MyTestServiceImpl

@Override
    public void exprot(List<ResetStatiDto> statiDtos){
        // 获取导出项目非类表数据
        ExportOtherDto otherInfoDto = new ExportOtherDto();
        //导出没有子集合的数据
        List<ResetStatiExportDto> exportDtos = new ArrayList<>();
        // 补全数据序号及计算统计数据
        int index = 1;
        double resetBuildingAreaTotal = 0.00;
        double totalBuildingAreaTotal = 0.00;
        double payMoenyTotal = 0.00;
        for (ResetStatiDto dto : statiDtos) {
            dto.setIndex(index);
            if (StringUtils.isNotBlank(dto.getResetBuildingArea())) {
                resetBuildingAreaTotal += Double.parseDouble(dto.getResetBuildingArea());
            }
            if (StringUtils.isNotBlank(dto.getPayMoeny())) {
                payMoenyTotal += Double.parseDouble(dto.getPayMoeny());
            }
            List<ResetStatiSubDto> sub = dto.getStatisSub();
            if(CollectionUtils.isEmpty(sub)){
                ResetStatiExportDto exportDto = ConvertUtil.map(dto, ResetStatiExportDto.class);
                exportDtos.add(exportDto);
            }else{
                for (ResetStatiSubDto a : sub) {
                    //将有子集合的数据转成没有子集合的数据
                    ResetStatiExportDto exportDto = ConvertUtil.map(dto, ResetStatiExportDto.class);
                    exportDto.setResettlementName(a.getResettlementName());
                    exportDto.setTotalBuildingArea(a.getTotalBuildingArea());
                    exportDto.setTotalHouseArea(a.getTotalHouseArea());

                    exportDtos.add(exportDto);
                    if (StringUtils.isNotBlank(a.getTotalBuildingArea())) {
                        totalBuildingAreaTotal += Double.parseDouble(a.getTotalBuildingArea());
                    }
                }
            }
            index++;

        }
        otherInfoDto.setResetBuildingAreaTotal(resetBuildingAreaTotal);
        otherInfoDto.setTotalBuildingAreaTotal(totalBuildingAreaTotal);
        otherInfoDto.setPayMoenyTotal(payMoenyTotal);

        // 设置导出响应文件信息
        String fileName = otherInfoDto.getProjectName() + ".xlsx";
        // 导出
        ExcelWriter excelWriter = EasyExcel.write("D:/excel/"+fileName,ResetStatiExportDto.class)
                .registerWriteHandler(new MergeStrategy(statiDtos))
                .withTemplate("D:/excel/resettlement_statistics.xlsx").build();

        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        excelWriter.fill(exportDtos, fillConfig, writeSheet);
        excelWriter.fill(otherInfoDto, writeSheet);
        excelWriter.finish();
	}

MergeStrategy

/**
     * 合并策略
     */
	public static class MergeStrategy extends AbstractMergeStrategy {
		private List<ResetStatiDto> dtos;

		public MergeStrategy(List<ResetStatiDto> dtos) {
			this.dtos = dtos;
		}

		protected void merge(org.apache.poi.ss.usermodel.Sheet sheet, Cell cell, Head head, Integer integer) {
			//需要合并的列
			int[] columns = {0, 1, 2, 3, 4, 5, 7, 8};
			//从第九行开始填充
			if (cell.getRowIndex() == 8 && cell.getColumnIndex() == 0) {
                //第几行需要合并
				int startRow = 8;
				int endRow = 9;
				for (int i = 0; i < dtos.size(); i++) {
					ResetStatiDto dto = dtos.get(i);
					if (!CollectionUtils.isEmpty(dto.getStatisSub()) && dto.getStatisSub().size() > 1) {
						endRow = startRow + dto.getStatisSub().size() - 1;
						for (int c : columns) {
							sheet.addMergedRegionUnsafe(new CellRangeAddress(startRow,
									endRow, c, c));
						}
						startRow = endRow;
					}
					startRow++;
				}

			}
		}
	}

ResetStatiDto

@Getter
@Setter
@ToString
@EqualsAndHashCode
@Accessors(chain = true)
@ApiModel
public class ResetStatiDto {
    private static final long serialVersionUID = 3398108329936183500L;

    @ApiModelProperty(value = "回迁方式(实物/货币)1-产权调换,2-货币补偿")
    private String compensateWay;

    @ApiModelProperty(value = "合同号")
    private String contractCode;

    @ApiModelProperty(value = "被征收人")
    private String levyMan;

    @ApiModelProperty(value = "原房建筑面积(平方米)")
    private String oldBuildingArea;

    @ApiModelProperty(value = "货币补偿总金额(万元)")
    private String payMoeny;

    @ApiModelProperty(value = "安置房建筑面积(平方米)")
    private String resetBuildingArea;

    @ApiModelProperty(value = "安置房套内面积")
    private String houseArea;

    @ApiModelProperty(value = "序号(冗余字段,导出时使用)", hidden = true)
    private int index = 0;

    @ApiModelProperty(value = "实测安置房信息")
    private List<ResetStatiSubDto> statisSub;

}

ResetStatiSubDto

@Getter
@Setter
@ToString
@EqualsAndHashCode
@Accessors(chain = true)
@ApiModel
public class ResetStatiSubDto implements Serializable {
    private static final long serialVersionUID = 3398108329936183500L;

    @ApiModelProperty(value = "安置点")
    private String resettlementName;

    @ApiModelProperty(value = "实测建筑面积(平方米)")
    private String totalBuildingArea;

    @ApiModelProperty(value = "实测套内面积(平方米)")
    private String totalHouseArea;


}

ExportOtherDto

@Data
public class ExportOtherDto {
    @ApiModelProperty(name = "projectName", value = "征收项目名称")
    private String projectName="我是测试项目";

    @ApiModelProperty(name = "projectSeat", value = "项目具体坐落")
    private String projectSeat="贵阳市观山湖区";

    @ApiModelProperty(name = "draftingOrgName", value = "测绘调查机构")
    private String draftingOrgName="YYY测绘";

    @ApiModelProperty(name = "labourServiceOrgName", value = "征收劳务机构")
    private String labourServiceOrgName="WWW劳务";

    @ApiModelProperty(name = "investigatorOrgName", value = "评估机构")
    private String investigatorOrgName="QQ评估";

    @ApiModelProperty(name = "createAreaName", value = "所属区域名")
    private String createAreaName="观山湖区";

    @ApiModelProperty(value = "安置房建筑面积(平方米)合计")
    private double resetBuildingAreaTotal = 0.00;

    @ApiModelProperty(value = "实测建筑面积(平方米)合计")
    private double totalBuildingAreaTotal = 0.00;

    @ApiModelProperty(value = "货币补偿总金额(万元)合计")
    private double payMoenyTotal = 0.00;
}

ResetStatiExportDto

@Getter
@Setter
@ToString
@EqualsAndHashCode
@Accessors(chain = true)
@ApiModel
public class ResetStatiExportDto implements Serializable {
    private static final long serialVersionUID = 3398108329936183500L;

    @ApiModelProperty(value = "回迁方式(实物/货币)1-产权调换,2-货币补偿")
    private String compensateWay;

    @ApiModelProperty(value = "合同号")
    private String contractCode;

    @ApiModelProperty(value = "被征收人")
    private String levyMan;

    @ApiModelProperty(value = "原房建筑面积(平方米)")
    private String oldBuildingArea;

    @ApiModelProperty(value = "货币补偿总金额(万元)")
    private String payMoeny;

    @ApiModelProperty(value = "安置房建筑面积(平方米)")
    private String resetBuildingArea;

    @ApiModelProperty(value = "安置房套内面积")
    private String houseArea;

    @ApiModelProperty(value = "安置点")
    private String resettlementName;

    @ApiModelProperty(value = "实测建筑面积(平方米)")
    private String totalBuildingArea;

    @ApiModelProperty(value = "实测套内面积(平方米)")
    private String totalHouseArea;

    @ApiModelProperty(value = "实测公摊系数")
    private String actualFactor;

    @ApiModelProperty(value = "序号(冗余字段,导出时使用)", hidden = true)
    private int index = 0;

    @ApiModelProperty(value = "")
    private String landNatureName;

    @ApiModelProperty(value = "备注")
    private String remark;

}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!