package com.ruoyi.basic.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.enums.WriteDirectionEnum; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.fill.FillConfig; import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.production.dto.ExportProductionPrintOrderDto; import lombok.SneakyThrows; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; /** * @author buhuazhen * @date 2026/4/25 * @email 3038525872@qq.com */ @Component public class ProductionPrintOrderExcel { /** * 合并单元格并为合并区域添加左右边框 * * @param sheet Sheet * @param workbook Workbook * @param range 要合并的区域 */ public static void mergeWithBorder(Sheet sheet, Workbook workbook, CellRangeAddress range, CellStyle s) { // 1. 添加合并区域(检测是否重叠) for (int i = sheet.getNumMergedRegions() - 1; i >= 0; i--) { CellRangeAddress old = sheet.getMergedRegion(i); // 判断是否重叠(简单矩形重叠逻辑) if (!(range.getLastRow() < old.getFirstRow() || range.getFirstRow() > old.getLastRow() || range.getLastColumn() < old.getFirstColumn() || range.getFirstColumn() > old.getLastColumn())) { // 存在重叠 → 删除旧的 sheet.removeMergedRegion(i); } } sheet.addMergedRegion(range); // 2. 为合并区域内的所有单元格添加左右边框 for (int rowIdx = range.getFirstRow(); rowIdx <= range.getLastRow(); rowIdx++) { Row row = sheet.getRow(rowIdx); if (row == null) { row = sheet.createRow(rowIdx); } for (int colIdx = range.getFirstColumn(); colIdx <= range.getLastColumn(); colIdx++) { Cell cell = row.getCell(colIdx); if (cell == null) { cell = row.createCell(colIdx); } CellStyle style = workbook.createCellStyle(); // 若该单元格已有样式,复制 if (cell.getCellStyle() != null) { style.cloneStyleFrom(cell.getCellStyle()); } // 设置左右边框 style.setBorderLeft(s.getBorderLeft()); style.setBorderRight(s.getBorderRight()); style.setBorderTop(s.getBorderTop()); style.setBorderBottom(s.getBorderBottom()); style.setAlignment(s.getAlignment()); style.setVerticalAlignment(VerticalAlignment.CENTER); cell.setCellStyle(style); } } } @SneakyThrows public byte[] createPrintOrderTemplate(ExportProductionPrintOrderDto printOrderDto, InputStream templateInputStream) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try (ExcelWriter excelWriter = EasyExcel.write(byteArrayOutputStream) .withTemplate(templateInputStream) .build()) { FillConfig fillConfig = FillConfig.builder() .forceNewRow(true) .autoStyle(true) .direction(WriteDirectionEnum.VERTICAL) .build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); excelWriter.fill(printOrderDto, writeSheet); excelWriter.fill(new FillWrapper("materialInfo", printOrderDto.getMaterialInfo()), fillConfig, writeSheet); excelWriter.fill(new FillWrapper("processContent", printOrderDto.getProcessContent()), fillConfig, writeSheet); excelWriter.fill(new FillWrapper("plateMaking", printOrderDto.getPlateMaking()), fillConfig, writeSheet); excelWriter.finish(); } catch (Exception e) { throw new ServiceException("excel 生成失败! " + e.getMessage()); } ByteArrayOutputStream out = new ByteArrayOutputStream(); try { Workbook workbook = WorkbookFactory.create( new ByteArrayInputStream(byteArrayOutputStream.toByteArray()) ); CellStyle cellStyleTblr = workbook.createCellStyle(); cellStyleTblr.setBorderBottom(BorderStyle.THIN); cellStyleTblr.setBorderTop(BorderStyle.THIN); cellStyleTblr.setBorderLeft(BorderStyle.THIN); cellStyleTblr.setBorderRight(BorderStyle.THIN); cellStyleTblr.setWrapText(true); cellStyleTblr.setAlignment(HorizontalAlignment.CENTER); cellStyleTblr.setVerticalAlignment(VerticalAlignment.CENTER); Sheet sheet = workbook.getSheetAt(0); // ===== 插入图片 ===== if(printOrderDto.getCuttingImage() != null){ byte[] imageBytes = printOrderDto.getCuttingImage(); int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_JPEG); CreationHelper helper = workbook.getCreationHelper(); Drawing drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = helper.createClientAnchor(); anchor.setCol1(6); // 第7列(G列) anchor.setRow1(7); anchor.setDx1(142700); // 向右移动(约半格) anchor.setDy1(222700); anchor.setCol2(8); // 宽度终点 anchor.setRow2(9); // 高度终点 Picture picture = drawing.createPicture(anchor, pictureIdx); // picture.resize(0.5); } // 进行合并操作 切料示意图部分 int startRow = 7; int size = printOrderDto.getMaterialInfo().size(); int qlEndRow = startRow + size - 1 + 4; mergeWithBorder(sheet, workbook, new CellRangeAddress( startRow, qlEndRow, 6, 7 ), cellStyleTblr); // 产品备注 mergeWithBorder(sheet, workbook, new CellRangeAddress( 6+1+printOrderDto.getMaterialInfo().size() +0, 6+1+printOrderDto.getMaterialInfo().size() +1, 0, 5 ), cellStyleTblr); int zbRowStart = qlEndRow + 2 + CollUtil.size(printOrderDto.getPlateMaking()) +1; int zbRowEnd = zbRowStart + CollUtil.size(printOrderDto.getProcessContent()); mergeWithBorder(sheet, workbook, new CellRangeAddress( zbRowStart, zbRowEnd, 4, 7 ), cellStyleTblr); workbook.write(out); workbook.close(); } catch (Exception e) { throw new ServiceException("图片处理失败! " + e.getMessage()); } return out.toByteArray(); } }