| src/main/java/com/ruoyi/quality/pojo/QualityInspect.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/quality/utils/FinalInspectExportUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/quality/utils/ProcessInspectExportUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/quality/utils/RawMaterialInspectExportUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/quality/QualityInspectMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/static/junge-logo.png | 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
@@ -96,6 +96,18 @@ private String model; /** * æè´¨ */ @Excel(name = "æè´¨") private String material; /** * éªæ¶ä¾æ® */ @Excel(name = "éªæ¶ä¾æ®") private String acceptanceBasis; /** * åä½ */ @Excel(name = "åä½") @@ -107,6 +119,71 @@ @Excel(name = "æ»æ°é") private BigDecimal quantity; /** * æ½æ£æ° */ @Excel(name = "æ½æ£æ°") private BigDecimal samplingCount; /** * å¾çº¸å ³é®é¨ä½å°ºå¯¸ */ @Excel(name = "å¾çº¸å ³é®é¨ä½å°ºå¯¸") private String drawingKeyDimensions; /** * 宿µå ³é®é¨ä½å°ºå¯¸ */ @Excel(name = "宿µå ³é®é¨ä½å°ºå¯¸") private String measuredKeyDimensions; /** * ä¸»è¦ææ¯åæ°(è¿ç¨æ£éª) */ @Excel(name = "ä¸»è¦ææ¯åæ°") private String mainTechnicalParams; /** * å®é ææ¯åæ°(è¿ç¨æ£éª) */ @Excel(name = "å®é ææ¯åæ°") private String actualTechnicalParams; /** * 说æä¹¦(è¿ç¨æ£éª) */ @Excel(name = "说æä¹¦") private String specificationManual; /** * å ¥åºç¼å· */ @Excel(name = "å ¥åºç¼å·") private String warehouseCode; /** * æå±è®¾å¤åç§° */ @Excel(name = "æå±è®¾å¤åç§°") private String equipmentName; /** * 项ç®åç§° */ @Excel(name = "项ç®åç§°") private String projectName; /** * å¤å®(åæ ¼/ä¸åæ ¼) */ @Excel(name = "å¤å®") private String verdict; /** * å¼å¸¸å¤æ³¨(åæææ£éª) */ private String abnormalRemark; @Excel(name = "åæ ¼æ°é") @TableField("qualified_quantity") private BigDecimal qualifiedQuantity; src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -21,6 +21,9 @@ import com.ruoyi.procurementrecord.service.ProcurementRecordService; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.quality.dto.QualityInspectDto; import com.ruoyi.quality.utils.FinalInspectExportUtil; import com.ruoyi.quality.utils.ProcessInspectExportUtil; import com.ruoyi.quality.utils.RawMaterialInspectExportUtil; import com.ruoyi.quality.mapper.QualityInspectMapper; import com.ruoyi.quality.mapper.QualityTestStandardMapper; import com.ruoyi.quality.mapper.QualityUnqualifiedMapper; @@ -82,12 +85,15 @@ public int add(QualityInspectDto qualityInspectDto) { QualityInspect qualityInspect = new QualityInspect(); BeanUtils.copyProperties(qualityInspectDto, qualityInspect); qualityInspect.setId(null);//强å¶èµ°æ°æ®åºèªå¢ï¼é¿å åç«¯è¯¯ä¼ id导è´ä¸»é®å²çª qualityInspect.setInspectState(0);//é»è®¤æªæäº¤ qualityInspectMapper.insert(qualityInspect); if (ObjectUtils.isNotEmpty(qualityInspectDto.getQualityInspectParams())) { for (QualityInspectParam qualityInspectParam : qualityInspectDto.getQualityInspectParams()) { qualityInspectParam.setInspectId(qualityInspect.getId()); } qualityInspectParamService.saveBatch(qualityInspectDto.getQualityInspectParams()); } // ä¿åéä»¶ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_INSPECT, qualityInspect.getId(), qualityInspectDto.getStorageBlobDTOs()); return 0; @@ -110,9 +116,36 @@ public int submit(QualityInspect inspect) { QualityInspect qualityInspect = qualityInspectMapper.selectById(inspect.getId()); if (Integer.valueOf(1).equals(qualityInspect.getInspectState())) { throw new ServiceException("该记å½å·²æäº¤ï¼ä¸è½éå¤æäº¤"); } // åæææ£éª/è¿ç¨æ£éª/åºåæ£éªï¼è¡¨åä¸åå¡«ååæ ¼/ä¸åæ ¼æ°éï¼æ¹ç¨ãå¤å®ãåæ®µ boolean isVerdictInspect = qualityInspect.getInspectType() != null && (qualityInspect.getInspectType() == 0 || qualityInspect.getInspectType() == 1 || qualityInspect.getInspectType() == 2); //æäº¤åå¿ é¡»å¤ææ¯å¦åæ ¼ if (ObjectUtils.isNull(qualityInspect.getCheckResult())) { if (isVerdictInspect) { // æ¹ç¨ãå¤å®ãåæ®µ if (ObjectUtils.isNull(qualityInspect.getVerdict())) { throw new ServiceException("请å å¤å®æ¯å¦åæ ¼"); } } else { throw new ServiceException("请å 夿æ¯å¦åæ ¼"); } } // ç±ãå¤å®ãæ¨å¯¼åæ ¼/ä¸åæ ¼æ°é if (isVerdictInspect) { BigDecimal total = qualityInspect.getQuantity() == null ? BigDecimal.ZERO : qualityInspect.getQuantity(); if ("åæ ¼".equals(qualityInspect.getVerdict())) { qualityInspect.setQualifiedQuantity(total); qualityInspect.setUnqualifiedQuantity(BigDecimal.ZERO); } else if ("ä¸åæ ¼".equals(qualityInspect.getVerdict())) { qualityInspect.setQualifiedQuantity(BigDecimal.ZERO); qualityInspect.setUnqualifiedQuantity(total); } } if (ObjectUtils.isNull(qualityInspect.getQualifiedQuantity())) { @@ -166,7 +199,10 @@ qualityUnqualified.setProductModelId(qualityInspect.getProductModelId()); List<QualityInspectParam> inspectParams = qualityInspectParamService.list(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, inspect.getId())); String text = inspectParams.stream().map(QualityInspectParam::getParameterItem).collect(Collectors.joining(",")); qualityUnqualified.setDefectivePhenomena(text + "è¿äºææ ä¸åå¨ä¸åæ ¼");//ä¸åæ ¼ç°è±¡ if (text == null || text.isEmpty()) { text = qualityInspect.getAbnormalRemark(); } qualityUnqualified.setDefectivePhenomena((text == null || text.isEmpty()) ? "æ£éªä¸åæ ¼" : text + "è¿äºææ ä¸åå¨ä¸åæ ¼");//ä¸åæ ¼ç°è±¡ qualityUnqualified.setInspectId(qualityInspect.getId()); qualityUnqualifiedMapper.insert(qualityUnqualified); @@ -208,6 +244,9 @@ return R.ok("æ£éªåå·²æäº¤"); } if (ObjectUtils.isNull(qualityInspect.getVerdict())) { qualityInspect.setVerdict("åæ ¼"); } if (ObjectUtils.isNull(qualityInspect.getCheckResult())) { qualityInspect.setCheckResult("åæ ¼"); } @@ -336,6 +375,21 @@ @Override public void qualityInspectExport(HttpServletResponse response, QualityInspect qualityInspect) { List<QualityInspect> qualityInspects = qualityInspectMapper.qualityInspectExport(qualityInspect); // åæææ£éªï¼æçº¸è´¨åæ®æ ·å¼å¯¼åº if (qualityInspect.getInspectType() != null && qualityInspect.getInspectType() == 0) { RawMaterialInspectExportUtil.export(response, qualityInspects); return; } // è¿ç¨æ£éªï¼æçº¸è´¨åæ®æ ·å¼å¯¼åº if (qualityInspect.getInspectType() != null && qualityInspect.getInspectType() == 1) { ProcessInspectExportUtil.export(response, qualityInspects); return; } // åºåæ£éªï¼æçº¸è´¨åæ®æ ·å¼å¯¼åº if (qualityInspect.getInspectType() != null && qualityInspect.getInspectType() == 2) { FinalInspectExportUtil.export(response, qualityInspects); return; } ExcelUtil<QualityInspect> util = new ExcelUtil<QualityInspect>(QualityInspect.class); switch (qualityInspect.getInspectType()) { case 0: src/main/java/com/ruoyi/quality/utils/FinalInspectExportUtil.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,384 @@ package com.ruoyi.quality.utils; import com.ruoyi.quality.pojo.QualityInspect; import jakarta.servlet.http.HttpServletResponse; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.PrintSetup; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.util.Units; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.List; /** * åºåæ£éªå¯¼åºï¼æçº¸è´¨åæ®æ ·å¼çæ Excelï¼ */ public class FinalInspectExportUtil { // ==================== å¯å®å¶åºåï¼æ¹è¿éå³å¯è°æ´æ¨¡æ¿ï¼ ==================== /** LOGO å¾çä¸åå æ ¼è¾¹æ¡ä¹é´ççç½ï¼åç´ ï¼ */ private static final float LOGO_PADDING_PX = 6f; /** å·¦ä¸è§ LOGO å¾çï¼classpath è·¯å¾ï¼æ¾å¨ resources/static ä¸ï¼ */ private static final String LOGO_IMAGE_PATH = "/static/junge-logo.png"; /** æ¬å°å¼åç¯å¢ LOGO ç»å¯¹è·¯å¾ï¼ä¼å 读åï¼ */ private static final String LOGO_ABS_PATH = "D:/develop/XingRuan/product-inventory-management-junge/product-inventory-management/multiple/assets/logo/JunGeJiTuan-logo.png"; /** å± ä¸å¤§æ é¢ */ private static final String TITLE = "åºåæ£éªè®°å½è¡¨"; /** åºå®æ°æ®è¡æ°ï¼æ°æ®ä¸è¶³è¡¥ç©ºè¡ï¼è¶ è¿èªå¨è¿½å ï¼ */ private static final int FIXED_ROW_COUNT = 14; /** 表头åï¼ä»å·¦å°å³ï¼ */ private static final String[] HEADERS = { "åºå·", "åç§°", "å¾å·", "æè´¨", "æ£éªä¾æ®", "æ°é", "æ½æ£æ°", "å¾çº¸å ³é®é¨ä½å°ºå¯¸", "宿µå ³é®é¨ä½å°ºå¯¸", "æ£éªæ¥æ", "å ¥åºç¼å·", "æå±è®¾å¤åç§°", "项ç®åå", "å¤å®" }; /** å宽èªéåºï¼æ¯åå¨å 容宽度åºç¡ä¸é¢å¤å ç宽度ï¼çº¦çäºä¸ä¸ªæ±åå®½åº¦ï¼ */ private static final int COL_WIDTH_PADDING = 2; /** ååæå¤§å®½åº¦ï¼çº¦çäºæ±å个æ°ï¼ï¼é²æ¢ä¸ªå«è¶ é¿å 容æåæå¾è¿å®½ */ private static final int COL_WIDTH_MAX = 40; /** æ£æ/æ é¢åå· */ private static final float BODY_FONT_SIZE = 12f; private static final float TITLE_FONT_SIZE = 16f; /** æ¯å¦æ¨ªåæå° */ private static final boolean LANDSCAPE = true; // ======================================================================== public static void export(HttpServletResponse response, List<QualityInspect> list) { try (XSSFWorkbook workbook = new XSSFWorkbook()) { Sheet sheet = workbook.createSheet(TITLE); int colCount = HEADERS.length; // æ ·å¼ CellStyle titleStyle = createStyle(workbook, true, TITLE_FONT_SIZE, HorizontalAlignment.CENTER); CellStyle labelStyle = createStyle(workbook, false, BODY_FONT_SIZE, HorizontalAlignment.LEFT); CellStyle headerStyle = createStyle(workbook, true, BODY_FONT_SIZE, HorizontalAlignment.CENTER); CellStyle centerStyle = createStyle(workbook, false, BODY_FONT_SIZE, HorizontalAlignment.CENTER); CellStyle leftStyle = createStyle(workbook, false, BODY_FONT_SIZE, HorizontalAlignment.LEFT); leftStyle.setWrapText(true); // æ°æ®åºæ ·å¼å è¾¹æ¡ addThinBorder(headerStyle); addThinBorder(centerStyle); addThinBorder(leftStyle); // ---- 第1~2è¡ï¼é¡µç ---- Row row1 = sheet.createRow(0); Row row2 = sheet.createRow(1); row1.setHeightInPoints(45); row2.setHeightInPoints(20); // å·¦ä¸ï¼å ¬å¸ LOGO å¾çï¼A1:C2 åå¹¶åå æ ¼ï¼ CellRangeAddress logoRegion = new CellRangeAddress(0, 1, 0, 2); sheet.addMergedRegion(logoRegion); Cell logoCell = row1.createCell(0); logoCell.setCellStyle(createStyle(workbook, false, 12f, HorizontalAlignment.CENTER)); applyRegionBorder(sheet, logoRegion); // å± ä¸å¤§æ é¢ï¼D~Kï¼ Cell titleCell = row1.createCell(3); titleCell.setCellValue(TITLE); titleCell.setCellStyle(titleStyle); CellRangeAddress titleRegion = new CellRangeAddress(0, 1, 3, colCount - 4); sheet.addMergedRegion(titleRegion); applyRegionBorder(sheet, titleRegion); // å³ä¸ï¼æä»¶ç¼å· / 页æ°ï¼é å·¦ï¼ Cell fileNoCell = row1.createCell(colCount - 3); fileNoCell.setCellValue("æä»¶ç¼å·ï¼"); fileNoCell.setCellStyle(labelStyle); CellRangeAddress fileNoRegion = new CellRangeAddress(0, 0, colCount - 3, colCount - 1); sheet.addMergedRegion(fileNoRegion); applyRegionBorder(sheet, fileNoRegion); Cell pageCell = row2.createCell(colCount - 3); pageCell.setCellValue("é¡µæ° / No.ï¼"); pageCell.setCellStyle(labelStyle); CellRangeAddress pageRegion = new CellRangeAddress(1, 1, colCount - 3, colCount - 1); sheet.addMergedRegion(pageRegion); applyRegionBorder(sheet, pageRegion); // ---- 第3è¡ï¼è¡¨å¤´ ---- int headerRowIndex = 2; Row headerRow = sheet.createRow(headerRowIndex); headerRow.setHeightInPoints(24); for (int i = 0; i < colCount; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(HEADERS[i]); cell.setCellStyle(headerStyle); } // ---- æ°æ®è¡ï¼åºå®è¡æ°ï¼ä¸è¶³è¡¥ç©ºè¡ ---- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); int dataRows = Math.max(FIXED_ROW_COUNT, list.size()); for (int r = 0; r < dataRows; r++) { Row dataRow = sheet.createRow(headerRowIndex + 1 + r); for (int c = 0; c < colCount; c++) { Cell cell = dataRow.createCell(c); // ææ¬ç±»å左对é½ï¼å ¶ä½å± ä¸ï¼åºå·/æ°é/æ½æ£æ°/æ£éªæ¥æ/å¤å®å± ä¸ï¼ boolean isTextColumn = c == 1 || c == 2 || c == 3 || c == 4 || c == 7 || c == 8 || c == 10 || c == 11 || c == 12; cell.setCellStyle(isTextColumn ? leftStyle : centerStyle); } // åºå·åºå®ç¼å· 1~N dataRow.getCell(0).setCellValue(r + 1); if (r < list.size()) { QualityInspect item = list.get(r); setText(dataRow.getCell(1), item.getProductName()); // åç§° setText(dataRow.getCell(2), item.getModel()); // å¾å· setText(dataRow.getCell(3), item.getMaterial()); // æè´¨ setText(dataRow.getCell(4), item.getAcceptanceBasis()); // æ£éªä¾æ® setText(dataRow.getCell(5), plain(item.getQuantity())); // æ°é setText(dataRow.getCell(6), plain(item.getSamplingCount())); // æ½æ£æ° setText(dataRow.getCell(7), item.getDrawingKeyDimensions()); // å¾çº¸å ³é®é¨ä½å°ºå¯¸ setText(dataRow.getCell(8), item.getMeasuredKeyDimensions()); // 宿µå ³é®é¨ä½å°ºå¯¸ setText(dataRow.getCell(9), item.getCheckTime() == null ? "" : sdf.format(item.getCheckTime())); // æ£éªæ¥æ setText(dataRow.getCell(10), item.getWarehouseCode()); // å ¥åºç¼å· setText(dataRow.getCell(11), item.getEquipmentName()); // æå±è®¾å¤åç§° setText(dataRow.getCell(12), item.getProjectName()); // 项ç®åå setText(dataRow.getCell(13), item.getVerdict()); // å¤å® } // æ ¹æ®ææ¬åæ¢è¡è¡æ°ä¼°ç®è¡é« dataRow.setHeightInPoints(estimateRowHeight(dataRow, colCount)); } // å宽æå 容èªéåº autoSizeColumns(sheet, colCount, headerRowIndex, dataRows); // å宽确å®åååµå ¥ LOGO addLogoImage(workbook, sheet); // ---- 页é¢è®¾ç½®ï¼A4 ---- PrintSetup ps = sheet.getPrintSetup(); ps.setPaperSize(PrintSetup.A4_PAPERSIZE); ps.setLandscape(LANDSCAPE); sheet.setMargin(Sheet.TopMargin, 0.4); sheet.setMargin(Sheet.BottomMargin, 0.4); sheet.setMargin(Sheet.LeftMargin, 0.3); sheet.setMargin(Sheet.RightMargin, 0.3); sheet.setFitToPage(true); ps.setFitWidth((short) 1); ps.setFitHeight((short) 0); // ---- è¾åº ---- response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); String fileName = URLEncoder.encode(TITLE, "UTF-8"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); OutputStream os = response.getOutputStream(); workbook.write(os); os.flush(); } catch (Exception e) { throw new RuntimeException("导åºå¤±è´¥", e); } } /** å¨ A1:C2 åå¹¶åºåµå ¥å ¬å¸ LOGO å¾ç */ private static void addLogoImage(XSSFWorkbook workbook, Sheet sheet) { byte[] bytes = loadLogoBytes(); if (bytes == null) { System.err.println("[FinalInspectExport] LOGO å¾çæªæ¾å°ï¼å¯¼åºå°ä¸å¸¦ LOGOï¼èµæºè·¯å¾: " + LOGO_IMAGE_PATH + "ï¼"); return; } try { int pictureIdx = workbook.addPicture(bytes, XSSFWorkbook.PICTURE_TYPE_PNG); XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch(); // å¾çå®ä½ï¼A1:C1 åºåå float colAPx = sheet.getColumnWidthInPixels(0); float colBPx = sheet.getColumnWidthInPixels(1); float colCPx = sheet.getColumnWidthInPixels(2); float blockWidthPx = colAPx + colBPx + colCPx; float row0Px = sheet.getRow(0).getHeightInPoints() * 96f / 72f; float row1Px = sheet.getRow(1).getHeightInPoints() * 96f / 72f; float cellHPx = row0Px + row1Px; // 读åå¾ççå®å®½é« int imgW = 236; int imgH = 190; if (bytes.length > 24) { imgW = readInt(bytes, 16); imgH = readInt(bytes, 20); } // æåå æ ¼å¤§å°çæ¯ç¼©æ¾ï¼åå¨çç½ï¼ï¼æ´ä½å± ä¸ float availW = blockWidthPx - LOGO_PADDING_PX * 2; float availH = cellHPx - LOGO_PADDING_PX * 2; float scale = Math.min(availW / imgW, availH / imgH); float dispW = imgW * scale; float dispH = imgH * scale; float absLeft = LOGO_PADDING_PX + (availW - dispW) / 2f; float absTop = LOGO_PADDING_PX + (availH - dispH) / 2f; float absRight = absLeft + dispW; float absBottom = absTop + dispH; // è®¡ç® from/to éç¹ï¼ææåç§»éä¿æå¨æå¨å/è¡çåæ³èå´å int fromCol; int fromOffPx; if (absLeft <= colAPx) { fromCol = 0; fromOffPx = (int) absLeft; } else if (absLeft <= colAPx + colBPx) { fromCol = 1; fromOffPx = (int) (absLeft - colAPx); } else { fromCol = 2; fromOffPx = (int) (absLeft - colAPx - colBPx); } int toCol; int toOffPx; if (absRight <= colAPx) { toCol = 0; toOffPx = (int) absRight; } else if (absRight <= colAPx + colBPx) { toCol = 1; toOffPx = (int) (absRight - colAPx); } else { toCol = 2; toOffPx = (int) (absRight - colAPx - colBPx); } int fromRow = 0; float fromRowOff = absTop; if (absTop > row0Px) { fromRow = 1; fromRowOff = absTop - row0Px; } int toRow = 0; float toRowOff = absBottom; if (absBottom > row0Px) { toRow = 1; toRowOff = absBottom - row0Px; } XSSFClientAnchor anchor = new XSSFClientAnchor( fromOffPx * Units.EMU_PER_PIXEL, (int) (fromRowOff * Units.EMU_PER_PIXEL), toOffPx * Units.EMU_PER_PIXEL, (int) (toRowOff * Units.EMU_PER_PIXEL), fromCol, fromRow, toCol, toRow); anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); drawing.createPicture(anchor, pictureIdx); } catch (Exception e) { // LOGO å 载失败ä¸å½±å导åºï¼ä½æå°éè¯¯ä¾¿äºææ¥ System.err.println("[FinalInspectExport] LOGO åµå ¥å¤±è´¥: " + e.getMessage()); } } /** 读å LOGOï¼æ¬å°å¼åä¼å 读ç»å¯¹è·¯å¾ï¼å ¶æ¬¡ classpathï¼æå项ç®ç¸å¯¹è·¯å¾ */ private static byte[] loadLogoBytes() { try (InputStream is = new java.io.FileInputStream(LOGO_ABS_PATH)) { return is.readAllBytes(); } catch (Exception ignored) { } try (InputStream is = FinalInspectExportUtil.class.getResourceAsStream(LOGO_IMAGE_PATH)) { if (is != null) { return is.readAllBytes(); } } catch (Exception ignored) { } try (InputStream is = new java.io.FileInputStream("src/main/resources" + LOGO_IMAGE_PATH)) { return is.readAllBytes(); } catch (Exception e) { return null; } } /** 读å PNG 头é¨ç宽/é«ï¼å¤§ç«¯æ´æ°ï¼ */ private static int readInt(byte[] b, int off) { return ((b[off] & 0xFF) << 24) | ((b[off + 1] & 0xFF) << 16) | ((b[off + 2] & 0xFF) << 8) | (b[off + 3] & 0xFF); } private static CellStyle createStyle(XSSFWorkbook workbook, boolean bold, float fontSize, HorizontalAlignment align) { CellStyle style = workbook.createCellStyle(); Font font = workbook.createFont(); font.setFontName("å®ä½"); font.setBold(bold); font.setFontHeightInPoints((short) fontSize); style.setFont(font); style.setAlignment(align); style.setVerticalAlignment(VerticalAlignment.CENTER); return style; } private static void addThinBorder(CellStyle style) { style.setBorderTop(BorderStyle.THIN); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); } private static void applyRegionBorder(Sheet sheet, CellRangeAddress region) { RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet); RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet); RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet); RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet); } private static void setText(Cell cell, String value) { cell.setCellValue(value == null ? "" : value); } private static String plain(BigDecimal value) { return value == null ? "" : value.toPlainString(); } /** æææ¬åå 容ä¸åå®½ä¼°ç®æ¢è¡åçè¡é«ï¼ç¹æ°ï¼ */ private static float estimateRowHeight(Row row, int colCount) { int maxLines = 1; for (int c = 1; c < colCount; c++) { boolean isTextColumn = c == 1 || c == 2 || c == 3 || c == 4 || c == 7 || c == 8 || c == 10 || c == 11 || c == 12; if (!isTextColumn) { continue; } Cell cell = row.getCell(c); String value = cell == null ? null : cell.getStringCellValue(); if (value == null || value.isEmpty()) { continue; } int lines = (int) Math.ceil(displayLen(value) / (COL_WIDTH_MAX * 2d)); maxLines = Math.max(maxLines, lines); } return Math.max(22f, maxLines * 15f + 6f); } /** å宽èªéåºï¼æè¡¨å¤´ä¸æ°æ®å å®¹è®¡ç®æ¯å宽度 */ private static void autoSizeColumns(Sheet sheet, int colCount, int headerRowIndex, int dataRows) { for (int c = 0; c < colCount; c++) { double maxLen = displayLen(HEADERS[c]); for (int r = 0; r < dataRows; r++) { Row row = sheet.getRow(headerRowIndex + 1 + r); Cell cell = row == null ? null : row.getCell(c); if (cell != null && cell.getCellType() == CellType.STRING) { maxLen = Math.max(maxLen, displayLen(cell.getStringCellValue())); } } double widthChars = Math.min(maxLen + COL_WIDTH_PADDING, COL_WIDTH_MAX + COL_WIDTH_PADDING); // 䏿æä¸¤ä¸ªåè§åç¬¦å®½åº¦è®¡ç® sheet.setColumnWidth(c, (int) (widthChars * 256)); } } /** è®¡ç®æ¾ç¤ºå®½åº¦ï¼ä¸æçå ¨è§å符æ 2 个åè§å®½åº¦è®¡ */ private static double displayLen(String s) { if (s == null) { return 0; } double len = 0; for (char ch : s.toCharArray()) { if ((ch >= 0x2E80 && ch <= 0x9FFF) || (ch >= 0x3000 && ch <= 0x303F) || ch >= 0xFF00) { len += 2; } else { len += 1; } } return len; } } src/main/java/com/ruoyi/quality/utils/ProcessInspectExportUtil.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,381 @@ package com.ruoyi.quality.utils; import com.ruoyi.quality.pojo.QualityInspect; import jakarta.servlet.http.HttpServletResponse; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.PrintSetup; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.util.Units; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.List; /** * è¿ç¨æ£éªå¯¼åºï¼æçº¸è´¨åæ®æ ·å¼çæ Excelï¼ */ public class ProcessInspectExportUtil { // ==================== å¯å®å¶åºåï¼æ¹è¿éå³å¯è°æ´æ¨¡æ¿ï¼ ==================== /** LOGO å¾çä¸åå æ ¼è¾¹æ¡ä¹é´ççç½ï¼åç´ ï¼ */ private static final float LOGO_PADDING_PX = 6f; /** å·¦ä¸è§ LOGO å¾çï¼classpath è·¯å¾ï¼æ¾å¨ resources/static ä¸ï¼ */ private static final String LOGO_IMAGE_PATH = "/static/junge-logo.png"; /** æ¬å°å¼åç¯å¢ LOGO ç»å¯¹è·¯å¾ï¼ä¼å 读åï¼ */ private static final String LOGO_ABS_PATH = "D:/develop/XingRuan/product-inventory-management-junge/product-inventory-management/multiple/assets/logo/JunGeJiTuan-logo.png"; /** å± ä¸å¤§æ é¢ */ private static final String TITLE = "è¿ç¨æ£éªè®°å½è¡¨"; /** åºå®æ°æ®è¡æ°ï¼æ°æ®ä¸è¶³è¡¥ç©ºè¡ï¼è¶ è¿èªå¨è¿½å ï¼ */ private static final int FIXED_ROW_COUNT = 14; /** 表头åï¼ä»å·¦å°å³ï¼ */ private static final String[] HEADERS = { "åºå·", "åç§°", "è§æ ¼åå·", "æè´¨", "éªæ¶ä¾æ®", "æ°é", "æ½æ£æ°", "ä¸»è¦ææ¯åæ°", "å®é ææ¯åæ°", "说æä¹¦", "æ£éªæ¥æ", "å ¥åºç¼å·", "æå±è®¾å¤åç§°", "项ç®åç§°", "å¤å®" }; /** å宽èªéåºï¼æ¯åå¨å 容宽度åºç¡ä¸é¢å¤å ç宽度ï¼çº¦çäºä¸ä¸ªæ±åå®½åº¦ï¼ */ private static final int COL_WIDTH_PADDING = 2; /** ååæå¤§å®½åº¦ï¼çº¦çäºæ±å个æ°ï¼ï¼é²æ¢ä¸ªå«è¶ é¿å 容æåæå¾è¿å®½ */ private static final int COL_WIDTH_MAX = 40; /** æ£æ/æ é¢åå· */ private static final float BODY_FONT_SIZE = 12f; private static final float TITLE_FONT_SIZE = 16f; /** æ¯å¦æ¨ªåæå° */ private static final boolean LANDSCAPE = true; // ======================================================================== public static void export(HttpServletResponse response, List<QualityInspect> list) { try (XSSFWorkbook workbook = new XSSFWorkbook()) { Sheet sheet = workbook.createSheet(TITLE); int colCount = HEADERS.length; // æ ·å¼ CellStyle titleStyle = createStyle(workbook, true, TITLE_FONT_SIZE, HorizontalAlignment.CENTER); CellStyle labelStyle = createStyle(workbook, false, BODY_FONT_SIZE, HorizontalAlignment.LEFT); CellStyle headerStyle = createStyle(workbook, true, BODY_FONT_SIZE, HorizontalAlignment.CENTER); CellStyle centerStyle = createStyle(workbook, false, BODY_FONT_SIZE, HorizontalAlignment.CENTER); centerStyle.setWrapText(true); // æ°æ®åºæ ·å¼å è¾¹æ¡ addThinBorder(headerStyle); addThinBorder(centerStyle); // ---- 第1~2è¡ï¼é¡µç ---- Row row1 = sheet.createRow(0); Row row2 = sheet.createRow(1); row1.setHeightInPoints(36); row2.setHeightInPoints(16); // å·¦ä¸ï¼å ¬å¸ LOGO å¾çï¼A1:C2 åå¹¶åå æ ¼ï¼ CellRangeAddress logoRegion = new CellRangeAddress(0, 1, 0, 2); sheet.addMergedRegion(logoRegion); Cell logoCell = row1.createCell(0); logoCell.setCellStyle(createStyle(workbook, false, 12f, HorizontalAlignment.CENTER)); applyRegionBorder(sheet, logoRegion); // å± ä¸å¤§æ é¢ Cell titleCell = row1.createCell(3); titleCell.setCellValue(TITLE); titleCell.setCellStyle(titleStyle); CellRangeAddress titleRegion = new CellRangeAddress(0, 1, 3, colCount - 4); sheet.addMergedRegion(titleRegion); applyRegionBorder(sheet, titleRegion); // å³ä¸ï¼æä»¶ç¼å· / 页æ°ï¼é å·¦ï¼ Cell fileNoCell = row1.createCell(colCount - 3); fileNoCell.setCellValue("æä»¶ç¼å·ï¼"); fileNoCell.setCellStyle(labelStyle); CellRangeAddress fileNoRegion = new CellRangeAddress(0, 0, colCount - 3, colCount - 1); sheet.addMergedRegion(fileNoRegion); applyRegionBorder(sheet, fileNoRegion); Cell pageCell = row2.createCell(colCount - 3); pageCell.setCellValue("é¡µæ° / No.ï¼"); pageCell.setCellStyle(labelStyle); CellRangeAddress pageRegion = new CellRangeAddress(1, 1, colCount - 3, colCount - 1); sheet.addMergedRegion(pageRegion); applyRegionBorder(sheet, pageRegion); // ---- 第3è¡ï¼è¡¨å¤´ ---- int headerRowIndex = 2; Row headerRow = sheet.createRow(headerRowIndex); headerRow.setHeightInPoints(24); for (int i = 0; i < colCount; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(HEADERS[i]); cell.setCellStyle(headerStyle); } // ---- æ°æ®è¡ï¼åºå®è¡æ°ï¼ä¸è¶³è¡¥ç©ºè¡ï¼æ°æ®å ¨é¨å± ä¸ ---- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); int dataRows = Math.max(FIXED_ROW_COUNT, list.size()); for (int r = 0; r < dataRows; r++) { Row dataRow = sheet.createRow(headerRowIndex + 1 + r); for (int c = 0; c < colCount; c++) { Cell cell = dataRow.createCell(c); cell.setCellStyle(centerStyle); } // åºå·åºå®ç¼å· 1~N dataRow.getCell(0).setCellValue(r + 1); if (r < list.size()) { QualityInspect item = list.get(r); setText(dataRow.getCell(1), item.getProductName()); // åç§° setText(dataRow.getCell(2), item.getModel()); // è§æ ¼åå· setText(dataRow.getCell(3), item.getMaterial()); // æè´¨ setText(dataRow.getCell(4), item.getAcceptanceBasis()); // éªæ¶ä¾æ® setText(dataRow.getCell(5), plain(item.getQuantity())); // æ°é setText(dataRow.getCell(6), plain(item.getSamplingCount())); // æ½æ£æ° setText(dataRow.getCell(7), item.getMainTechnicalParams()); // ä¸»è¦ææ¯åæ° setText(dataRow.getCell(8), item.getActualTechnicalParams()); // å®é ææ¯åæ° setText(dataRow.getCell(9), item.getSpecificationManual()); // 说æä¹¦ setText(dataRow.getCell(10), item.getCheckTime() == null ? "" : sdf.format(item.getCheckTime())); // æ£éªæ¥æ setText(dataRow.getCell(11), item.getWarehouseCode()); // å ¥åºç¼å· setText(dataRow.getCell(12), item.getEquipmentName()); // æå±è®¾å¤åç§° setText(dataRow.getCell(13), item.getProjectName()); // 项ç®åç§° setText(dataRow.getCell(14), item.getVerdict()); // å¤å® } // æ ¹æ®ææ¬åæ¢è¡è¡æ°ä¼°ç®è¡é« dataRow.setHeightInPoints(estimateRowHeight(dataRow, colCount)); } // å宽æå 容èªéåº autoSizeColumns(sheet, colCount, headerRowIndex, dataRows); // å宽确å®åååµå ¥ LOGO addLogoImage(workbook, sheet); // ---- 页é¢è®¾ç½®ï¼A4 ---- PrintSetup ps = sheet.getPrintSetup(); ps.setPaperSize(PrintSetup.A4_PAPERSIZE); ps.setLandscape(LANDSCAPE); sheet.setMargin(Sheet.TopMargin, 0.4); sheet.setMargin(Sheet.BottomMargin, 0.4); sheet.setMargin(Sheet.LeftMargin, 0.3); sheet.setMargin(Sheet.RightMargin, 0.3); sheet.setFitToPage(true); ps.setFitWidth((short) 1); ps.setFitHeight((short) 0); // ---- è¾åº ---- response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); String fileName = URLEncoder.encode(TITLE, "UTF-8"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); OutputStream os = response.getOutputStream(); workbook.write(os); os.flush(); } catch (Exception e) { throw new RuntimeException("导åºå¤±è´¥", e); } } /** å¨ A1:C2 åå¹¶åºåµå ¥å ¬å¸ LOGO å¾çï¼æåå æ ¼èªéåºãæ´ä½å± ä¸ */ private static void addLogoImage(XSSFWorkbook workbook, Sheet sheet) { byte[] bytes = loadLogoBytes(); if (bytes == null) { System.err.println("[ProcessInspectExport] LOGO å¾çæªæ¾å°ï¼å¯¼åºå°ä¸å¸¦ LOGOï¼èµæºè·¯å¾: " + LOGO_IMAGE_PATH + "ï¼"); return; } try { int pictureIdx = workbook.addPicture(bytes, XSSFWorkbook.PICTURE_TYPE_PNG); XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch(); // å¾çå®ä½ï¼A1:C2 åºåå float colAPx = sheet.getColumnWidthInPixels(0); float colBPx = sheet.getColumnWidthInPixels(1); float colCPx = sheet.getColumnWidthInPixels(2); float blockWidthPx = colAPx + colBPx + colCPx; float row0Px = sheet.getRow(0).getHeightInPoints() * 96f / 72f; float row1Px = sheet.getRow(1).getHeightInPoints() * 96f / 72f; float cellHPx = row0Px + row1Px; // 读åå¾ççå®å®½é« int imgW = 236; int imgH = 190; if (bytes.length > 24) { imgW = readInt(bytes, 16); imgH = readInt(bytes, 20); } // æåå æ ¼å¤§å°çæ¯ç¼©æ¾ï¼åå¨çç½ï¼ï¼æ´ä½å± ä¸ float availW = blockWidthPx - LOGO_PADDING_PX * 2; float availH = cellHPx - LOGO_PADDING_PX * 2; float scale = Math.min(availW / imgW, availH / imgH); float dispW = imgW * scale; float dispH = imgH * scale; float absLeft = LOGO_PADDING_PX + (availW - dispW) / 2f; float absTop = LOGO_PADDING_PX + (availH - dispH) / 2f; float absRight = absLeft + dispW; float absBottom = absTop + dispH; // è®¡ç® from/to éç¹ï¼ææåç§»éä¿æå¨æå¨å/è¡çåæ³èå´å int fromCol; int fromOffPx; if (absLeft <= colAPx) { fromCol = 0; fromOffPx = (int) absLeft; } else if (absLeft <= colAPx + colBPx) { fromCol = 1; fromOffPx = (int) (absLeft - colAPx); } else { fromCol = 2; fromOffPx = (int) (absLeft - colAPx - colBPx); } int toCol; int toOffPx; if (absRight <= colAPx) { toCol = 0; toOffPx = (int) absRight; } else if (absRight <= colAPx + colBPx) { toCol = 1; toOffPx = (int) (absRight - colAPx); } else { toCol = 2; toOffPx = (int) (absRight - colAPx - colBPx); } int fromRow = 0; float fromRowOff = absTop; if (absTop > row0Px) { fromRow = 1; fromRowOff = absTop - row0Px; } int toRow = 0; float toRowOff = absBottom; if (absBottom > row0Px) { toRow = 1; toRowOff = absBottom - row0Px; } XSSFClientAnchor anchor = new XSSFClientAnchor( fromOffPx * Units.EMU_PER_PIXEL, (int) (fromRowOff * Units.EMU_PER_PIXEL), toOffPx * Units.EMU_PER_PIXEL, (int) (toRowOff * Units.EMU_PER_PIXEL), fromCol, fromRow, toCol, toRow); anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); drawing.createPicture(anchor, pictureIdx); } catch (Exception e) { // LOGO å 载失败ä¸å½±å导åºï¼ä½æå°éè¯¯ä¾¿äºææ¥ System.err.println("[ProcessInspectExport] LOGO åµå ¥å¤±è´¥: " + e.getMessage()); } } /** 读å LOGOï¼æ¬å°å¼åä¼å 读ç»å¯¹è·¯å¾ï¼å ¶æ¬¡ classpathï¼æå项ç®ç¸å¯¹è·¯å¾ */ private static byte[] loadLogoBytes() { try (InputStream is = new java.io.FileInputStream(LOGO_ABS_PATH)) { return is.readAllBytes(); } catch (Exception ignored) { } try (InputStream is = ProcessInspectExportUtil.class.getResourceAsStream(LOGO_IMAGE_PATH)) { if (is != null) { return is.readAllBytes(); } } catch (Exception ignored) { } try (InputStream is = new java.io.FileInputStream("src/main/resources" + LOGO_IMAGE_PATH)) { return is.readAllBytes(); } catch (Exception e) { return null; } } /** æææ¬åå 容ä¸åå®½ä¼°ç®æ¢è¡åçè¡é«ï¼ç¹æ°ï¼ */ private static float estimateRowHeight(Row row, int colCount) { int maxLines = 1; for (int c = 1; c < colCount; c++) { boolean isTextColumn = c == 1 || c == 2 || c == 3 || c == 4 || c == 7 || c == 8 || c == 9 || c == 11 || c == 12 || c == 13; if (!isTextColumn) { continue; } Cell cell = row.getCell(c); String value = cell == null ? null : cell.getStringCellValue(); if (value == null || value.isEmpty()) { continue; } int lines = (int) Math.ceil(displayLen(value) / (COL_WIDTH_MAX * 2d)); maxLines = Math.max(maxLines, lines); } return Math.max(22f, maxLines * 15f + 6f); } /** å宽èªéåºï¼æè¡¨å¤´ä¸æ°æ®å å®¹è®¡ç®æ¯å宽度 */ private static void autoSizeColumns(Sheet sheet, int colCount, int headerRowIndex, int dataRows) { for (int c = 0; c < colCount; c++) { double maxLen = displayLen(HEADERS[c]); for (int r = 0; r < dataRows; r++) { Row row = sheet.getRow(headerRowIndex + 1 + r); Cell cell = row == null ? null : row.getCell(c); if (cell != null && cell.getCellType() == CellType.STRING) { maxLen = Math.max(maxLen, displayLen(cell.getStringCellValue())); } } double widthChars = Math.min(maxLen + COL_WIDTH_PADDING, COL_WIDTH_MAX + COL_WIDTH_PADDING); // 䏿æä¸¤ä¸ªåè§åç¬¦å®½åº¦è®¡ç® sheet.setColumnWidth(c, (int) (widthChars * 256)); } } /** è®¡ç®æ¾ç¤ºå®½åº¦ï¼ä¸æçå ¨è§å符æ 2 个åè§å®½åº¦è®¡ */ private static double displayLen(String s) { if (s == null) { return 0; } double len = 0; for (char ch : s.toCharArray()) { if ((ch >= 0x2E80 && ch <= 0x9FFF) || (ch >= 0x3000 && ch <= 0x303F) || ch >= 0xFF00) { len += 2; } else { len += 1; } } return len; } /** 读å PNG 头é¨ç宽/é«ï¼å¤§ç«¯æ´æ°ï¼ */ private static int readInt(byte[] b, int off) { return ((b[off] & 0xFF) << 24) | ((b[off + 1] & 0xFF) << 16) | ((b[off + 2] & 0xFF) << 8) | (b[off + 3] & 0xFF); } private static CellStyle createStyle(XSSFWorkbook workbook, boolean bold, float fontSize, HorizontalAlignment align) { CellStyle style = workbook.createCellStyle(); Font font = workbook.createFont(); font.setFontName("å®ä½"); font.setBold(bold); font.setFontHeightInPoints((short) fontSize); style.setFont(font); style.setAlignment(align); style.setVerticalAlignment(VerticalAlignment.CENTER); return style; } private static void addThinBorder(CellStyle style) { style.setBorderTop(BorderStyle.THIN); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); } private static void applyRegionBorder(Sheet sheet, CellRangeAddress region) { RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet); RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet); RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet); RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet); } private static void setText(Cell cell, String value) { cell.setCellValue(value == null ? "" : value); } private static String plain(BigDecimal value) { return value == null ? "" : value.toPlainString(); } } src/main/java/com/ruoyi/quality/utils/RawMaterialInspectExportUtil.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,372 @@ package com.ruoyi.quality.utils; import com.ruoyi.quality.pojo.QualityInspect; import jakarta.servlet.http.HttpServletResponse; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.PrintSetup; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.util.Units; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFDrawing; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.List; /** * åæææ£éªå¯¼åºï¼æçº¸è´¨åæ®æ ·å¼çæ Excelï¼ */ public class RawMaterialInspectExportUtil { // ==================== å¯å®å¶åºåï¼æ¹è¿éå³å¯è°æ´æ¨¡æ¿ï¼ ==================== /** LOGO å¾çä¸åå æ ¼è¾¹æ¡ä¹é´ççç½ï¼åç´ ï¼ */ private static final float LOGO_PADDING_PX = 6f; /** å·¦ä¸è§ LOGO å¾çï¼classpath è·¯å¾ï¼æ¾å¨ resources/static ä¸ï¼ */ private static final String LOGO_IMAGE_PATH = "/static/junge-logo.png"; /** æ¬å°å¼åç¯å¢ LOGO ç»å¯¹è·¯å¾ï¼ä¼å 读åï¼ */ private static final String LOGO_ABS_PATH = "D:/develop/XingRuan/product-inventory-management-junge/product-inventory-management/multiple/assets/logo/JunGeJiTuan-logo.png"; /** å± ä¸å¤§æ é¢ */ private static final String TITLE = "æ¥æä»¶å ¥åºæ£éªè®°å½"; /** åºå®æ°æ®è¡æ°ï¼æ°æ®ä¸è¶³è¡¥ç©ºè¡ï¼è¶ è¿èªå¨è¿½å ï¼ */ private static final int FIXED_ROW_COUNT = 14; /** 表头åï¼ä»å·¦å°å³ï¼ */ private static final String[] HEADERS = { "åºå·", "项ç®", "ç©æåç§°", "æ£éªä¾æ®", "æ°é", "æ½æ£æ°é", "æ£éªæ¥æ", "å¼å¸¸å¤æ³¨", "å¤å®" }; /** å宽èªéåºï¼æ¯åå¨å 容宽度åºç¡ä¸é¢å¤å ç宽度ï¼çº¦çäºä¸ä¸ªæ±åå®½åº¦ï¼ */ private static final int COL_WIDTH_PADDING = 2; /** ååæå¤§å®½åº¦ï¼çº¦çäºæ±å个æ°ï¼ï¼é²æ¢ä¸ªå«è¶ é¿å 容æåæå¾è¿å®½ */ private static final int COL_WIDTH_MAX = 40; /** æ£æ/æ é¢åå· */ private static final float BODY_FONT_SIZE = 12f; private static final float TITLE_FONT_SIZE = 16f; /** æ¯å¦æ¨ªåæå° */ private static final boolean LANDSCAPE = true; // ======================================================================== public static void export(HttpServletResponse response, List<QualityInspect> list) { try (XSSFWorkbook workbook = new XSSFWorkbook()) { Sheet sheet = workbook.createSheet(TITLE); int colCount = HEADERS.length; // æ ·å¼ CellStyle titleStyle = createStyle(workbook, true, TITLE_FONT_SIZE, HorizontalAlignment.CENTER); CellStyle labelStyle = createStyle(workbook, false, BODY_FONT_SIZE, HorizontalAlignment.LEFT); CellStyle headerStyle = createStyle(workbook, true, BODY_FONT_SIZE, HorizontalAlignment.CENTER); CellStyle centerStyle = createStyle(workbook, false, BODY_FONT_SIZE, HorizontalAlignment.CENTER); centerStyle.setWrapText(true); // æ°æ®åºæ ·å¼å è¾¹æ¡ addThinBorder(headerStyle); addThinBorder(centerStyle); // ---- 第1~2è¡ï¼é¡µç ---- Row row1 = sheet.createRow(0); Row row2 = sheet.createRow(1); row1.setHeightInPoints(36); row2.setHeightInPoints(16); // å·¦ä¸ï¼å ¬å¸ LOGO å¾çï¼A1:C2 åå¹¶åå æ ¼ï¼ CellRangeAddress logoRegion = new CellRangeAddress(0, 1, 0, 2); sheet.addMergedRegion(logoRegion); Cell logoCell = row1.createCell(0); logoCell.setCellStyle(createStyle(workbook, false, 12f, HorizontalAlignment.CENTER)); applyRegionBorder(sheet, logoRegion); // å± ä¸å¤§æ é¢ï¼D~Fï¼ Cell titleCell = row1.createCell(3); titleCell.setCellValue(TITLE); titleCell.setCellStyle(titleStyle); CellRangeAddress titleRegion = new CellRangeAddress(0, 1, 3, colCount - 4); sheet.addMergedRegion(titleRegion); applyRegionBorder(sheet, titleRegion); // å³ä¸ï¼æä»¶ç¼å· / 页æ°ï¼é å·¦ï¼ Cell fileNoCell = row1.createCell(colCount - 3); fileNoCell.setCellValue("æä»¶ç¼å·ï¼"); fileNoCell.setCellStyle(labelStyle); CellRangeAddress fileNoRegion = new CellRangeAddress(0, 0, colCount - 3, colCount - 1); sheet.addMergedRegion(fileNoRegion); applyRegionBorder(sheet, fileNoRegion); Cell pageCell = row2.createCell(colCount - 3); pageCell.setCellValue("é¡µæ° / No.ï¼"); pageCell.setCellStyle(labelStyle); CellRangeAddress pageRegion = new CellRangeAddress(1, 1, colCount - 3, colCount - 1); sheet.addMergedRegion(pageRegion); applyRegionBorder(sheet, pageRegion); // ---- 第3è¡ï¼è¡¨å¤´ ---- int headerRowIndex = 2; Row headerRow = sheet.createRow(headerRowIndex); headerRow.setHeightInPoints(24); for (int i = 0; i < colCount; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(HEADERS[i]); cell.setCellStyle(headerStyle); } // ---- æ°æ®è¡ï¼åºå®è¡æ°ï¼ä¸è¶³è¡¥ç©ºè¡ ---- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); int dataRows = Math.max(FIXED_ROW_COUNT, list.size()); for (int r = 0; r < dataRows; r++) { Row dataRow = sheet.createRow(headerRowIndex + 1 + r); for (int c = 0; c < colCount; c++) { Cell cell = dataRow.createCell(c); cell.setCellStyle(centerStyle); } // åºå·åºå®ç¼å· 1~N dataRow.getCell(0).setCellValue(r + 1); if (r < list.size()) { QualityInspect item = list.get(r); setText(dataRow.getCell(1), item.getProjectName()); // é¡¹ç® setText(dataRow.getCell(2), item.getProductName()); // ç©æåç§° setText(dataRow.getCell(3), item.getAcceptanceBasis()); // æ£éªä¾æ® setText(dataRow.getCell(4), plain(item.getQuantity())); // æ°é setText(dataRow.getCell(5), plain(item.getSamplingCount())); // æ½æ£æ°é setText(dataRow.getCell(6), item.getCheckTime() == null ? "" : sdf.format(item.getCheckTime())); // æ£éªæ¥æ setText(dataRow.getCell(7), item.getAbnormalRemark()); // å¼å¸¸å¤æ³¨ setText(dataRow.getCell(8), item.getVerdict()); // å¤å® } // æ ¹æ®ææ¬åæ¢è¡è¡æ°ä¼°ç®è¡é« dataRow.setHeightInPoints(estimateRowHeight(dataRow, colCount)); } // å宽æå 容èªéåº autoSizeColumns(sheet, colCount, headerRowIndex, dataRows); // å宽确å®åååµå ¥ LOGO addLogoImage(workbook, sheet); // ---- 页é¢è®¾ç½®ï¼A4 ---- PrintSetup ps = sheet.getPrintSetup(); ps.setPaperSize(PrintSetup.A4_PAPERSIZE); ps.setLandscape(LANDSCAPE); sheet.setMargin(Sheet.TopMargin, 0.4); sheet.setMargin(Sheet.BottomMargin, 0.4); sheet.setMargin(Sheet.LeftMargin, 0.3); sheet.setMargin(Sheet.RightMargin, 0.3); sheet.setFitToPage(true); ps.setFitWidth((short) 1); ps.setFitHeight((short) 0); // ---- è¾åº ---- response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); String fileName = URLEncoder.encode(TITLE, "UTF-8"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); OutputStream os = response.getOutputStream(); workbook.write(os); os.flush(); } catch (Exception e) { throw new RuntimeException("导åºå¤±è´¥", e); } } /** å¨ A1:C2 åå¹¶åºåµå ¥å ¬å¸ LOGO å¾çï¼æåå æ ¼èªéåºãæ´ä½å± ä¸ */ private static void addLogoImage(XSSFWorkbook workbook, Sheet sheet) { byte[] bytes = loadLogoBytes(); if (bytes == null) { System.err.println("[RawMaterialInspectExport] LOGO å¾çæªæ¾å°ï¼å¯¼åºå°ä¸å¸¦ LOGOï¼èµæºè·¯å¾: " + LOGO_IMAGE_PATH + "ï¼"); return; } try { int pictureIdx = workbook.addPicture(bytes, XSSFWorkbook.PICTURE_TYPE_PNG); XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch(); // å¾çå®ä½ï¼A1:C2 åºåå float colAPx = sheet.getColumnWidthInPixels(0); float colBPx = sheet.getColumnWidthInPixels(1); float colCPx = sheet.getColumnWidthInPixels(2); float blockWidthPx = colAPx + colBPx + colCPx; float row0Px = sheet.getRow(0).getHeightInPoints() * 96f / 72f; float row1Px = sheet.getRow(1).getHeightInPoints() * 96f / 72f; float cellHPx = row0Px + row1Px; // 读åå¾ççå®å®½é« int imgW = 236; int imgH = 190; if (bytes.length > 24) { imgW = readInt(bytes, 16); imgH = readInt(bytes, 20); } // æåå æ ¼å¤§å°çæ¯ç¼©æ¾ï¼åå¨çç½ï¼ï¼æ´ä½å± ä¸ float availW = blockWidthPx - LOGO_PADDING_PX * 2; float availH = cellHPx - LOGO_PADDING_PX * 2; float scale = Math.min(availW / imgW, availH / imgH); float dispW = imgW * scale; float dispH = imgH * scale; float absLeft = LOGO_PADDING_PX + (availW - dispW) / 2f; float absTop = LOGO_PADDING_PX + (availH - dispH) / 2f; float absRight = absLeft + dispW; float absBottom = absTop + dispH; // è®¡ç® from/to éç¹ï¼ææåç§»éä¿æå¨æå¨å/è¡çåæ³èå´å int fromCol; int fromOffPx; if (absLeft <= colAPx) { fromCol = 0; fromOffPx = (int) absLeft; } else if (absLeft <= colAPx + colBPx) { fromCol = 1; fromOffPx = (int) (absLeft - colAPx); } else { fromCol = 2; fromOffPx = (int) (absLeft - colAPx - colBPx); } int toCol; int toOffPx; if (absRight <= colAPx) { toCol = 0; toOffPx = (int) absRight; } else if (absRight <= colAPx + colBPx) { toCol = 1; toOffPx = (int) (absRight - colAPx); } else { toCol = 2; toOffPx = (int) (absRight - colAPx - colBPx); } int fromRow = 0; float fromRowOff = absTop; if (absTop > row0Px) { fromRow = 1; fromRowOff = absTop - row0Px; } int toRow = 0; float toRowOff = absBottom; if (absBottom > row0Px) { toRow = 1; toRowOff = absBottom - row0Px; } XSSFClientAnchor anchor = new XSSFClientAnchor( fromOffPx * Units.EMU_PER_PIXEL, (int) (fromRowOff * Units.EMU_PER_PIXEL), toOffPx * Units.EMU_PER_PIXEL, (int) (toRowOff * Units.EMU_PER_PIXEL), fromCol, fromRow, toCol, toRow); anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); drawing.createPicture(anchor, pictureIdx); } catch (Exception e) { // LOGO å 载失败ä¸å½±å导åºï¼ä½æå°éè¯¯ä¾¿äºææ¥ System.err.println("[RawMaterialInspectExport] LOGO åµå ¥å¤±è´¥: " + e.getMessage()); } } /** 读å LOGOï¼æ¬å°å¼åä¼å 读ç»å¯¹è·¯å¾ï¼å ¶æ¬¡ classpathï¼æå项ç®ç¸å¯¹è·¯å¾ */ private static byte[] loadLogoBytes() { try (InputStream is = new java.io.FileInputStream(LOGO_ABS_PATH)) { return is.readAllBytes(); } catch (Exception ignored) { } try (InputStream is = RawMaterialInspectExportUtil.class.getResourceAsStream(LOGO_IMAGE_PATH)) { if (is != null) { return is.readAllBytes(); } } catch (Exception ignored) { } try (InputStream is = new java.io.FileInputStream("src/main/resources" + LOGO_IMAGE_PATH)) { return is.readAllBytes(); } catch (Exception e) { return null; } } /** æææ¬åå 容ä¸åå®½ä¼°ç®æ¢è¡åçè¡é«ï¼ç¹æ°ï¼ */ private static float estimateRowHeight(Row row, int colCount) { int maxLines = 1; for (int c = 1; c < colCount; c++) { boolean isTextColumn = c == 1 || c == 2 || c == 3 || c == 7; if (!isTextColumn) { continue; } Cell cell = row.getCell(c); String value = cell == null ? null : cell.getStringCellValue(); if (value == null || value.isEmpty()) { continue; } int lines = (int) Math.ceil(displayLen(value) / (COL_WIDTH_MAX * 2d)); maxLines = Math.max(maxLines, lines); } return Math.max(22f, maxLines * 15f + 6f); } /** å宽èªéåºï¼æè¡¨å¤´ä¸æ°æ®å å®¹è®¡ç®æ¯å宽度 */ private static void autoSizeColumns(Sheet sheet, int colCount, int headerRowIndex, int dataRows) { for (int c = 0; c < colCount; c++) { double maxLen = displayLen(HEADERS[c]); for (int r = 0; r < dataRows; r++) { Row row = sheet.getRow(headerRowIndex + 1 + r); Cell cell = row == null ? null : row.getCell(c); if (cell != null && cell.getCellType() == CellType.STRING) { maxLen = Math.max(maxLen, displayLen(cell.getStringCellValue())); } } double widthChars = Math.min(maxLen + COL_WIDTH_PADDING, COL_WIDTH_MAX + COL_WIDTH_PADDING); // 䏿æä¸¤ä¸ªåè§åç¬¦å®½åº¦è®¡ç® sheet.setColumnWidth(c, (int) (widthChars * 256)); } } /** è®¡ç®æ¾ç¤ºå®½åº¦ï¼ä¸æçå ¨è§å符æ 2 个åè§å®½åº¦è®¡ */ private static double displayLen(String s) { if (s == null) { return 0; } double len = 0; for (char ch : s.toCharArray()) { if ((ch >= 0x2E80 && ch <= 0x9FFF) || (ch >= 0x3000 && ch <= 0x303F) || ch >= 0xFF00) { len += 2; } else { len += 1; } } return len; } /** 读å PNG 头é¨ç宽/é«ï¼å¤§ç«¯æ´æ°ï¼ */ private static int readInt(byte[] b, int off) { return ((b[off] & 0xFF) << 24) | ((b[off + 1] & 0xFF) << 16) | ((b[off + 2] & 0xFF) << 8) | (b[off + 3] & 0xFF); } private static CellStyle createStyle(XSSFWorkbook workbook, boolean bold, float fontSize, HorizontalAlignment align) { CellStyle style = workbook.createCellStyle(); Font font = workbook.createFont(); font.setFontName("å®ä½"); font.setBold(bold); font.setFontHeightInPoints((short) fontSize); style.setFont(font); style.setAlignment(align); style.setVerticalAlignment(VerticalAlignment.CENTER); return style; } private static void addThinBorder(CellStyle style) { style.setBorderTop(BorderStyle.THIN); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); } private static void applyRegionBorder(Sheet sheet, CellRangeAddress region) { RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet); RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet); RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet); RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet); } private static void setText(Cell cell, String value) { cell.setCellValue(value == null ? "" : value); } private static String plain(BigDecimal value) { return value == null ? "" : value.toPlainString(); } } src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -63,7 +63,7 @@ <if test="qualityInspect.salesContractNo != null and qualityInspect.salesContractNo != '' "> AND po_sales.sales_contract_no like concat('%',#{qualityInspect.salesContractNo},'%') </if> ORDER BY qi.check_time DESC ORDER BY qi.check_time ASC, qi.id ASC </select> <select id="qualityInspectExport" resultType="com.ruoyi.quality.pojo.QualityInspect"> src/main/resources/static/junge-logo.png