使用Hutool的ExcelWriter实现Excel循环主次标题导出


业务效果图

业务部分源码


@Service
@Slf4j
public class ExamineServiceImpl implements ExamineService {

	// ---------------------------------------- 提交汇总报表导出 start --------------------------------------------------

	/**
	 * 提交汇总报表导出
	 **/
	@Override
	public void exportTotal(User userInfo, ResExportRequest request, HttpServletResponse response) {
		// RETRIEVE DATA
		ResExportVo resExportVo = exportData(request);
		// EXPORT DATA IN EXCEL STYLE
		String title = resExportVo.getAreaName() + "(乡镇)糖料蔗作业补助情况公示表";
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
		response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(title));
		OutputStream out = null;
		try {
//            BigExcelWriter bigWriter = ExcelUtil.getBigWriter("d:/writeBeanTest.xlsx");
			ExcelWriter bigWriter = ExcelUtil.getBigWriter();
			setContextCellStyle(bigWriter);
			setExcelHeader(resExportVo, bigWriter);
			List multiItemVo = resExportVo.getMultiItemVo();
			int fixHeaderHeight = FIX_HEADER_HEIGHT;
			for (SingleItemVo singleItemVo : multiItemVo) {
				setEachMainHeader(bigWriter, fixHeaderHeight);
				fixHeaderHeight++;
				setEachMainHeaderParam(bigWriter, fixHeaderHeight, singleItemVo.getMainHeaderVo());
				fixHeaderHeight++;
				setEachSecondHeader(bigWriter, fixHeaderHeight);
				fixHeaderHeight++;
				setEachSecondHeaderParam(bigWriter, fixHeaderHeight, singleItemVo.getSecondHeaderVos());
				fixHeaderHeight += singleItemVo.getSecondHeaderVos().size();
			}
			out = response.getOutputStream();
			bigWriter.flush(out, true);
			bigWriter.close();
		} catch (IOException e) {
			throw new BizzException(ResponseCode.FAILED.getCode(), title + "导出失败");
		} finally {
			IoUtil.close(out);
		}

	}

	/**
	 * 申报审核-导出报表
	 * */
	@Override
	public void exportAudit(List declareNos, HttpServletResponse response) {
		// PACKAGE PARAM AND RETRIEVE DATA
		// List declareNos = new ArrayList<>(Arrays.asList("DEC4512022058322038918", "DEC45132310413220511825"));
		List subsidyDeclares = exportAuditData(declareNos);
		subsidyDeclares.forEach(System.out::println);

		// PROCESS EXPORT DATA
		processData(subsidyDeclares);

		double sumWorkload = subsidyDeclares.stream().mapToDouble(e -> Double.parseDouble(e.getWorkLoad())).sum();
		double sumSubsidyMoney = subsidyDeclares.stream().mapToDouble(e -> Double.parseDouble(e.getSubsidyMoney())).sum();

		log.info("[SubsidyDeclareServiceImpl][workRecordExcelExport] sumWorkload: {}, sumSubsidyMoney: {}", sumWorkload, sumSubsidyMoney);
		log.info("[SubsidyDeclareServiceImpl][workRecordExcelExport] itemList: {}", subsidyDeclares);

		Map param = new HashMap<>();
		param.put("itemList", subsidyDeclares);
		param.put("sumWorkload", sumWorkload);
		param.put("sumSubsidyMoney", sumSubsidyMoney);

		try {
			TemplateExcelUtils.downLoadExcel("糖料蔗机械化作业补贴申报表", "糖料蔗机械化作业补贴申报表模板.xlsx", param, response);
		} catch (Exception e) {
			throw new ServiceException("Excel Import Error!");
		}
	}

	private void processData(List subsidyDeclares) {
		int i = 0;
		for (SubsidyDeclare d : subsidyDeclares) {
			d.setNo(++i);
			d.setWorkName(sysBaseService.ofWorkType(d.getWorkType()));
			d.setWorkTime(new SimpleDateFormat("yyyy-MM-dd").format(d.getWorkDate()));
			if (!d.getWorkTon().equals("0.00")) {
				d.setWorkLoad(d.getWorkTon());
			} else {
				d.setWorkLoad(d.getMArea());
			}
		}
	}

	public List exportAuditData(List declareNos) {

		// PACKAGE QUERY PARAM
		List records = declareNos.stream().map(e -> {
			SubsidyDeclare sdr = new SubsidyDeclare();
			sdr.setDeclareNo(e);
			return sdr;
		}).collect(Collectors.toList());

		// RETRIEVE DATA FROM DATABASE BY PARAM
		List> collect = records.stream().map(e -> {
			List gamDeclareRels = gamDeclareRelMapper.querySubsidyList(e);
			int i = 0;
			for (SubsidyDeclare d : gamDeclareRels) {
				d.setNo(++i);
				d.setWorkName(sysBaseService.ofWorkType(d.getWorkType()));
				d.setWorkTime(new SimpleDateFormat("yyyy-MM-dd").format(d.getWorkDate()));
				if (!d.getWorkTon().equals("0.00")) {
					d.setWorkLoad(d.getWorkTon());
				} else {
					d.setWorkLoad(d.getMArea());
				}
			}
			return gamDeclareRels;
		}).collect(Collectors.toList());

		// GENERATE RESULT DATA
		List totalRecords = new ArrayList<>();
		collect.forEach(totalRecords::addAll);

		return totalRecords;
	}


	public ResExportVo exportData(ResExportRequest request) {
		List erVos1 = request.getErVos();
		List areaCodes = erVos1.stream().map(ExportRequestVo::getAreaCode).collect(Collectors.toList());
		Set set1 = new HashSet(areaCodes);
		if (set1.size() > 1) {
			log.warn("一次只能导出一个乡镇的公示数据");
			throw new ServiceException("一次只能导出一个乡镇的公示数据");
		}
		String areaCode = set1.stream().findFirst().get();
		ResExportVo resExportVo = new ResExportVo();
		setCommonInfo(resExportVo, areaCode);
		List multiItemVos = erVos1.stream()
				.map(e -> getSingleItemVo(e.getBatchNo(), e.getSubBatchNo(), e.getOfficeCode()))
				.collect(Collectors.toList());
		log.warn("multiItemVos: {}", multiItemVos);
		resExportVo.setMultiItemVo(multiItemVos);
		log.info("[PublicityServiceTest][exportTest] resExportVo: {}", resExportVo);
		return resExportVo;
	}

	private void setCommonInfo(ResExportVo exportVo, String areaCode) {
		// 制表单位:
		String areaName = sysBaseService.ofArea(areaCode);
		// 制表日期
		String currentDate = DateUtil.date().toString("yyyy年MM月dd日");
		log.info("areaName: {} , currentDate: {}", areaName, currentDate);
		exportVo.setAreaName(areaName);
		exportVo.setCurrentDate(currentDate);
	}

	private SingleItemVo getSingleItemVo(String batchNo, String subBatchNo, String officeCode) {
		SingleItemVo singleItemVo = new SingleItemVo();
		// 对多个officeCode进行判断,如果officeCode不一样则进行错误回显 "一次只能导出一个乡镇的公示数据"
		PubPageRequest pubPageRequest = new PubPageRequest();
		pubPageRequest.setBatchNo(batchNo);
		pubPageRequest.setSumBatchNo(subBatchNo);
		PubDetailVo pdVo = gamPublicityMapper.queryPubPageForExport(pubPageRequest);
		if (Objects.isNull(pdVo)) {
			throw new ServiceException("当前批次号为: " + batchNo + "无相关记录!");
		}
		MainHeaderVo mainHeaderVo = new MainHeaderVo();
		mainHeaderVo.setPubBatchNo(pdVo.getBatchNo());// 公示批次编号
		mainHeaderVo.setAreaName(sysBaseService.ofArea(pdVo.getAreaCode()));// 所属乡镇
		mainHeaderVo.setOfficeName(sysBaseService.ofOffice(pdVo.getOfficeCode())); // 单位名称
		mainHeaderVo.setWorkTypeName(sysBaseService.ofWorkType(pdVo.getWorkType())); // 作业类型
		mainHeaderVo.setSumWorkArea(pdVo.getWArea()); // 作业面积
		mainHeaderVo.setSumWorkload(pdVo.getWorkTon()); // 作业量
		mainHeaderVo.setSumQArea(pdVo.getQArea()); // 合格面积

		mainHeaderVo.setSubsidyMoney(pdVo.getSubsidyMoney()); // 补贴金额

		// -------------------------------------------------------------------------------
		ExaPageRequest request = new ExaPageRequest();
		request.setOfficeCode(officeCode);
		request.setPubBatchNo(batchNo);
		List rets = gamDeclareRelMapper.queryDeclarePageListForExport(request);
		if(CollectionUtils.isEmpty(rets)){
			throw new ServiceException("公示批次号为: " + batchNo + "行政编码为: " + officeCode + "暂无数据!");
		}
		List shVos = new ArrayList();
		for (int i = 0; i < rets.size(); i++) {
			SecondHeaderVo shVo = new SecondHeaderVo();
			shVo.setNo(i + 1); // 序号
			shVo.setOwnerAndPhone(rets.get(i).getOwnerName()); // 车主
			shVo.setDeviceId(rets.get(i).getDeviceId()); // 设备号
			if (StringUtils.isNotBlank(rets.get(i).getTraceNo())) {
				shVo.setTraceNoOrReceipt(rets.get(i).getTraceNo()); // 轨迹图编号
			} else {
				shVo.setTraceNoOrReceipt(rets.get(i).getReceipt()); // 糖企收据编号
			}
			shVo.setWArea(rets.get(i).getWArea()); // 作业面积(亩)
			shVo.setWorkTon(rets.get(i).getWorkTon()); // 作业量
			shVo.setQArea(rets.get(i).getQArea()); // 合格面积
			shVo.setSubsidyStandard(rets.get(i).getSubsidyStandard() + "元/亩"); // 补贴标准
			shVo.setSubsidyMoney(Objects.isNull(rets.get(i).getSubsidyMoney()) ? new BigDecimal("0") : rets.get(i).getSubsidyMoney());
			shVo.setWorkDate(rets.get(i).getWorkTime()); // 作业时间
			shVo.setLocation(rets.get(i).getLocation()); // 作业地点
			shVos.add(shVo);
		}
		singleItemVo.setSecondHeaderVos(shVos);
		mainHeaderVo.setSubsidyStandard(rets.get(0).getSubsidyStandard() + "元/亩"); // 补贴标准
		singleItemVo.setMainHeaderVo(mainHeaderVo);
		return singleItemVo;
	}

	private PubDetailVo parseRets(PubDetailVo r) {
		PubDetailVo response = new PubDetailVo();
		BeanUtils.copyProperties(r, response);
		response.setStatusName(PublicityStatusEnum.toText(r.getStatusFlag()));
		response.setMArea(r.getQArea().subtract(r.getRArea()));
		response.setName(sysBaseService.ofOffice(r.getOfficeCode()));
		response.setWorkTypeName(sysBaseService.ofWorkType(r.getWorkType()));
		response.setAreaName(sysBaseService.ofArea(r.getAreaCode()));
		if (PublicityStatusEnum.PUB_ING.equals(PublicityStatusEnum.of(r.getStatusFlag()))) {
			response.setPeriod(org.apache.commons.lang3.StringUtils.join(r.getStartTime(), "-", r.getEndTime()));
		}
		return response;
	}


	private void setContextCellStyle(ExcelWriter writer) {
		StyleSet styleSet = writer.getStyleSet();
		CellStyle cellStyle = styleSet.getCellStyle();
		cellStyle.setWrapText(true);
	}

	private void setExcelHeader(ResExportVo resExportVo, ExcelWriter writer) {
		writer.merge(0, 0, 0, 10, resExportVo.getAreaName() + "(乡镇)糖料蔗作业补助情况公示", false);
		writer.setRowHeight(0, 40);
		writer.merge(1, 1, 0, 3, "制表单位:" + resExportVo.getAreaName() + "乡镇", false);
		writer.merge(1, 1, 4, 10, "制表日期:" + resExportVo.getCurrentDate(), false);
		setHeaderStyle(writer);
	}

	private void setHeaderStyle(ExcelWriter writer){
		Font fontHeader = writer.createFont();
		fontHeader.setBold(true);
		fontHeader.setFontHeight((short)450);

		CellStyle cellStyle = writer.createCellStyle(0, 0);
		cellStyle.setAlignment(HorizontalAlignment.CENTER);
		cellStyle.setFont(fontHeader);

		CellStyle cellStyle1 = writer.createCellStyle(0, 1);
		cellStyle1.setAlignment(HorizontalAlignment.CENTER);
		Font font01 = writer.createFont();
		font01.setBold(true);
		cellStyle1.setFont(font01);

		CellStyle cellStyle2 = writer.createCellStyle(4, 1);
		cellStyle2.setAlignment(HorizontalAlignment.CENTER);
		Font font02 = writer.createFont();
		font02.setBold(true);
		cellStyle2.setFont(font02);
	}

	private void setEachMainHeader(ExcelWriter writer, int i) {
		// column, row, value
		writer.writeCellValue(1, i, "所属乡镇");
		writer.writeCellValue(2, i, "单位名称");
		writer.writeCellValue(3, i, "作业类型");
		writer.writeCellValue(4, i, "作业面积(亩)");
		writer.writeCellValue(5, i, "作业量(吨)");
		writer.writeCellValue(6, i, "合格面积");
		writer.writeCellValue(7, i, "补贴标准");
		writer.merge(i, i, 8, 10, "补贴金额", false);

		// set cell style
		setEachMainHeaderStyle(writer, i);

		setMainHeaderColumnWidthWithFixPoint(writer);
	}

	private void setMainHeaderColumnWidthWithFixPoint(ExcelWriter writer) {
		writer.setColumnWidth(0, 20);
		writer.setColumnWidth(1, 20);
		writer.setColumnWidth(2, 20);
		writer.setColumnWidth(3, 20);
		writer.setColumnWidth(4, 20);
		writer.setColumnWidth(5, 20);
		writer.setColumnWidth(6, 20);
		writer.setColumnWidth(7, 20);
		writer.setColumnWidth(8, 50);
	}

	private void setCellStyleWithFixPoint(ExcelWriter writer, int x, int y){
		CellStyle cellStyle= writer.createCellStyle(x, y);
		cellStyle.setAlignment(HorizontalAlignment.CENTER);
		Font font= writer.createFont();
		font.setBold(true);
		cellStyle.setFont(font);
	}

	private void setEachMainHeaderStyle(ExcelWriter writer, int i) {
		setCellStyleWithFixPoint(writer, 0, i);
		setCellStyleWithFixPoint(writer, 1, i);
		setCellStyleWithFixPoint(writer, 2, i);
		setCellStyleWithFixPoint(writer, 3, i);
		setCellStyleWithFixPoint(writer, 4, i);
		setCellStyleWithFixPoint(writer, 5, i);
		setCellStyleWithFixPoint(writer, 6, i);
		setCellStyleWithFixPoint(writer, 7, i);
		setCellStyleWithFixPoint(writer, 8, i);
	}

	private void setMainHeaderAndParamStyle(ExcelWriter writer, int i) {
		// 根据row设置单元格样式
		CellStyle rowStyle = writer.createRowStyle(i);
		// 内容居左
//		rowStyle.setAlignment(HorizontalAlignment.LEFT);
		// 内容背景颜色
		rowStyle.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
		// 字体格式
		Font font = writer.createFont();
		font.setBold(true);
		rowStyle.setFont(font);
	}

	private void setEachMainHeaderParam(ExcelWriter writer, int i, MainHeaderVo vo) {
		// column, row, value
		writer.writeCellValue(0, i, vo.getPubBatchNo());
		writer.writeCellValue(1, i, vo.getAreaName());
		writer.writeCellValue(2, i, vo.getOfficeName());
		writer.writeCellValue(3, i, vo.getWorkTypeName());
		writer.writeCellValue(4, i, vo.getSumWorkArea());
		writer.writeCellValue(5, i, vo.getSumWorkload());
		writer.writeCellValue(6, i, vo.getSumQArea());
		writer.writeCellValue(7, i, vo.getSubsidyStandard());
		writer.merge(i, i, 8, 10, vo.getSubsidyMoney(), false);

		// 根据row设置单元格样式
		setMainHeaderAndParamStyle(writer, i);

	}

	private void setEachSecondHeader(ExcelWriter writer, int i) {
		// column, row, value
		writer.writeCellValue(0, i, "序号");
		writer.writeCellValue(1, i, "车主");
		writer.writeCellValue(2, i, "设备号");
		writer.writeCellValue(3, i, "轨迹图编号/糖企收据编号/回收企业编号");
		writer.writeCellValue(4, i, "作业面积(亩)");
		writer.writeCellValue(5, i, "作业量(吨)");
		writer.writeCellValue(6, i, "合格面积(亩)");
		writer.writeCellValue(7, i, "补贴标准");
		writer.writeCellValue(8, i, "补贴金额");
		writer.writeCellValue(9, i, "作业时间");
		writer.writeCellValue(10, i, "作业地点");

		setEachSecondHeaderStyle(writer, i);

		setSecondHeaderColumnWidthWithFixPoint(writer);
	}

	private void setSecondHeaderColumnWidthWithFixPoint(ExcelWriter writer) {
		writer.setColumnWidth(0, 20);
		writer.setColumnWidth(1, 20);
		writer.setColumnWidth(2, 20);
		writer.setColumnWidth(3, 20);
		writer.setColumnWidth(4, 20);
		writer.setColumnWidth(5, 20);
		writer.setColumnWidth(6, 20);
		writer.setColumnWidth(7, 20);
		writer.setColumnWidth(8, 20);
		writer.setColumnWidth(9, 20);
		writer.setColumnWidth(10, 20);
	}

	private void setEachSecondHeaderStyle(ExcelWriter writer, int i) {
		setCellStyleWithFixPoint(writer, 0, i);
		setCellStyleWithFixPoint(writer, 1, i);
		setCellStyleWithFixPoint(writer, 2, i);
		setCellStyleWithFixPoint(writer, 3, i);
		setCellStyleWithFixPoint(writer, 4, i);
		setCellStyleWithFixPoint(writer, 5, i);
		setCellStyleWithFixPoint(writer, 6, i);
		setCellStyleWithFixPoint(writer, 7, i);
		setCellStyleWithFixPoint(writer, 8, i);
		setCellStyleWithFixPoint(writer, 9, i);
		setCellStyleWithFixPoint(writer, 10, i);
	}


	private void setEachSecondHeaderParam(ExcelWriter writer, int i, List vos) {
		for (int x = 0; x < vos.size(); x++) {
			// column, row, value
			writer.writeCellValue(0, (i + x), "" + (x + 1));
			writer.writeCellValue(1, (i + x), vos.get(x).getOwnerAndPhone());
			writer.writeCellValue(2, (i + x), vos.get(x).getDeviceId());
			writer.writeCellValue(3, (i + x), vos.get(x).getTraceNoOrReceipt());
			writer.writeCellValue(4, (i + x), vos.get(x).getWArea());
			writer.writeCellValue(5, (i + x), vos.get(x).getWorkTon());
			writer.writeCellValue(6, (i + x), vos.get(x).getQArea());
			writer.writeCellValue(7, (i + x), vos.get(x).getSubsidyStandard());
			writer.writeCellValue(8, (i + x), vos.get(x).getSubsidyMoney());
			writer.writeCellValue(9, (i + x), vos.get(x).getWorkDate());
			writer.writeCellValue(10, (i + x), vos.get(x).getLocation());
		}
	}

	// ---------------------------------------- 提交汇总报表导出 end--------------------------------------------------


	private ExaDetailVo parseRets(ExaDetailVo vo, Map workTypeMaps) {
		ExaDetailVo response = new ExaDetailVo();
		BeanUtils.copyProperties(vo, response);
		response.setStatusName(DeclareStatusEnum.toText(vo.getStatusFlag()));
		if (DeclareTypeEnum.MU.equals(DeclareTypeEnum.of(vo.getDeclareType())) &&
				Objects.nonNull(vo.getMuArea()) && vo.getMuArea().compareTo(BigDecimal.ZERO) > 0) {
			response.setWArea(vo.getMuArea());
			response.setQArea(vo.getMuArea());
			response.setRArea(BigDecimal.ZERO);
			if (Objects.nonNull(response.getQArea()) && Objects.nonNull(response.getRArea())) {
				response.setMArea(response.getQArea().subtract(response.getRArea()));
			}
		}

		if (DeclareTypeEnum.WORK.equals(DeclareTypeEnum.of(vo.getDeclareType()))
				&& Objects.nonNull(vo.getQArea()) && Objects.nonNull(vo.getRArea())) {
			response.setMArea(vo.getQArea().subtract(vo.getRArea()));
		}

		if (DeclareTypeEnum.TON.equals(DeclareTypeEnum.of((vo.getDeclareType())))) {
			response.setTraceNo(vo.getReceipt());
			// TODO cxf 按吨计算面积健壮性
			if (Objects.nonNull(vo.getQArea())) {
				if (Objects.nonNull(vo.getRArea())) {
					response.setMArea(vo.getQArea().subtract(vo.getRArea()));
				} else {
					response.setMArea(vo.getQArea());
				}
			} else {
				log.error("[ExamineServiceImpl][parseRets]按吨申报未获取到面积数据,ExaDetailVo={}", JSON.toJSONString(vo));
			}

		}
		response.setAreaName(sysBaseService.ofArea(vo.getAreaCode()));
		response.setName(sysBaseService.ofOffice(vo.getOfficeCode()));
		if (Objects.nonNull(workTypeMaps)) {
			response.setWorkTypeName(workTypeMaps.get(vo.getWorkType()));
		}

		response.setDeclareType(vo.getDeclareType());
		response.setDeclareTypeName(DeclareTypeEnum.toText(vo.getDeclareType()));
		if (StringUtils.isNotEmpty(vo.getOwnerName()) || StringUtils.isNotEmpty(vo.getOwnerPhone())) {
			response.setOwner(vo.getOwnerName() + "/" + vo.getOwnerPhone());
		}

		//if (BigDecimal.ZERO.compareTo(vo.getSubsidyMoney()) == 0) {
		//    response.setSubsidyMoney(vo.getSumSubsidyMoney());
		//}

		if (DeclareTypeEnum.of(vo.getDeclareType()).equals(DeclareTypeEnum.WORK)
				|| (DeclareTypeEnum.of(vo.getDeclareType()).equals(DeclareTypeEnum.TON)
				&& DeclareWayEnum.of(vo.getDeclareWay()).equals(DeclareWayEnum.GLGJ))) {
			response.setAnalyseRepeat(AnalyseRepeatEnum.YES.getCode());
		}

		//如果重复面积小于0,则置为0
		if (response.getMArea() != null && response.getMArea().compareTo(BigDecimal.ZERO) < 0) {
			response.setMArea(BigDecimal.ZERO);
		}

		return response;
	}

	private List doRets(List vos) {
		String ret = vos.get(0).getStatusFlag();
		if (DeclareStatusEnum.TO_EXA.equals(DeclareStatusEnum.of(ret))) {
			ExaStatVo voPub = new ExaStatVo();
			voPub.setStatusFlag(DeclareStatusEnum.TO_PUB.getCode());
			voPub.setStatusName(DeclareStatusEnum.TO_PUB.getName());
			voPub.setAmount(BigDecimal.ZERO);
			voPub.setCount(0);
			voPub.setWArea(BigDecimal.ZERO);
			voPub.setQArea(BigDecimal.ZERO);
			voPub.setRArea(BigDecimal.ZERO);
			voPub.setMArea(BigDecimal.ZERO);
			vos.add(voPub);
			return vos;
		} else {
			List rets = new ArrayList<>();
			ExaStatVo voExa = new ExaStatVo();
			voExa.setStatusFlag(DeclareStatusEnum.TO_EXA.getCode());
			voExa.setStatusName(DeclareStatusEnum.TO_EXA.getName());
			voExa.setAmount(BigDecimal.ZERO);
			voExa.setCount(0);
			voExa.setWArea(BigDecimal.ZERO);
			voExa.setQArea(BigDecimal.ZERO);
			voExa.setRArea(BigDecimal.ZERO);
			voExa.setMArea(BigDecimal.ZERO);
			rets.add(voExa);
			rets.addAll(vos);
			return rets;
		}
	}

	private List init() {
		List vos = new ArrayList<>();
		ExaStatVo voExa = new ExaStatVo();
		voExa.setStatusFlag(DeclareStatusEnum.TO_EXA.getCode());
		voExa.setStatusName(DeclareStatusEnum.TO_EXA.getName());
		voExa.setAmount(BigDecimal.ZERO);
		voExa.setCount(0);
		vos.add(voExa);

		ExaStatVo voPub = new ExaStatVo();
		voPub.setStatusFlag(DeclareStatusEnum.TO_PUB.getCode());
		voPub.setStatusName(DeclareStatusEnum.TO_PUB.getName());
		voPub.setAmount(BigDecimal.ZERO);
		voPub.setCount(0);
		vos.add(voPub);
		return vos;
	}

	private MoneyTonMuVo getMoneyTonMu(List vos, List rels) {
		if (CollectionUtils.isEmpty(vos) || CollectionUtils.isEmpty(rels)) {
			log.error("[ExamineServiceImpl][getMoneyTonMu]计算面积异常,vos={}", JSON.toJSONString(vos));
			throw new BizzException(CloudResponseCode.NO_DATA.getCode(), "申报数据异常");
		}
		MoneyTonMuVo vo = new MoneyTonMuVo();

		BigDecimal subsidyMoney = rels.stream().map(GamDeclareRel::getSubsidyMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
		vo.setSubsidyMoney(subsidyMoney);
		vo.setWorkType(vos.get(0).getWorkType());

		Map> declareMaps
				= vos.stream().collect(Collectors.groupingBy(GamDeclare::getDeclareType));
		Map> declareRelMaps
				= rels.stream().collect(Collectors.groupingBy(GamDeclareRel::getDeclareType));
		if (declareMaps.containsKey(DeclareTypeEnum.MU.getCode())) {
			List mus = declareMaps.get(DeclareTypeEnum.MU.getCode());
			BigDecimal wArea = mus.stream().map(GamDeclare::getWorkArea).reduce(BigDecimal.ZERO, BigDecimal::add);
			vo.setMuArea(wArea);
		}
		MoneyTonMuVo tonVo = new MoneyTonMuVo();
		if (declareMaps.containsKey(DeclareTypeEnum.TON.getCode())) {
			List tons = declareMaps.get(DeclareTypeEnum.TON.getCode());
			BigDecimal workTon = tons.stream().map(GamDeclare::getWorkTon).reduce(BigDecimal.ZERO, BigDecimal::add);
			vo.setWorkTon(workTon);
			GamDeclare traceOne = tons.stream()
					.filter(r -> DeclareWayEnum.of(r.getDeclareWay()).equals(DeclareWayEnum.GLGJ))
					.findFirst().orElse(null);
			if (Objects.nonNull(traceOne)) {
				List tonRels = declareRelMaps.get(DeclareTypeEnum.TON.getCode());
				Triple relAreas = getAreaByRels(tonRels);
				if (Objects.nonNull(relAreas)) {
					tonVo.setWArea(relAreas.getLeft());
					tonVo.setQArea(relAreas.getMiddle());
					tonVo.setRArea(relAreas.getRight());
				}
			}
		}

		if (declareMaps.containsKey(DeclareTypeEnum.WORK.getCode())) {
			List workRels = declareRelMaps.get(DeclareTypeEnum.WORK.getCode());
			Triple relAreas = getAreaByRels(workRels);
			if (Objects.nonNull(relAreas)) {
				vo.setWArea(relAreas.getLeft());
				vo.setQArea(relAreas.getMiddle());
				vo.setRArea(relAreas.getRight());
				vo.setMArea(vo.getQArea().subtract(vo.getRArea()));
			}
		}

		cacl(vo, tonVo);
		return vo;
	}

	public Triple getAreaByRels(List rels) {
		List plotIds = rels.stream()
				.map(GamDeclareRel::getPlotId).collect(Collectors.toList());
		List plots = plotService.getPlots(plotIds);
		if (CollectionUtils.isEmpty(plots)) {
			log.error("[ExamineServiceImpl][getMoneyTonMu]未获取到地块数据,plotIds={}", JSON.toJSONString(plotIds));
			return null;
		}

		BigDecimal wArea = plots.stream().map(TbWorkplot::getWArea).reduce(BigDecimal.ZERO, BigDecimal::add);
		BigDecimal qArea = plots.stream().map(TbWorkplot::getQArea).reduce(BigDecimal.ZERO, BigDecimal::add);
		BigDecimal rArea = plots.stream().map(TbWorkplot::getRArea).reduce(BigDecimal.ZERO, BigDecimal::add);

		return Triple.of(wArea, qArea, rArea);
	}


	private void cacl(MoneyTonMuVo vo, MoneyTonMuVo tonVo) {
		BigDecimal muWArea = BigDecimal.ZERO;
		BigDecimal muQArea = BigDecimal.ZERO;
		BigDecimal muRArea = BigDecimal.ZERO;

		BigDecimal workWArea = BigDecimal.ZERO;
		BigDecimal workQArea = BigDecimal.ZERO;
		BigDecimal workRArea = BigDecimal.ZERO;

		BigDecimal tonWArea = BigDecimal.ZERO;
		BigDecimal tonQArea = BigDecimal.ZERO;
		BigDecimal tonRArea = BigDecimal.ZERO;

		if (Objects.nonNull(vo.getMuArea())) {
			muWArea = vo.getMuArea();
			muQArea = vo.getMuArea();
		}
		if (Objects.nonNull(tonVo)) {
			if (Objects.nonNull(tonVo.getWArea())) {
				tonWArea = tonVo.getWArea();
			}
			if (Objects.nonNull(tonVo.getQArea())) {
				tonQArea = tonVo.getQArea();
			}

			if (Objects.nonNull(tonVo.getRArea())) {
				tonRArea = tonVo.getRArea();
			}
		}

		if (Objects.nonNull(vo.getWArea())) {
			workWArea = vo.getWArea();
		}
		if (Objects.nonNull(vo.getQArea())) {
			workQArea = vo.getQArea();
		}
		if (Objects.nonNull(vo.getRArea())) {
			workRArea = vo.getRArea();
		}

		vo.setWArea(muWArea.add(workWArea).add(tonWArea));
		vo.setQArea(muQArea.add(workQArea).add(tonQArea));
		vo.setRArea(muRArea.add(workRArea).add(tonRArea));
		vo.setMArea(vo.getQArea().subtract(vo.getRArea()));
	}





}