最近的项目做导出,说是简单的项目,就选了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;
}
来源:oschina
链接:https://my.oschina.net/u/815005/blog/4706446