From 5048f6183b336e32a55b4d9e5b26790243748e3c Mon Sep 17 00:00:00 2001 From: FCD <2453864257@qq.com> Date: Tue, 16 Dec 2025 09:00:53 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E4=BA=A7=E8=BF=87=E7=A8=8B=E6=8A=A5?= =?UTF-8?q?=E5=91=8A=E5=A2=9E=E5=8A=A0=E6=89=B9=E6=AC=A1=E6=88=90=E5=93=81?= =?UTF-8?q?=E6=A3=80=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/poi/ExcelCPPCReportMapUtil.java | 530 ++++++++++++++++++ .../QcCheckReportProduceController.java | 117 +++- .../quality/QcCheckTaskProduceMapper.xml | 40 +- 3 files changed, 681 insertions(+), 6 deletions(-) create mode 100644 op-common/op-common-core/src/main/java/com/op/common/core/utils/poi/ExcelCPPCReportMapUtil.java diff --git a/op-common/op-common-core/src/main/java/com/op/common/core/utils/poi/ExcelCPPCReportMapUtil.java b/op-common/op-common-core/src/main/java/com/op/common/core/utils/poi/ExcelCPPCReportMapUtil.java new file mode 100644 index 000000000..5b1c631ca --- /dev/null +++ b/op-common/op-common-core/src/main/java/com/op/common/core/utils/poi/ExcelCPPCReportMapUtil.java @@ -0,0 +1,530 @@ +package com.op.common.core.utils.poi; + +import com.alibaba.fastjson2.JSONObject; +import com.op.common.core.domain.ExcelCol; +import org.apache.commons.compress.utils.IOUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * CPP报告Excel生成工具类 + * 功能:生成包含logo、标题、检验信息、数据表格、签名图片的CPP检验报告Excel + * + * @author 019117 + * @date 2025-12-15 + */ +public class ExcelCPPCReportMapUtil { + //下载 + public static SXSSFWorkbook initWorkbook(String sheetName , String title, List excelCol , List data, Map detailMap,List bytes) throws IOException { + SXSSFWorkbook workbook = new SXSSFWorkbook(); + int colSize = excelCol.size(); + + //创建Sheet(工作簿) + Sheet sheet = null; + if (!StringUtils.hasText(sheetName)){ + sheet = workbook.createSheet(); + }else{ + sheet = workbook.createSheet(sheetName); + } + + // 从resources目录获取图片字节数组 + byte[] imageBytes = getImageBytesFromResources("image/logo.png"); + /**logo**/ + int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG); + CreationHelper helper = workbook.getCreationHelper(); + Drawing drawing = sheet.createDrawingPatriarch(); + ClientAnchor anchor = helper.createClientAnchor(); + anchor.setCol1(0); // B列 + anchor.setRow1(0); // 第2行(Excel的行和列都是从0开始计数的) + anchor.setCol2(1); // C列(图片宽度跨越的列数,这里设置为1列宽) + anchor.setRow2(2); // 第6行(图片高度跨越的行数,这里设置为4行高,可以根据图片大小调整) + Picture pict = drawing.createPicture(anchor, pictureIdx); + pict.resize(); // 根据图片的实际大小调整图片在Excel中的显示大小 + /**报告标题**/ + sheet.addMergedRegion(new CellRangeAddress(0, 1, 2, 11)); + // 获取合并后的单元格的第一个单元格(即C1),并设置值 + Row row1 = sheet.getRow(0); // 获取第1行(索引为0) + if (row1 == null) {row1 = sheet.createRow(0); // 如果第1行不存在,则创建它 + } + Cell cell = row1.getCell(2); // 获取C列(索引为2)的单元格 + if (cell == null) { + cell = row1.createCell(2); // 如果C列的单元格不存在,则创建它 + } + cell.setCellValue("中山榄菊日化实业有限公司"); // 设置单元格的值 + cell.setCellStyle(getTitelStyle(workbook)); // 应用样式到单元格 + /**报告二级标题、检验标准**/ + // 合并C3到I4的单元格,并设置样式 + mergeAndStyleCells(sheet, new CellRangeAddress(2, 3, 2, 8), detailMap.get("title")); + // 合并J3到L4的单元格,并设置样式 + mergeAndStyleCells(sheet, new CellRangeAddress(2, 3, 9, 12), "编码"+detailMap.get("standardNo")); + /**左右表格1**/ + //画边框 + for(int r5=4;r5<11;r5++){ + Row row05 = sheet.getRow(r5); + if (row05 == null) {row05 = sheet.createRow(r5);} + for (int col = 0; col < 14; col++) { + Cell cell1 = row05.createCell(col); + cell1.setCellStyle(getRowStyle(sheet)); + } + } + for(int d5=11;d5<(11+data.size());d5++){ + Row row05 = sheet.getRow(d5); + if (row05 == null) {row05 = sheet.createRow(d5);} + for (int col = 0; col < 14; col++) { + Cell cell1 = row05.createCell(col); + cell1.setCellStyle(getDataStyle(sheet)); + } + } + + Row row5 = sheet.getRow(4); + // 合并A5到B6的单元格,并设置样式和内容 + mergeAndStyleCells2(sheet,row5, new CellRangeAddress(4, 5, 0, 1), "产品名称/生产组", true, true, IndexedColors.GREY_25_PERCENT); + // 合并C5到D6的单元格,并设置样式(无背景色,只有边框和内容居中) + mergeAndStyleCells2(sheet,row5, new CellRangeAddress(4, 5, 2, 8), detailMap.get("materialName")+"/"+detailMap.get("checkLoc"), true, false, null); + // 合并J5到K6的单元格,并设置样式和内容 + mergeAndStyleCells2(sheet,row5, new CellRangeAddress(4, 5, 9, 10), "产品编码", true, true, IndexedColors.GREY_25_PERCENT); + // 合并L5到N6的单元格,并设置样式(无背景色,只有边框和内容居中) + mergeAndStyleCells2(sheet,row5, new CellRangeAddress(4, 5, 11, 13), detailMap.get("materialCode"), true, false, null); + Row row7 = sheet.getRow(6); + // 合并A7到B8的单元格,并设置样式和内容 + mergeAndStyleCells2(sheet,row7, new CellRangeAddress(6, 7, 0, 1), "首检时间", true, true, IndexedColors.GREY_25_PERCENT); + // 合并C5到D6的单元格,并设置样式(无背景色,只有边框和内容居中) + mergeAndStyleCells2(sheet,row7, new CellRangeAddress(6, 7, 2, 3), detailMap.get("incomeTime"), true, false, null); + // 合并E5到F6的单元格,并设置样式和内容 + mergeAndStyleCells2(sheet,row7, new CellRangeAddress(6, 7, 4, 5), "生产批次", true, true, IndexedColors.GREY_25_PERCENT); + // 合并G5到I6的单元格,并设置样式(无背景色,只有边框和内容居中) + mergeAndStyleCells2(sheet,row7, new CellRangeAddress(6, 7, 6, 13), detailMap.get("incomeBatchNo"), true, false, null); + // 合并J5到K6的单元格,并设置样式和内容 + Row row9 = sheet.getRow(8); + // 合并A7到B8的单元格,并设置样式和内容 + mergeAndStyleCells2(sheet,row9, new CellRangeAddress(8, 9, 0, 1), "首检原因", true, true, IndexedColors.GREY_25_PERCENT); + // 合并C5到D6的单元格,并设置样式(无背景色,只有边框和内容居中) + mergeAndStyleCells2(sheet,row9, new CellRangeAddress(8, 9, 2, 13), detailMap.get("reason"), true, false, null); + /**上下表格2**///------------------------------------------------- + Row row10 = sheet.getRow(10); + if (row10 == null) {row10 = sheet.createRow(10);} + Cell cellA13 = row10.createCell(0); + cellA13.setCellValue("序号"); + cellA13.setCellStyle(getRowStyle(sheet)); + mergeAndStyleCells(sheet, new CellRangeAddress(10, 10, 1, 4), "检验项目"); + mergeAndStyleCells(sheet, new CellRangeAddress(10, 10, 5, 8), "内容"); +// 移除:实测结果列的合并单元格逻辑 + Cell cellL13 = row10.createCell(9); // 原11列 → 调整为9列(去掉实测结果2列后索引前移) + cellL13.setCellValue("判定"); + cellL13.setCellStyle(getRowStyle(sheet)); + mergeAndStyleCells(sheet, new CellRangeAddress(10, 10, 10, 11), "附件"); // 原12-13列 → 调整为10-11列 + +//将data中的值填充到excel + int rowNum = 11; + if(!CollectionUtils.isEmpty(data)){ + Iterator iterator = data.iterator(); + //遍历数据 + for (;iterator.hasNext();){ + + T obj = iterator.next();//获取当前行对应的数据 + JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(obj)); + + Row dataRow = sheet.getRow(rowNum); + if (dataRow == null) { // 补充:防止行不存在的空指针 + dataRow = sheet.createRow(rowNum); + } + // 假设使用了默认字体和字符宽度来计算行高(这是一个简化的示例) + // 修复:原代码cell未定义,这里调整为取第一个单元格示例(可根据实际需求修改) + Cell tempCell = dataRow.getCell(0) != null ? dataRow.getCell(0) : dataRow.createCell(0); + int cellHeight = (int) (tempCell.getStringCellValue() == null ? 20 : tempCell.getStringCellValue().length() * 6); + dataRow.setHeightInPoints(Math.max(dataRow.getHeightInPoints(), cellHeight)); + + // 序号列(0列) + Cell cellData0 = dataRow.getCell(0); + if (cellData0 == null) { + cellData0 = dataRow.createCell(0); + } + cellData0.setCellValue(rowNum-10); + cellData0.setCellStyle(getDataStyle(sheet)); + + // 检验项目列(1列) + Cell cellData1 = dataRow.getCell(1); + if (cellData1 == null) { + cellData1 = dataRow.createCell(1); + } + cellData1.setCellValue(getValue(jsonObject.get(excelCol.get(0).getField()))); + cellData1.setCellStyle(getDataStyle(sheet)); + + // 内容列(5-8列) + Cell cellData2 = dataRow.getCell(5); + if (cellData2 == null) { + cellData2 = dataRow.createCell(5); + } + cellData2.setCellValue(getValue(jsonObject.get(excelCol.get(1).getField()))); + cellData2.setCellStyle(getDataStyle(sheet)); + sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum, 5, 8)); + + // 移除:实测结果列(9-10列)的所有逻辑 + + // 判定列(原11列 → 调整为9列) + Cell cellData4 = dataRow.getCell(9); + if (cellData4 == null) { + cellData4 = dataRow.createCell(9); + } + cellData4.setCellValue(getValue(jsonObject.get(excelCol.get(2).getField()))); // 原excelCol.get(3) → 调整为get(2)(数据源索引前移) + cellData4.setCellStyle(getDataStyle(sheet)); + + // 附件列(图片插入):原12列 → 调整为10列 + // 下载图片 + byte[] imageFileBytes = bytes.get(rowNum-11); + if (imageFileBytes != null) { + // 将图片添加到工作簿中 + int picIdx = workbook.addPicture(imageFileBytes, Workbook.PICTURE_TYPE_JPEG); + // 创建绘图对象和锚点 + CreationHelper fhelper = workbook.getCreationHelper(); + Drawing fdrawing = sheet.createDrawingPatriarch(); + ClientAnchor fanchor = fhelper.createClientAnchor(); + fanchor.setCol1(10); // 原12列 → 调整为10列 + fanchor.setRow1(rowNum); + fanchor.setCol2(12); // 原14列 → 调整为12列 + fanchor.setRow2(rowNum+1); + // 插入图片到指定位置 + Picture fpict =fdrawing.createPicture(fanchor, picIdx); + //fpict.resize(); + } + + iterator.remove(); + rowNum++; + } + } + + // 指定要检查的列索引(例如,B列的索引是1) + int columnIndex = 1; + // 遍历所有行,从第二行开始(索引1),因为第一行可能是标题行 + for (int rowIndex = 11; rowIndex <= sheet.getLastRowNum(); ) { + Row currentRow = sheet.getRow(rowIndex); + if (currentRow != null) { + Cell currentCell = currentRow.getCell(columnIndex); + if (currentCell != null && currentCell.getCellType() == CellType.STRING) { // 假设我们处理字符串类型的单元格 + String currentValue = currentCell.getStringCellValue(); + + // 查找连续相同值的行 + int lastRowIndex = rowIndex; + while (lastRowIndex + 1 <= sheet.getLastRowNum()) { + Row nextRow = sheet.getRow(lastRowIndex + 1); + if (nextRow != null) { + Cell nextCell = nextRow.getCell(columnIndex); + if (nextCell != null && nextCell.getCellType() == CellType.STRING && + nextCell.getStringCellValue().equals(currentValue)) { + lastRowIndex++; // 继续向下查找 + } else { + break; // 找到不同值,停止查找 + } + } else { + break; // 没有更多行,停止查找 + } + } + + // 合并找到的行 + if (rowIndex != lastRowIndex) { // 只有在找到连续相同值的行时才进行合并 + sheet.addMergedRegion(new CellRangeAddress(rowIndex, lastRowIndex, 1, 4)); + }else{ + sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, 4)); + } + + // 更新rowIndex以跳过已合并的行 + rowIndex = lastRowIndex + 1; // 从下一个未合并的行开始继续遍历 + } else { + // 如果当前单元格不是字符串类型,则直接跳到下一行 + rowIndex++; + } + } else { + // 如果当前行为空,则直接跳到下一行 + rowIndex++; + } + } + Row rowEnd0 = sheet.createRow(rowNum); + mergeAndStyleCellsNoBorder(sheet,rowEnd0, new CellRangeAddress(rowNum, rowNum+1, 0, 1), "备注", true, true, IndexedColors.GREY_25_PERCENT); + mergeAndStyleCellsNoBorder(sheet,rowEnd0, new CellRangeAddress(rowNum, rowNum+1, 2, 13), detailMap.get("remark"), true, true,null); + + Row rowEnd1 = sheet.createRow(rowNum+2); + mergeAndStyleCellsNoBorder(sheet,rowEnd1, new CellRangeAddress(rowNum+2, rowNum+3, 0, 1), "综合检验结论", true, true, IndexedColors.GREY_25_PERCENT); + mergeAndStyleCellsNoBorder(sheet,rowEnd1, new CellRangeAddress(rowNum+2, rowNum+3, 2, 3), detailMap.get("checkResult"), true, false, null); + mergeAndStyleCellsNoBorder(sheet,rowEnd1, new CellRangeAddress(rowNum+2, rowNum+3, 5, 10), "备注:判定合格打“√”,不合格打“×”", true, true, null); + Row rowEnd2 = sheet.createRow(rowNum+5); + mergeAndStyleCellsNoBorder(sheet,rowEnd2, new CellRangeAddress(rowNum+5, rowNum+5, 0, 1), "车间组长/机管员签名", true, true, IndexedColors.GREY_25_PERCENT); + // 下载图片 + int signNum = bytes.size()-3; + byte[] imageFileBytes1 = bytes.get(signNum); + if (imageFileBytes1 != null) { + // 将图片添加到工作簿中 + int picIdx = workbook.addPicture(imageFileBytes1, Workbook.PICTURE_TYPE_JPEG); // 假设图片是JPEG格式,根据实际情况调整 + // 创建绘图对象和锚点 + CreationHelper fhelper = workbook.getCreationHelper(); + Drawing fdrawing = sheet.createDrawingPatriarch(); + ClientAnchor fanchor = fhelper.createClientAnchor(); + fanchor.setCol1(2); // 列索引从0开始,1表示第二列(B列) + fanchor.setRow1(rowNum+5); // 行索引从0开始,1表示第二行 + fanchor.setCol2(5); // 14-12是列数 + fanchor.setRow2(rowNum+7); // + // 插入图片到指定位置 + Picture fpict =fdrawing.createPicture(fanchor, picIdx); + //fpict.resize(); // 根据图片的实际大小调整图片在Excel中的显示大小 + } + + // 下载图片 + byte[] imageFileBytes2 = bytes.get(signNum+1); + if (imageFileBytes2 != null) { + // 将图片添加到工作簿中 + int picIdx = workbook.addPicture(imageFileBytes2, Workbook.PICTURE_TYPE_JPEG); // 假设图片是JPEG格式,根据实际情况调整 + // 创建绘图对象和锚点 + CreationHelper fhelper = workbook.getCreationHelper(); + Drawing fdrawing = sheet.createDrawingPatriarch(); + ClientAnchor fanchor = fhelper.createClientAnchor(); + fanchor.setCol1(6); // 列索引从0开始,1表示第二列(B列) + fanchor.setRow1(rowNum+5); // 行索引从0开始,1表示第二行 + fanchor.setCol2(9); // 14-12是列数 + fanchor.setRow2(rowNum+7); // + // 插入图片到指定位置 + Picture fpict =fdrawing.createPicture(fanchor, picIdx); + //fpict.resize(); // 根据图片的实际大小调整图片在Excel中的显示大小 + } + Row rowEnd3 = sheet.createRow(rowNum+8); + mergeAndStyleCellsNoBorder(sheet,rowEnd3, new CellRangeAddress(rowNum+8, rowNum+8, 0, 1), "质量管理部品管员签名", true, true, IndexedColors.GREY_25_PERCENT); + // 下载图片 + byte[] imageFileBytes3 = bytes.get(signNum+2); + if (imageFileBytes3 != null) { + // 将图片添加到工作簿中 + int picIdx = workbook.addPicture(imageFileBytes3, Workbook.PICTURE_TYPE_JPEG); // 假设图片是JPEG格式,根据实际情况调整 + // 创建绘图对象和锚点 + CreationHelper fhelper = workbook.getCreationHelper(); + Drawing fdrawing = sheet.createDrawingPatriarch(); + ClientAnchor fanchor = fhelper.createClientAnchor(); + fanchor.setCol1(2); // 列索引从0开始,1表示第二列(B列) + fanchor.setRow1(rowNum+8); // 行索引从0开始,1表示第二行 + fanchor.setCol2(5); // 14-12是列数 + fanchor.setRow2(rowNum+10); // + // 插入图片到指定位置 + Picture fpict =fdrawing.createPicture(fanchor, picIdx); + //fpict.resize(); // 根据图片的实际大小调整图片在Excel中的显示大小 + } + + return workbook; + } + +// //标题样式 +// public static CellStyle getHeaderFont(Workbook workbook){ +// Font font = workbook.createFont(); +// font.setFontHeightInPoints((short) 15);//字体大小 +// font.setBold(true);//加粗 +// CellStyle cellStyle = workbook.createCellStyle(); +// cellStyle.setFont(font); +// cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);//设置水平居中 +// cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//设置垂直居中 +// // 设置上边框 +// cellStyle.setBorderTop(BorderStyle.THIN); +// // 设置下边框 +// cellStyle.setBorderBottom(BorderStyle.THIN); +// // 设置左边框 +// cellStyle.setBorderLeft(BorderStyle.THIN); +// // 设置右边框 +// cellStyle.setBorderRight(BorderStyle.THIN); +// cellStyle.setFillBackgroundColor(IndexedColors.AQUA.getIndex()); +// +// return cellStyle; +// } + + // //内容样式 +// public static CellStyle getDataFont(Workbook workbook){ +// Font font = workbook.createFont(); +// font.setFontHeightInPoints((short) 12);//字体大小 +// font.setBold(false);//不加粗 +// CellStyle cellStyle = workbook.createCellStyle(); +// cellStyle.setFont(font); +// cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);//设置水平居中 +// cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//设置垂直居中 +// cellStyle.setWrapText(true);//设置单元格内容自动换行 +// return cellStyle; +// } +// + //处理数据 + public static String getValue(Object object){ + if (object==null){ + return ""; + }else { + return object.toString(); + } + } + // //处理数据 +// public static Integer getValueNum(Object object){ +// if (object==null){ +// return 0; +// }else { +// return Integer.parseInt(object.toString()); +// } +// } + // 从resources目录获取图片的字节数组 + private static byte[] getImageBytesFromResources(String resourceName) { + try (InputStream inputStream = ExcelSCReportMapUtil.class.getClassLoader().getResourceAsStream(resourceName); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + + if (inputStream == null) { + throw new RuntimeException("找不到资源: " + resourceName); + } + + IOUtils.copy(inputStream, byteArrayOutputStream); + return byteArrayOutputStream.toByteArray(); + + } catch (IOException e) { + throw new RuntimeException("读取资源时出错: " + resourceName, e); + } + } + //报告大标题样式-1 + public static CellStyle getTitelStyle(Workbook workbook){ + Font font = workbook.createFont(); + // 设置字体为加粗 + font.setBold(true); + // 设置字体大小(例如,设置为16) + font.setFontHeightInPoints((short) 24); + CellStyle cellStyle = workbook.createCellStyle(); + cellStyle.setFont(font); + cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);//设置水平居中 + cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//设置垂直居中 + cellStyle.setWrapText(true);//设置单元格内容自动换行 + return cellStyle; + } + public static CellStyle getRowStyle(Sheet sheet){ + CellStyle style = sheet.getWorkbook().createCellStyle(); + // 设置边框线 + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + style.setBorderTop(BorderStyle.THIN); + // 设置水平居中 + style.setAlignment(HorizontalAlignment.CENTER); + style.setWrapText(true);//设置单元格内容自动换行 + // 设置垂直居中 + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font font = sheet.getWorkbook().createFont(); + font.setBold(true); + // 设置字体大小(例如,设置为14) + font.setFontHeightInPoints((short) 14); + style.setFont(font); + return style; + } + public static CellStyle getDataStyle(Sheet sheet){ + CellStyle style = sheet.getWorkbook().createCellStyle(); + // 设置边框线 + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + style.setBorderTop(BorderStyle.THIN); + Font font = sheet.getWorkbook().createFont(); + + // 设置字体大小(例如,设置为14) + font.setFontHeightInPoints((short) 14); + style.setFont(font); + style.setWrapText(true);//设置单元格内容自动换行 + // 设置水平居中 + style.setAlignment(HorizontalAlignment.LEFT); + // 设置垂直居中 + style.setVerticalAlignment(VerticalAlignment.CENTER); + return style; + } + private static void mergeAndStyleCells(Sheet sheet, CellRangeAddress cellRangeAddress, String cellValue) { + // 合并单元格 + sheet.addMergedRegion(cellRangeAddress); + + // 创建一个单元格样式 + CellStyle style = sheet.getWorkbook().createCellStyle(); + + // 设置字体为加粗 + Font font = sheet.getWorkbook().createFont(); + font.setBold(true); + // 设置字体大小(例如,设置为14) + font.setFontHeightInPoints((short) 14); + style.setFont(font); + + // 设置水平居中 + style.setAlignment(HorizontalAlignment.CENTER); + // 设置垂直居中 + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setWrapText(true);//设置单元格内容自动换行 + // 获取合并后的单元格的第一个单元格,并设置值 + Row row = sheet.getRow(cellRangeAddress.getFirstRow()); + if (row == null) { + row = sheet.createRow(cellRangeAddress.getFirstRow()); + } + Cell cell = row.getCell(cellRangeAddress.getFirstColumn()); + if (cell == null) { + cell = row.createCell(cellRangeAddress.getFirstColumn()); + } + cell.setCellValue(cellValue); // 设置单元格的值 + cell.setCellStyle(style); // 应用样式到单元格 + } + private static void mergeAndStyleCells2(Sheet sheet,Row row, CellRangeAddress cellRangeAddress, String cellValue, boolean centered, boolean hasBackground, IndexedColors backgroundColor) { + // 合并单元格 + sheet.addMergedRegion(cellRangeAddress); + + // 创建一个单元格样式 + CellStyle style = sheet.getWorkbook().createCellStyle(); + + // 设置字体居中 + if (centered) { + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + } + + // 设置背景颜色(如果有) + if (hasBackground && backgroundColor != null) { + style.setFillForegroundColor(backgroundColor.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + } + + // 设置边框线 + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + style.setBorderTop(BorderStyle.THIN); + + // 获取合并后的单元格的第一个单元格,并设置值 + Cell cell = row.getCell(cellRangeAddress.getFirstColumn()); + if (cell == null) { + cell = row.createCell(cellRangeAddress.getFirstColumn()); + } + cell.setCellValue(cellValue); // 设置单元格的值 + cell.setCellStyle(style); // 应用样式到单元格 + } + private static void mergeAndStyleCellsNoBorder(Sheet sheet,Row row, CellRangeAddress cellRangeAddress, String cellValue, boolean centered, boolean hasBackground, IndexedColors backgroundColor) { + // 合并单元格 + sheet.addMergedRegion(cellRangeAddress); + + // 创建一个单元格样式 + CellStyle style = sheet.getWorkbook().createCellStyle(); + + // 设置字体居中 + if (centered) { + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + } + + // 设置背景颜色(如果有) + if (hasBackground && backgroundColor != null) { + style.setFillForegroundColor(backgroundColor.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + } + + // 获取合并后的单元格的第一个单元格,并设置值 + Cell cell = row.getCell(cellRangeAddress.getFirstColumn()); + if (cell == null) { + cell = row.createCell(cellRangeAddress.getFirstColumn()); + } + cell.setCellValue(cellValue); // 设置单元格的值 + cell.setCellStyle(style); // 应用样式到单元格 + } +} \ No newline at end of file diff --git a/op-modules/op-quality/src/main/java/com/op/quality/controller/QcCheckReportProduceController.java b/op-modules/op-quality/src/main/java/com/op/quality/controller/QcCheckReportProduceController.java index b5bbe5919..6f0fea390 100644 --- a/op-modules/op-quality/src/main/java/com/op/quality/controller/QcCheckReportProduceController.java +++ b/op-modules/op-quality/src/main/java/com/op/quality/controller/QcCheckReportProduceController.java @@ -3,10 +3,7 @@ package com.op.quality.controller; import com.op.common.core.domain.ExcelCol; import com.op.common.core.utils.DateUtils; import com.op.common.core.utils.StringUtils; -import com.op.common.core.utils.poi.ExcelReportMapUtil; -import com.op.common.core.utils.poi.ExcelSCReportMapUtil; -import com.op.common.core.utils.poi.ExcelSCXJReportMapUtil; -import com.op.common.core.utils.poi.ExcelUtil; +import com.op.common.core.utils.poi.*; import com.op.common.core.web.controller.BaseController; import com.op.common.core.web.domain.AjaxResult; import com.op.common.core.web.page.TableDataInfo; @@ -286,6 +283,118 @@ public class QcCheckReportProduceController extends BaseController { } } } + + @RequiresPermissions("quality:produceReport:export") + @Log(title = "批次成品检报告导出", businessType = BusinessType.EXPORT) + @PostMapping("/cppcReportExport") + public void cppcReportExport(HttpServletResponse response, QcCheckTaskIncome qcCheckTaskIncome) { + List list = qcCheckReportProduceService.getCkeckProjectMap(qcCheckTaskIncome.getRecordId()); + List bytes = new ArrayList<>();//图片 + SysFile sysFile = null; + for(Map mapdto:list){ + sysFile = new SysFile(); + if(mapdto.get("files")!=null){ + sysFile.setUrl(mapdto.get("files").toString()); + byte[] byte0 = remoteFileService.downLoadFileByte(sysFile); + bytes.add(byte0); + }else{ + bytes.add(null); + } + } + QcCheckReportIncome detailInfo = qcCheckReportProduceService.selectQcCheckReportIncomeByRecordId(qcCheckTaskIncome.getRecordId()); + + // 定义正则表达式,匹配id=后面的内容直到&fileName之前的部分 + String regex = "id=([^&]+)&fileName"; + // 创建Pattern对象 + Pattern pattern = Pattern.compile(regex); + // 创建Matcher对象 + if(StringUtils.isNotBlank(detailInfo.getCxzz())){ + Matcher matcher = pattern.matcher(detailInfo.getCxzz());//产线组长 + // 查找匹配项 + if (matcher.find()) { + // 提取括号内的内容,即id=和&fileName之间的部分 + String value = matcher.group(1); + SysFile sysFile1 = new SysFile(); + sysFile1.setUrl(value); + byte[] byte0 = remoteFileService.downLoadFileByte(sysFile1); + bytes.add(byte0); + } + }else{ + bytes.add(null); + } + if(StringUtils.isNotBlank(detailInfo.getJgy())){ + Matcher matcher2 = pattern.matcher(detailInfo.getJgy());//机管员 + // 查找匹配项 + if (matcher2.find()) { + // 提取括号内的内容,即id=和&fileName之间的部分 + String value = matcher2.group(1); + SysFile sysFile1 = new SysFile(); + sysFile1.setUrl(value); + byte[] byte0 = remoteFileService.downLoadFileByte(sysFile1); + bytes.add(byte0); + } + }else{ + bytes.add(null); + } + if(StringUtils.isNotBlank(detailInfo.getPgy())){ + Matcher matcher3 = pattern.matcher(detailInfo.getPgy());//机管员 + // 查找匹配项 + if (matcher3.find()) { + // 提取括号内的内容,即id=和&fileName之间的部分 + String value = matcher3.group(1); + SysFile sysFile1 = new SysFile(); + sysFile1.setUrl(value); + byte[] byte0 = remoteFileService.downLoadFileByte(sysFile1); + bytes.add(byte0); + } + }else{ + bytes.add(null); + } + + Map detailMap = new HashMap<>(); + detailMap.put("orderType",detailInfo.getOrderType()); + detailMap.put("title","批次检验确认表"); + detailMap.put("incomeBatchNo",detailInfo.getIncomeBatchNo()); + detailMap.put("checkNo",detailInfo.getCheckNo()); + detailMap.put("materialCode",detailInfo.getMaterialCode()); + detailMap.put("materialName",detailInfo.getMaterialName()); + detailMap.put("checkLoc",detailInfo.getCheckLoc()); + detailMap.put("reason",detailInfo.getReason()); + detailMap.put("checkType",detailInfo.getCheckType()); + detailMap.put("standardNo",detailInfo.getStandardNo()); + detailMap.put("incomeTime",DateUtils.parseDateToStr("yyyy-MM-dd",detailInfo.getIncomeTime())); + if(StringUtils.isNotBlank(detailInfo.getCheckResult())){ + detailMap.put("checkResult",detailInfo.getCheckResult().equals("Y")?"√合格":"×不合格"); + } + + detailMap.put("checkManName",detailInfo.getCheckManName()); + detailMap.put("remark",detailInfo.getRemark()); + //表格结构数据 + ArrayList excelCols = new ArrayList<>(); + excelCols.add(new ExcelCol("检验项目", "projectRuleName", 60)); + excelCols.add(new ExcelCol("内容", "ruleName", 30)); + excelCols.add(new ExcelCol("判定", "status", 30)); + excelCols.add(new ExcelCol("附件", "files", 30)); + String sheetName = "批次检验报告"; + SXSSFWorkbook workbook = null; + try { + //设置响应头 + response.setHeader("Content-disposition", + "attachment; filename=" + sheetName); + response.setContentType("application/octet-stream;charset=UTF-8"); + ServletOutputStream outputStream = response.getOutputStream(); + //调用工具类 + workbook = ExcelCPPCReportMapUtil.initWorkbook(sheetName, "-", excelCols, list, detailMap,bytes); + workbook.write(outputStream); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (workbook != null) { + workbook.dispose(); + } + } + } + private List getMapFromList(List dtos){ List maps = new ArrayList<>(); int n = 1; diff --git a/op-modules/op-quality/src/main/resources/mapper/quality/QcCheckTaskProduceMapper.xml b/op-modules/op-quality/src/main/resources/mapper/quality/QcCheckTaskProduceMapper.xml index 3f55a007d..b4b37cd5c 100644 --- a/op-modules/op-quality/src/main/resources/mapper/quality/QcCheckTaskProduceMapper.xml +++ b/op-modules/op-quality/src/main/resources/mapper/quality/QcCheckTaskProduceMapper.xml @@ -361,8 +361,8 @@ qct.supplier_code, qct.supplier_name, qct.income_time, qct.check_loc, qct.check_status, qct.check_time, qct.check_result, qct.check_type, CASE - WHEN 'checkTypeSC' = #{checkType} THEN '首件检验' - WHEN 'checkTypeCPPC' = #{checkType} THEN '批次成品检验' + WHEN qct.check_type = 'checkTypeSC' THEN '首件检验' + WHEN qct.check_type = 'checkTypeCPPC' THEN '批次成品检验' ELSE '' END check_name, CONVERT(varchar(10),qct.create_time, 120) createTimeStr, @@ -393,6 +393,42 @@ and #{checkTimeEnd} > CONVERT(varchar(30),qct.create_time, 120) and qct.check_type in ('checkTypeSC','checkTypeCPPC') and qct.del_flag = '0' + union ALL + select + '','','', + qct.order_no, qct.material_code, qct.material_name, qct.quality, qct.unit, + qct.supplier_code, qct.supplier_name,CONVERT(varchar(10), qct.income_time, 120) income_time,'','', + null,'', qct.check_type,'巡检检验' check_name,CONVERT(varchar(10),qct.create_time, 120) createTimeStr, + qct.confirm,qct.confirm_man_name,'','' + from qc_check_task qct + + and qct.check_no = #{checkNo} + and qct.income_batch_no = #{incomeBatchNo} + and qct.order_no = #{orderNo} + and qct.material_code = #{materialCode} + and qct.material_name like concat('%', + #{materialName}, '%') + + and qct.supplier_code = #{supplierCode} + and qct.supplier_name like concat('%', + #{supplierName}, '%') + + and qct.check_loc = #{checkLoc} + and qct.check_status = #{checkStatus} + and qct.check_man_code = #{checkManCode} + and qct.check_man_name like concat('%', + #{checkManName}, '%') + + and qct.check_result = #{checkResult} + and CONVERT(varchar(30),qct.income_time, 120) >= #{incomeTimeStart} + and #{incomeTimeEnd} > CONVERT(varchar(30),qct.income_time, 120) + and CONVERT(varchar(30),qct.create_time, 120) >= #{checkTimeStart} + and #{checkTimeEnd} > CONVERT(varchar(30),qct.create_time, 120) + and qct.check_type = 'checkTypeSCXJ' and qct.del_flag = '0' + + GROUP BY qct.order_no, qct.material_code, qct.material_name, qct.quality, qct.unit, + qct.supplier_code, qct.supplier_name,CONVERT(varchar(10), qct.income_time, 120), qct.check_type,CONVERT(varchar(10),qct.create_time, 120), + qct.confirm,qct.confirm_man_name ) t left join pro_order_workorder pow on pow.workorder_code = t.order_no where pow.del_flag = '0'