From d21636425e2c593adca56d6c0c4763ad64bddbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E4=B8=89=E7=82=AE?= <15856818120@163.com> Date: Thu, 22 Jan 2026 18:25:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E8=A2=AB=E8=A6=86=E7=9B=96?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/mybatis/cost/ProjectCostMapper.xml | 196 ++++---- .../cost/beans/ProjectLeaseCostDetail.java | 92 +++- .../cost/service/ProjectCostServiceImpl.java | 460 +++++++++++++++--- 3 files changed, 588 insertions(+), 160 deletions(-) diff --git a/resources/mybatis/cost/ProjectCostMapper.xml b/resources/mybatis/cost/ProjectCostMapper.xml index ba90d0e..236d4b8 100644 --- a/resources/mybatis/cost/ProjectCostMapper.xml +++ b/resources/mybatis/cost/ProjectCostMapper.xml @@ -4,23 +4,25 @@ + insert into wf_project_settlement_details( - ID, - SETTLEMENT_ID, - OPERATE_TYPE, - MACHINE_TYPE_ID, - MACHINE_TYPE_NAME, - MACHINE_CODE, - MACHINE_MODEL, - MACHINE_UNIT, - PRICE, - LEASE_NUM, - RETURN_NUM, - LEASE_UNIT, - OPERATE_PERSON_NAME, - OPERATE_DATE, - TASK_CODE + ID, + SETTLEMENT_ID, + OPERATE_TYPE, + MACHINE_TYPE_ID, + MACHINE_TYPE_NAME, + MACHINE_CODE, + MACHINE_MODEL, + MACHINE_UNIT, + PRICE, + LEASE_NUM, + RETURN_NUM, + LEASE_UNIT, + OPERATE_PERSON_NAME, + OPERATE_DATE, + TASK_CODE ) values - - ( - #{item.id}, - #{item.settlementId}, - #{item.operateType}, - #{item.machineTypeId}, - #{item.machineTypeName}, - #{item.machineCode}, - #{item.machineModel}, - #{item.machineUnit}, - #{item.price}, - #{item.leaseNum}, - #{item.returnNum}, - #{item.leaseUnit}, - #{item.operatePersonName}, - #{item.operateDate}, - #{item.taskCode} - ) - + + ( + #{item.id}, + #{item.settlementId}, + #{item.operateType}, + #{item.machineTypeId}, + #{item.machineTypeName}, + #{item.machineCode}, + #{item.machineModel}, + #{item.machineUnit}, + #{item.price}, + #{item.leaseNum}, + #{item.returnNum}, + #{item.leaseUnit}, + #{item.operatePersonName}, + #{item.operateDate}, + #{item.taskCode} + ) + - \ No newline at end of file + diff --git a/src/com/bonus/cost/beans/ProjectLeaseCostDetail.java b/src/com/bonus/cost/beans/ProjectLeaseCostDetail.java index dc040aa..33e7777 100644 --- a/src/com/bonus/cost/beans/ProjectLeaseCostDetail.java +++ b/src/com/bonus/cost/beans/ProjectLeaseCostDetail.java @@ -2,11 +2,12 @@ package com.bonus.cost.beans; import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; import java.util.Map; /** * 工程领退物资明细实体类 - * + * * @author syruan */ public class ProjectLeaseCostDetail { @@ -21,6 +22,11 @@ public class ProjectLeaseCostDetail { */ private String machineName; + /** + * 机具类别 + */ + private String machineCodeName; + /** * 机具类型名称 */ @@ -51,6 +57,8 @@ public class ProjectLeaseCostDetail { */ private String machineCode; + private String oldMachineCode; + /** * 备注 */ @@ -106,6 +114,21 @@ public class ProjectLeaseCostDetail { */ private String operatePersonName; + /** + * 累计领料数量 + */ + private BigDecimal totalLeaseQuantity; + + /** + * 累计退料数量 + */ + private BigDecimal totalReturnQuantity; + + /** + * 领退料差额 + */ + private BigDecimal differenceQuantity; + /** * 操作日期 */ @@ -128,6 +151,16 @@ public class ProjectLeaseCostDetail { */ private String endTime; + /** + * 租赁单位 + */ + private String bsName; + + /** + * 序号(第几次领料) + */ + private Integer sequence; + /** * 查询关键字 */ @@ -324,4 +357,61 @@ public class ProjectLeaseCostDetail { public void setMachineTypeName(String machineTypeName) { this.machineTypeName = machineTypeName; } + + public String getOldMachineCode() { + return oldMachineCode; + } + + public void setOldMachineCode(String oldMachineCode) { + this.oldMachineCode = oldMachineCode; + } + + public String getBsName() { + return bsName; + } + + public void setBsName(String bsName) { + this.bsName = bsName; + } + + public String getMachineCodeName() { + return machineCodeName; + } + + public void setMachineCodeName(String machineCodeName) { + this.machineCodeName = machineCodeName; + } + + public Integer getSequence() { + return sequence; + } + + public void setSequence(Integer sequence) { + this.sequence = sequence; + } + + public BigDecimal getTotalLeaseQuantity() { + return totalLeaseQuantity; + } + + public void setTotalLeaseQuantity(BigDecimal totalLeaseQuantity) { + this.totalLeaseQuantity = totalLeaseQuantity; + } + + public BigDecimal getTotalReturnQuantity() { + return totalReturnQuantity; + } + + public void setTotalReturnQuantity(BigDecimal totalReturnQuantity) { + this.totalReturnQuantity = totalReturnQuantity; + } + + public BigDecimal getDifferenceQuantity() { + return differenceQuantity; + } + + public void setDifferenceQuantity(BigDecimal differenceQuantity) { + this.differenceQuantity = differenceQuantity; + } } + diff --git a/src/com/bonus/cost/service/ProjectCostServiceImpl.java b/src/com/bonus/cost/service/ProjectCostServiceImpl.java index ab26ba0..89399f7 100644 --- a/src/com/bonus/cost/service/ProjectCostServiceImpl.java +++ b/src/com/bonus/cost/service/ProjectCostServiceImpl.java @@ -25,6 +25,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.OutputStream; +import java.math.BigDecimal; import java.net.URLEncoder; import java.time.LocalDate; import java.time.LocalDateTime; @@ -44,20 +45,20 @@ public class ProjectCostServiceImpl implements ProjectCostService { @Autowired private ProjectCostDao projectCostDao; - + @Autowired private NewSettlementService newSettlementService; @Autowired private PlanApplicationDao planApplicationDao; - + // 定义两个格式化器:输入格式(带时分秒)、输出格式(仅年月日) private static final DateTimeFormatter INPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private static final DateTimeFormatter OUTPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); /** * 安全转换为Double类型 - * + * * @param obj 要转换的对象 * @param defaultValue 默认值 * @return 转换后的Double值 @@ -91,7 +92,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { /** * 安全转换为Integer类型 - * + * * @param obj 要转换的对象 * @param defaultValue 默认值 * @return 转换后的Integer值 @@ -351,18 +352,18 @@ public class ProjectCostServiceImpl implements ProjectCostService { LocalDateTime endtime = LocalDateTime.parse("2025-05-26 14:21:00", formatter); long daysBetween = java.time.Duration.between(operateTime, endtime).toDays(); System.err.println(daysBetween); - + } @Override public Map calculateSettlement(ProjectLeaseCostDetail o) { return newSettlementService.getNewSettlement(o); } - - - + + + public Map calculateSettlement2(ProjectLeaseCostDetail o) { - - + + // 获取领料明细 List leaseDetails = queryProjectLeaseDetails(o); // 获取退料明细 @@ -440,7 +441,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { startDate = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0); endDate = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59); } - + // 对每种物资类型进行计算 for (Map.Entry> entry : groupedByMachineType.entrySet()) { boolean add=true; @@ -450,7 +451,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { if("3627".equals(machineTypeId)) { System.err.println(machineTypeId); } - + // 按操作时间排序 items.sort(Comparator.comparing(ProjectLeaseCostDetail::getOperateTime, Comparator.nullsFirst(Comparator.naturalOrder()))); @@ -473,7 +474,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { // 第一步:处理统计期间开始之前的所有操作,计算期初在用数量 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - + DateTimeFormatter formatter_day = DateTimeFormatter.ofPattern("yyyy-MM-dd"); for (ProjectLeaseCostDetail item : items) { if (item == null || item.getOperateTime() == null) { @@ -498,7 +499,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { } System.out.println("物资ID=" + machineTypeId + " 期初在用数量: " + currentCount); - + // 如果期初在用数量大于0,需要计算从统计开始时间到第一个操作时间(或统计结束时间)的费用 if (currentCount > 0) { // 找到统计期间内的第一个操作时间 @@ -519,8 +520,8 @@ public class ProjectCostServiceImpl implements ProjectCostService { onlyAdd=false; } } - - + + if (!operateTime.isBefore(startDate) && !operateTime.isAfter(endDate)) { if (firstOperateTimeInPeriod == null || operateTime.isBefore(firstOperateTimeInPeriod)) { firstOperateTimeInPeriod = operateTime; @@ -531,8 +532,8 @@ public class ProjectCostServiceImpl implements ProjectCostService { // 如果统计期间内有操作,计算从开始时间到第一个操作时间的费用 // 如果统计期间内没有操作,计算从开始时间到结束时间的费用 LocalDateTime endTimeForInitialSegment = firstOperateTimeInPeriod != null ? firstOperateTimeInPeriod : endDate; - - + + long daysBetween = getDay(startDate, endTimeForInitialSegment); LocalDateTime startTimes = LocalDateTime.parse(o.getStartTime()+" 00:00:01", formatter); if(!onlyAdd) { @@ -541,7 +542,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { add=false; } } - + LocalDateTime lastTimes = LocalDateTime.parse(o.getEndTime()+" 23:59:59", formatter); String parsedDateOnly = formatLocalDateTimeToDate(lastTimes); String end_times = formatLocalDateTimeToDate(endTimeForInitialSegment); @@ -551,14 +552,14 @@ public class ProjectCostServiceImpl implements ProjectCostService { }else { ProjectLeaseCostDetail item=items.get(items.size()-1); LocalDateTime operateTime = LocalDateTime.parse(item.getOperateTime(), formatter); - - + + //判断当前数据是最后一条数据 ===== if(2==item.getOperateType() && operateTime.equals(endTimeForInitialSegment)) { daysBetween+=1; } - - + + } } if (daysBetween > 0) { @@ -607,7 +608,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { // 判断操作类型:1-领料,2-退料 boolean isLease = (item.getOperateType() == null || item.getOperateType() != 2); int quantity = 0; - + // 计算上一个时间点到当前操作时间的租赁费用 if (currentCount > 0 && !previousTime.equals(operateTime)) { if("3627".equals(machineTypeId)) { @@ -633,25 +634,25 @@ public class ProjectCostServiceImpl implements ProjectCostService { if (daysBetween < 1) { daysBetween = 1; } - + if(add) { if(parsedDateOnly.equals(end_times)) { daysBetween+=1; }else { //计算-- - + if(i==items.size()-1 && 2==item.getOperateType()) { long datadelNum = item.getReturnNum() != null ? item.getReturnNum() : 0; if(currentCount==datadelNum) { daysBetween+=1; } - + } - + } } -// - +// + // 计算该时间段的租赁费用 double segmentAmount = currentCount * unitPrice * daysBetween; totalItemAmount += segmentAmount; @@ -702,7 +703,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { if (currentCount > 0 && !previousTime.equals(endDate)) { // 计算两个时间点之间的天数 long daysBetween =getDay(previousTime, endDate); - + LocalDateTime lastTimes = LocalDateTime.parse(o.getEndTime()+" 23:59:59", formatter); String parsedDateOnly = formatLocalDateTimeToDate(lastTimes); String end_times = formatLocalDateTimeToDate(previousTime); @@ -726,8 +727,8 @@ public class ProjectCostServiceImpl implements ProjectCostService { if(add) { daysBetween+=1; } - - + + } // 计算该时间段的租赁费用 @@ -814,21 +815,21 @@ public class ProjectCostServiceImpl implements ProjectCostService { result.put("totalAmount", totalAmount); // 总金额 return result; } - + /** * 新的结算逻辑 - * - * + * + * */ public Map getNewSettlement() { Map result = new HashMap<>(); - + return result; - + } - - - + + + /** * 核心方法:将LocalDateTime格式化为yyyy-MM-dd字符串 * @param dateTime 待格式化的LocalDateTime对象 @@ -844,9 +845,9 @@ public class ProjectCostServiceImpl implements ProjectCostService { LocalDate startDate = operateTime.toLocalDate(); LocalDate endDate = endtime.toLocalDate(); long naturalDays = ChronoUnit.DAYS.between(startDate, endDate); - System.out.println("自然日天数差(正确结果):" + naturalDays); + System.out.println("自然日天数差(正确结果):" + naturalDays); return naturalDays; - + } @Override @@ -982,6 +983,13 @@ public class ProjectCostServiceImpl implements ProjectCostService { List leaseDetails = queryProjectLeaseDetails(queryParam); List returnDetails = queryProjectReturnDetails(queryParam); + //同一天的统一类型的机具进行合并 + leaseDetails = mergeByDay(leaseDetails,1); + returnDetails = mergeByDay(returnDetails,2); + + //计算差额 + leaseDetails =calculateMaterialDifference(leaseDetails, returnDetails); + List allDetails = new ArrayList<>(); if (leaseDetails != null) { allDetails.addAll(leaseDetails); @@ -1064,6 +1072,142 @@ public class ProjectCostServiceImpl implements ProjectCostService { return calculation; } + /** + * 计算领退料差额 + * @param leaseDetails 领料明细列表 + * @param returnDetails 退料明细列表 + * @return 计算后的领料明细列表(包含差额) + */ + public List calculateMaterialDifference( + List leaseDetails, + List returnDetails) { + + // 1. 按物料类型分组领料数据 + Map> leaseByMaterial = + leaseDetails.stream() + .sorted(Comparator.comparing(ProjectLeaseCostDetail::getOperateTime)) + .collect(Collectors.groupingBy( + ProjectLeaseCostDetail::getMachineTypeId, + LinkedHashMap::new, // 保持顺序 + Collectors.toList() + )); + + // 2. 按物料类型分组退料数据 + Map> returnByMaterial = + returnDetails.stream() + .sorted(Comparator.comparing(ProjectLeaseCostDetail::getOperateTime)) + .collect(Collectors.groupingBy( + ProjectLeaseCostDetail::getMachineTypeId, + LinkedHashMap::new, + Collectors.toList() + )); + + // 3. 处理每个物料类型 + List result = new ArrayList<>(); + + for (Map.Entry> entry : leaseByMaterial.entrySet()) { + Integer materialType = entry.getKey(); + List materialLeases = entry.getValue(); + List materialReturns = + returnByMaterial.getOrDefault(materialType, new ArrayList<>()); + + // 计算该物料的累计差额 + List calculated = + calculateForSingleMaterial(materialLeases, materialReturns); + + result.addAll(calculated); + } + + return result; + } + + /** + * 计算单个物料的领退料差额 + */ + private List calculateForSingleMaterial( + List leases, + List returns) { + + List result = new ArrayList<>(); + + // 初始化累计量 + BigDecimal totalReturn = BigDecimal.ZERO; + + // 累计退料 + for (ProjectLeaseCostDetail detail : returns) { + BigDecimal returnQty = detail.getReturnNum() != null ? + BigDecimal.valueOf(detail.getReturnNum()) : BigDecimal.ZERO; + totalReturn = totalReturn.add(returnQty); + } + + // 按时间顺序处理每次领料 + for (ProjectLeaseCostDetail lease : leases) { + + //比较当前退料数量和领料数量 + if(BigDecimal.valueOf(lease.getLeaseNum()).compareTo(totalReturn)>=0){ + lease.setDifferenceQuantity(BigDecimal.valueOf(lease.getLeaseNum()).subtract(totalReturn)); + totalReturn = BigDecimal.ZERO; + }else { + lease.setDifferenceQuantity(BigDecimal.ZERO); + //获取剩余的退料数量 + totalReturn = totalReturn.subtract(BigDecimal.valueOf(lease.getLeaseNum())); + } + + result.add(lease); + } + + return result; + } + + /** + * 根据 operateDate 按天合并,累加 leaseNum + */ + public List mergeByDay(List leases, int i) { + List leasesNew = new ArrayList<>(); + + // 使用 Map 按日期分组,同一天的合并一起 + Map mergedMap = new LinkedHashMap<>(); + + for (ProjectLeaseCostDetail returnDetail : leases) { + if ("牵张设备".equals(returnDetail.getMachineCodeName()) ||"施工机械".equals(returnDetail.getMachineCodeName()) ||"仪器设备".equals(returnDetail.getMachineCodeName())){ + leasesNew.add(returnDetail); + }else { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String dateOnly = returnDetail.getOperateTime().substring(0, 10); + LocalDate dateKey = LocalDate.parse(dateOnly, + formatter); + if (mergedMap.containsKey(dateKey)) { + // 已存在该日期的记录,合并数量 + ProjectLeaseCostDetail existing = mergedMap.get(dateKey); + if (i==1){ + // 累加 leaseNum + existing.setLeaseNum( + (existing.getLeaseNum() != null ? existing.getLeaseNum() : 0) + + (returnDetail.getLeaseNum() != null ? returnDetail.getLeaseNum() : 0) + ); + }else { + // 累加 leaseNum + existing.setReturnNum( + (existing.getReturnNum() != null ? existing.getReturnNum() : 0) + + (returnDetail.getReturnNum() != null ? returnDetail.getReturnNum() : 0) + ); + } + } else { + // 新日期的记录,创建副本(避免修改原对象) + mergedMap.put(dateKey, returnDetail); + } + } + + } + + //保存合并后的数据 + for (Map.Entry entry : mergedMap.entrySet()) { + ProjectLeaseCostDetail materialLeases = entry.getValue(); + leasesNew.add(materialLeases); + } + return leasesNew; + } + @Override public boolean deleteCalculation(Integer id) { return projectCostDao.deleteCalculation(id) > 0; @@ -1071,7 +1215,7 @@ public class ProjectCostServiceImpl implements ProjectCostService { /** * 封装导出Excel的方法,适用于只有HttpServletResponse的情况 - * + * * @param fileName 文件名 * @param sheetName sheet名称 * @param headers 表头 @@ -1914,46 +2058,234 @@ public class ProjectCostServiceImpl implements ProjectCostService { // 准备Excel数据 String fileName = "领退记录表_" + calculation.getProjectName() + "_" + calculation.getId() + ".xls"; - String sheetName = "领退记录表"; + String sheetName = "领用、差缺明细表"; + String sheetName2 = "退料明细表"; // 表头 - 增加规格型号字段 - String[] headers = { "序号", "物资类型", "规格型号", "操作类型", "操作时间", "数量", "单位", "操作人", "任务编号" }; + /*String[] headers = { "序号", "物资类型", "规格型号", "操作类型", "操作时间", "数量", "单位", "操作人", "任务编号" };*/ + String[] headers = { "领料日期", "工程名称", "库房", "类别", "机具设备名称", "规格型号", "编码", + "新编码", "单位", "数量", "差额", "租赁单位", "备注" }; + String[] headers2 = { "退料工程名称", "退料单位", "退料日期", "库房", "类别", "机具设备名称", "规格", + "编号", "单位", "数量", "备注" }; // 列宽 - 添加规格型号列宽 - int[] widths = { 256 * 5, 256 * 15, 256 * 15, 256 * 10, 256 * 18, 256 * 10, 256 * 10, 256 * 10, 256 * 15 }; + int[] widths = { 256 * 15,256 * 30,256 * 15,256 * 15,256 * 20,256 * 20,256 * 20,256 * 10,256 * 10, 256 * 10, 256 * 10, 256 * 20, 256 * 10 }; + int[] widths2 = { 256 * 30,256 * 15,256 * 15,256 * 15,256 * 18,256 * 20,256 * 20,256 * 10,256 * 10, 256 * 10, 256 * 10 }; // 数据格式(1:String left; 2:String center; 3:String right; 4:int right; 5:float // right) - int[] formats = { 4, 2, 2, 2, 2, 4, 2, 2, 2 }; - + int[] formats = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2 }; + int[] formats2 = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2 }; // 准备数据 List> dataList = new ArrayList<>(); - + List> dataList2 = new ArrayList<>(); // 获取所有物资的领退记录 List details = calculation.getDetails(); if (details != null && !details.isEmpty()) { - int index = 1; for (ProjectCostCalculationDetail detail : details) { List operRecords = detail.getDetails(); if (operRecords != null && !operRecords.isEmpty()) { for (ProjectLeaseCostDetail record : operRecords) { - Map row = new HashMap<>(); - row.put("序号", index++); - row.put("物资类型", record.getMachineTypeName()); - row.put("规格型号", record.getMachineModel()); // 添加规格型号字段 - row.put("操作类型", record.getOperateType() == 1 ? "领料" : "退料"); - row.put("操作时间", record.getOperateTime()); - row.put("数量", record.getOperateType() == 1 ? record.getLeaseNum() : record.getReturnNum()); - row.put("单位", record.getMachineUnit()); - row.put("操作人", record.getOperatePersonName()); - row.put("任务编号", record.getTaskCode()); - dataList.add(row); + if (record.getOperateType() == 1){ + Map row = new HashMap<>(); + row.put("领料日期", record.getOperateTime().substring(0,10)); + row.put("工程名称", calculation.getProjectName()); + if ("牵张设备".equals(record.getMachineCodeName()) ||"施工机械".equals(record.getMachineCodeName()) ||"仪器设备".equals(record.getMachineCodeName())){ + row.put("库房", "设备库"); + }else { + row.put("库房", "机具库"); + } + row.put("类别", record.getMachineCodeName()); // 添加规格型号字段 + row.put("机具设备名称", record.getMachineTypeName()); + row.put("规格型号", record.getMachineModel()); + row.put("编码", record.getOldMachineCode()); + row.put("新编码", record.getMachineCode()); + row.put("单位", record.getMachineUnit()); + row.put("数量", record.getOperateType() == 1 ? record.getLeaseNum() : record.getReturnNum()); + row.put("差额", record.getDifferenceQuantity()); + row.put("租赁单位", record.getBsName()); + row.put("备注",null); + dataList.add(row); + }else { + Map row = new HashMap<>(); + row.put("退料工程名称", calculation.getProjectName()); + row.put("退料单位", record.getBsName()); + row.put("退料日期", record.getOperateTime().substring(0,10)); // 添加规格型号字段 + if ("牵张设备".equals(record.getMachineCodeName()) ||"施工机械".equals(record.getMachineCodeName()) ||"仪器设备".equals(record.getMachineCodeName())){ + row.put("库房", "设备库"); + }else { + row.put("库房", "机具库"); + } + row.put("类别", record.getMachineCodeName()); // 添加规格型号字段 + row.put("机具设备名称", record.getMachineTypeName()); + row.put("规格", record.getMachineModel()); + row.put("编号", record.getOldMachineCode()); + row.put("单位", record.getMachineUnit()); + row.put("数量", record.getOperateType() == 1 ? record.getLeaseNum() : record.getReturnNum()); + row.put("备注",null); + dataList2.add(row); + } + } } } } + // 设置文件名 + String filename = ""; + try { + filename = URLEncoder.encode(fileName, "UTF-8"); + } catch (Exception e) { + filename = fileName; + } + // 设置响应头 + response.setHeader("Content-disposition", "attachment;filename=" + filename); + response.setContentType("application/vnd.ms-excel"); + response.setHeader("Pragma", "No-cache"); + + // 创建一个工作簿 + HSSFWorkbook wb = new HSSFWorkbook(); + // 创建一个sheet + HSSFSheet sheet = wb.createSheet(sheetName); + // 创建一个sheet + HSSFSheet sheet2 = wb.createSheet(sheetName2); // 调用导出方法 - exportExcel(fileName, sheetName, headers, widths, formats, dataList, response); + exportExcelNew(wb, sheet, headers, widths, formats, dataList, response); + exportExcelNew(wb, sheet2, headers2, widths2, formats2, dataList2, response); + // 输出文件 + OutputStream ouputStream = response.getOutputStream(); + wb.write(ouputStream); + ouputStream.flush(); + ouputStream.close(); + } + /** + * 封装导出Excel的方法,适用于只有HttpServletResponse的情况 + * + * @param wb 文件名 + * @param sheet sheet名称 + * @param headers 表头 + * @param widths 列宽 + * @param formats 数据格式 + * @param dataList 数据列表 + * @param response HttpServletResponse对象 + * @throws Exception 导出异常 + */ + private void exportExcelNew(HSSFWorkbook wb, HSSFSheet sheet, String[] headers, int[] widths, int[] formats, + List> dataList, javax.servlet.http.HttpServletResponse response) throws Exception { + try { + + + // 创建表头 + int headerrow = 0; + if (headers != null) { + HSSFRow row = sheet.createRow(headerrow); + // 设置表头行高 - 调高表头高度 + row.setHeight((short) 500); // 设置为原高度的约2倍 + + // 表头样式 + HSSFCellStyle style = wb.createCellStyle(); + HSSFFont font = wb.createFont(); + font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); + font.setFontName("微软雅黑"); + font.setFontHeightInPoints((short) 11); + style.setFont(font); + style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平居中 + style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中 + style.setBorderBottom(HSSFCellStyle.BORDER_THIN); + style.setBorderLeft(HSSFCellStyle.BORDER_THIN); + style.setBorderRight(HSSFCellStyle.BORDER_THIN); + style.setBorderTop(HSSFCellStyle.BORDER_THIN); + + // 设置淡黄色背景 + style.setFillForegroundColor((short) 0x2B); // 修改为更明确的淡黄色,0x2B是淡黄色(light yellow) + style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); + + for (int i = 0; i < headers.length; i++) { + sheet.setColumnWidth((short) i, (short) widths[i]); + HSSFCell cell = row.createCell(i); + cell.setCellValue(headers[i]); + cell.setCellStyle(style); + } + headerrow++; + } + + // 表格主体 + if (dataList != null) { + List styleList = new ArrayList(); + + if (headers != null) { + for (int i = 0; i < headers.length; i++) { // 列数 + HSSFCellStyle style = wb.createCellStyle(); + HSSFFont font = wb.createFont(); + font.setFontName("微软雅黑"); + font.setFontHeightInPoints((short) 10); + style.setFont(font); + style.setBorderBottom(HSSFCellStyle.BORDER_THIN); + style.setBorderLeft(HSSFCellStyle.BORDER_THIN); + style.setBorderRight(HSSFCellStyle.BORDER_THIN); + style.setBorderTop(HSSFCellStyle.BORDER_THIN); + // 添加垂直居中对齐 + style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); + + if (formats[i] == 1) { + style.setAlignment(HSSFCellStyle.ALIGN_LEFT); + } else if (formats[i] == 2) { + style.setAlignment(HSSFCellStyle.ALIGN_CENTER); + } else if (formats[i] == 3) { + style.setAlignment(HSSFCellStyle.ALIGN_RIGHT); + } else if (formats[i] == 4) { + style.setAlignment(HSSFCellStyle.ALIGN_RIGHT); + // int类型 + style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0")); + } else if (formats[i] == 5) { + // float类型 + style.setAlignment(HSSFCellStyle.ALIGN_RIGHT); + style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00")); + } else if (formats[i] == 6) { + // 百分比类型 + style.setAlignment(HSSFCellStyle.ALIGN_RIGHT); + style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00%")); + } + styleList.add(style); + } + } + + for (Map stringObjectMap : dataList) { // 行数 + HSSFRow row = sheet.createRow(headerrow); + int j = 0; + for (String key : headers) { // 列数 + HSSFCell cell = row.createCell(j); + Object o = stringObjectMap.get(key); + if (o == null || "".equals(o)) { + cell.setCellValue(""); + } else if (formats[j] == 4) { + // int + try { + cell.setCellValue(Long.parseLong(String.valueOf(o))); + } catch (Exception e) { + cell.setCellValue(0); + } + } else if (formats[j] == 5 || formats[j] == 6) { + // float + try { + cell.setCellValue(Double.parseDouble(String.valueOf(o))); + } catch (Exception e) { + cell.setCellValue(0.0); + } + } else { + cell.setCellValue(String.valueOf(o)); + } + + cell.setCellStyle(styleList.get(j)); + j++; + } + headerrow++; + } + } + + + } catch (Exception e) { + throw new Exception("导出Excel异常", e); + } } /** @@ -1968,4 +2300,4 @@ public class ProjectCostServiceImpl implements ProjectCostService { } return totalDays; } -} \ No newline at end of file +}