From ee5f977825e40fb746a4dd75344be296e610279c Mon Sep 17 00:00:00 2001 From: jing's Date: Wed, 6 Dec 2023 18:09:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bomnew/api/user/OptionalEbomApi.java | 96 +++- .../bomnew/constant/OptionalBomConstant.java | 2 +- .../product/bomnew/excel/EasyExcelUtil.java | 151 ++++++ .../bomnew/excel/ExcelExportField.java | 18 + .../bomnew/excel/ExportDeviceHelper.java | 415 ++++++++++----- .../excel/PreviewExcelExportHelper.java | 1 + .../PreviewProduceExcelExportHelper.java | 318 ++++++++++++ .../excel/PreviewTmpExcelExportHelper.java | 479 ++++++++++++++++++ .../pojo/dto/OptionalMbomCompareDTO.java | 3 +- .../query/OptionalEbomImportChildQuery.java | 8 +- .../master/OptionalEbomImportChildMapper.xml | 11 +- .../template/importDataTemplate.xlsx | Bin 0 -> 12939 bytes 12 files changed, 1371 insertions(+), 131 deletions(-) create mode 100644 nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/EasyExcelUtil.java create mode 100644 nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExcelExportField.java create mode 100644 nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewProduceExcelExportHelper.java create mode 100644 nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewTmpExcelExportHelper.java create mode 100644 nflg_project_dev/nflg-bom-new/src/main/resources/template/importDataTemplate.xlsx diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/OptionalEbomApi.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/OptionalEbomApi.java index a76d74d1..63b9adf4 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/OptionalEbomApi.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/api/user/OptionalEbomApi.java @@ -2,11 +2,17 @@ package com.nflg.product.bomnew.api.user; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.nflg.product.base.core.conmon.util.SessionUtil; import com.nflg.product.base.core.exception.NflgBusinessException; import com.nflg.product.bomnew.constant.OptionalBomConstant; +import com.nflg.product.bomnew.excel.EasyExcelUtil; +import com.nflg.product.bomnew.excel.ExportDeviceHelper; +import com.nflg.product.bomnew.excel.PreviewProduceExcelExportHelper; +import com.nflg.product.bomnew.excel.PreviewTmpExcelExportHelper; import com.nflg.product.bomnew.pojo.dto.*; import com.nflg.product.bomnew.pojo.query.OptionalEbomConfigListQuery; import com.nflg.product.bomnew.pojo.query.OptionalEbomImportChildQuery; @@ -28,9 +34,13 @@ import com.nflg.product.base.core.api.BaseApi; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.FileInputStream; import java.io.IOException; +import java.io.OutputStream; import java.util.Date; import java.util.List; +import java.util.Objects; /** * @@ -175,27 +185,27 @@ public class OptionalEbomApi extends BaseApi { if (dto == null) { return ResultVO.error("添加数据空"); } - if (dto.getPartType() != OptionalBomConstant.PartTypeEnum.PART_TYPE_RADIO.getValue() && dto.getPartType() != OptionalBomConstant.PartTypeEnum.PART_TYPE_CHECBOX.getValue()) { + + if ( !Objects.equals(dto.getPartType(), OptionalBomConstant.PartTypeEnum.PART_TYPE_RADIO.getValue()) && !Objects.equals(dto.getPartType() , OptionalBomConstant.PartTypeEnum.PART_TYPE_CHECBOX.getValue())) { return ResultVO.error("数据{partType}类型错误"); } if(dto.getRootRowId()==null ){ return ResultVO.error("rootRowId不能为空"); } - if(dto.getPartType() == OptionalBomConstant.PartTypeEnum.PART_TYPE_RADIO.getValue() &&( dto.getParentRowId()==null || dto.getParentRowId()==0)){ + if( Objects.equals(dto.getPartType() , OptionalBomConstant.PartTypeEnum.PART_TYPE_RADIO.getValue()) &&( dto.getParentRowId()==null )){ return ResultVO.error("标配件parentRowId不能为空"); } - if(dto.getPartType() == OptionalBomConstant.PartTypeEnum.PART_TYPE_CHECBOX.getValue()){ + if(Objects.equals(dto.getPartType() , OptionalBomConstant.PartTypeEnum.PART_TYPE_CHECBOX.getValue())){ dto.setParentRowId(null); } if(this.optionalEbomImportChildService.insertOption(dto)){ return ResultVO.success(true); }else{ - return ResultVO.error(STATE.Error,"添加失败"); + return ResultVO.error(STATE.Error,"添加配置失败"); } - } @@ -220,14 +230,6 @@ public class OptionalEbomApi extends BaseApi { - - - - - - - - @PostMapping("getTmpListPage") @ApiOperation("暂存方案分页数据") public ResultVO> getTmpListPage(@RequestBody OptionalEbomConfigListQuery query) { @@ -319,7 +321,75 @@ public class OptionalEbomApi extends BaseApi { } + @GetMapping("exportPreview") + @ApiOperation("预览导出") + public void exportPreview(HttpServletResponse response,@ApiParam("暂存id") @RequestParam("rowId") Long rowId) throws Exception { + OptionalEbomConfigTmpAggregVO voObj= aggregOptionConfigService.publishPreviewTree(rowId); + String fileName= StrUtil.format("{}预览导出{}",voObj.getDeviceInfo().getDeviceName(),System.currentTimeMillis()); + if(voObj!=null){ + EasyExcelUtil.setExportHeader(response,fileName); + PreviewTmpExcelExportHelper helper=new PreviewTmpExcelExportHelper(); + helper.export(response.getOutputStream(),voObj); + } + } + + @GetMapping("exportProducePreview") + @ApiOperation("生产预览导出") + public void exportProducePreview(HttpServletResponse response,@ApiParam("暂存id") @RequestParam("rowId") Long rowId) throws Exception { + OptionalEbomConfigTmpAggregVO voObj= aggregOptionConfigService.publishPreviewTree(rowId); + String fileName= StrUtil.format("{}生产预览导出{}",voObj.getDeviceInfo().getDeviceName(),System.currentTimeMillis()); + if(voObj!=null){ + EasyExcelUtil.setExportHeader(response,fileName); + PreviewProduceExcelExportHelper helper=new PreviewProduceExcelExportHelper(); + helper.export(response.getOutputStream(),voObj); + } + } + + @GetMapping("exportDeviceMaterial") + @ApiOperation("设备物料导出") + public void exportDeviceMaterial(HttpServletResponse response,@ApiParam("设备id") @RequestParam("rowId") Long rowId) throws Exception { + OptionalEbomImportChildQuery query=new OptionalEbomImportChildQuery(); + query.setRootRowId(rowId); + OptionalEbomConfigAggregVO voObj= aggregOptionConfigService.ebomEditTree(query); + String fileName= StrUtil.format("{}{}",voObj.getDeviceInfo().getDeviceNo(),voObj.getDeviceInfo().getDeviceName()); + if(voObj!=null){ + EasyExcelUtil.setExportHeader(response,fileName); + ExportDeviceHelper helper=new ExportDeviceHelper(); + OutputStream outputStream= response.getOutputStream(); + helper.export(outputStream,voObj); + outputStream.flush(); + + } + } + + + @GetMapping("downDeviceExcelTemplate") + @ApiOperation("导入数据模版下载") + public void downImportExcelTemplate(HttpServletResponse response ) throws Exception { + try { + //获取要下载的模板名称 + String fileName = "importDataTemplate.xlsx"; + EasyExcelUtil.setExportHeader(response,"移动破数据导入模版"); + //模板文件存放路径 + String filePath = getClass().getResource("/template/"+fileName).getPath(); + //IO流处理模板 + FileInputStream input = new FileInputStream(filePath); + OutputStream out = response.getOutputStream(); + byte[] b = new byte[2048]; + int len; + + while ((len = input.read(b)) != -1) { + out.write(b,0,len); + } + //返回请求访问的结果 + response.setHeader("Content-Length", String.valueOf(input.getChannel().size())); + input.close(); + } catch (Exception e) { + + } + + } diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java index c0c08b7d..085e2052 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java @@ -31,7 +31,7 @@ public class OptionalBomConstant { @AllArgsConstructor @Getter public enum SourceTypeEnum implements ValueEnum { - SOURCE_EXCEL(0, "excel"), + SOURCE_EXCEL(0, "template"), SOURCE_INPUT(1, "手动录入"); private final Integer value; private final String description; diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/EasyExcelUtil.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/EasyExcelUtil.java new file mode 100644 index 00000000..9765d82e --- /dev/null +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/EasyExcelUtil.java @@ -0,0 +1,151 @@ +package com.nflg.product.bomnew.excel; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.VerticalAlignment; + +import javax.servlet.http.HttpServletResponse; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.util.List; + +public class EasyExcelUtil { + + /** + * 默认头样式 + * + * @return WriteCellStyle + */ + public static WriteCellStyle getHeadStyle() { + // 头的策略 + WriteCellStyle headWriteCellStyle = new WriteCellStyle(); + + // 背景色, 设置为白色,也是默认颜色 + headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); + // 字体 + WriteFont headWriteFont = new WriteFont(); + //设置字体名字 + headWriteFont.setFontName("宋体"); + //设置字体大小 + headWriteFont.setFontHeightInPoints((short) 11); + //字体加粗 + headWriteFont.setBold(false); + //在样式用应用设置的字体; + headWriteCellStyle.setWriteFont(headWriteFont); + //设置底边框; + headWriteCellStyle.setBorderBottom(BorderStyle.THIN); + //设置底边框颜色; + headWriteCellStyle.setBottomBorderColor((short) 0); + //设置左边框; + headWriteCellStyle.setBorderLeft(BorderStyle.THIN); + //设置左边框颜色; + headWriteCellStyle.setLeftBorderColor((short) 0); + //设置右边框; + headWriteCellStyle.setBorderRight(BorderStyle.THIN); + //设置右边框颜色; + headWriteCellStyle.setRightBorderColor((short) 0); + //设置顶边框; + headWriteCellStyle.setBorderTop(BorderStyle.THIN); + //设置顶边框颜色; + headWriteCellStyle.setTopBorderColor((short) 0); + //设置自动换行; + headWriteCellStyle.setWrapped(false); + //设置水平对齐的样式为居中对齐; + headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + //设置垂直对齐的样式为居中对齐; + headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); + return headWriteCellStyle; + } + + + /** + * 默认行样式 + * + * @return WriteCellStyle + */ + public static WriteCellStyle getBodyStyle() { + WriteCellStyle bodyWriteCellStyle = new WriteCellStyle(); + //设置底边框; + bodyWriteCellStyle.setBorderBottom(BorderStyle.THIN); + //设置底边框颜色; + bodyWriteCellStyle.setBottomBorderColor((short) 0); + //设置左边框; + bodyWriteCellStyle.setBorderLeft(BorderStyle.THIN); + //设置左边框颜色; + bodyWriteCellStyle.setLeftBorderColor((short) 0); + //设置右边框; + bodyWriteCellStyle.setBorderRight(BorderStyle.THIN); + //设置右边框颜色; + bodyWriteCellStyle.setRightBorderColor((short) 0); + //设置顶边框; + bodyWriteCellStyle.setBorderTop(BorderStyle.THIN); + //设置顶边框颜色; + bodyWriteCellStyle.setTopBorderColor((short) 0); + // 字体 + WriteFont font = new WriteFont(); + //设置字体名字 + font.setFontName("宋体"); + //设置字体大小 + font.setFontHeightInPoints((short) 11); + //字体加粗 + font.setBold(false); + + bodyWriteCellStyle.setWriteFont(font); + //设置自动换行; + bodyWriteCellStyle.setWrapped(true); + //设置水平对齐的样式为居中对齐; + bodyWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + //设置垂直对齐的样式为居中对齐; + bodyWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); + return bodyWriteCellStyle; + } + + /** + * 获取头行默认样式 + * + * @return HorizontalCellStyleStrategy + */ + public static HorizontalCellStyleStrategy getDefaultStyle() { + return new HorizontalCellStyleStrategy(EasyExcelUtil.getHeadStyle(), EasyExcelUtil.getBodyStyle()); + } + + + public static void write(List> header, List data, OutputStream filePath, String sheetName, List handlers) { + + + ExcelWriter excelWriter = EasyExcel.write(filePath) + // 表头、内容样式设置 + .autoCloseStream(Boolean.FALSE) + .build(); + + ExcelWriterSheetBuilder excelWriterSheetBuilder = EasyExcel.writerSheet(0, sheetName).head(header); + for (CellWriteHandler handler : + handlers) { + excelWriterSheetBuilder.registerWriteHandler(handler); + } + excelWriter.write(data, excelWriterSheetBuilder.build()); + excelWriter.finish(); + } + + + + + + public static void setExportHeader(HttpServletResponse response, String fileName) throws Exception { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + } + + +} diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExcelExportField.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExcelExportField.java new file mode 100644 index 00000000..1ead2ac2 --- /dev/null +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExcelExportField.java @@ -0,0 +1,18 @@ +package com.nflg.product.bomnew.excel; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +@Data +public class ExcelExportField extends ImportExcelField { + + + + @ExcelProperty(value="",index = 3) + private String cellFourth; + + + + +} diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java index e5825cdf..794a43bb 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java @@ -1,11 +1,16 @@ package com.nflg.product.bomnew.excel; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.write.handler.AbstractCellWriteHandler; import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; @@ -13,154 +18,336 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; -import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; -import com.nflg.product.bomnew.pojo.vo.OptionalEbomConfigAggregVO; -import com.nflg.product.bomnew.pojo.vo.OptionalEbomImportChildVO; -import com.nflg.product.bomnew.pojo.vo.OptionalEbomImportVO; -import com.nflg.product.bomnew.pojo.vo.OptionalEbomMainVO; +import com.nflg.product.bomnew.pojo.vo.*; import org.apache.poi.ss.usermodel.*; import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Vector; +import java.io.OutputStream; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; + public class ExportDeviceHelper { - public void buildHeader(int maxColumn, OptionalEbomMainVO header, WriteSheet sheet, ExcelWriter writer, AtomicInteger tableNoCounting) { + public void export(OutputStream filePath, OptionalEbomConfigAggregVO voObj) { + + //使用一个计数器记录当前已经写了几个表格 + AtomicInteger tableNoCounting = new AtomicInteger(0); + ExcelWriter writer = EasyExcel.write(filePath)//指定写入的流 + .excelType(ExcelTypeEnum.XLSX)//指定Excel文件类型,如xlsx、xls + .autoCloseStream(Boolean.FALSE) + .build(); + + WriteSheet sheet = EasyExcel + .writerSheet("EBOM导出")//指定写入的sheet + .needHead(false)//是否需要head + .build(); + buildHeader(2, voObj.getDeviceInfo(), sheet, writer, tableNoCounting); + buildList(voObj.getSingleList(), sheet, writer, tableNoCounting); + writer.finish(); + + + } + + + public static class ColumnMergeStrategy implements CellWriteHandler { + + + private int[] mergeColumnIndex; + private int mergeRowIndex; + + public ColumnMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) { + this.mergeRowIndex = mergeRowIndex; + this.mergeColumnIndex = mergeColumnIndex; + } + + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { + + } + + @Override + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + + } + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + if (!isHead) { + //当前行 + int curRowIndex = cell.getRowIndex(); + //当前列 + int curColIndex = cell.getColumnIndex(); + // System.out.println(StrUtil.format("curRowIndex {} curColIndex {}",curRowIndex,curColIndex)); + if (curRowIndex > mergeRowIndex) { + for (int i = 0; i < mergeColumnIndex.length; i++) { + if (curColIndex == mergeColumnIndex[i]) { + mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); + break; + } + } + } + + } + } + + + /** + * 当前单元格向上合并 + * + * @param writeSheetHolder + * @param cell 当前单元格 + * @param curRowIndex 当前行 + * @param curColIndex 当前列 + */ + private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { + Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); + Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); + Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue(); + // 将当前单元格数据与上一个单元格数据比较 + Boolean dataBool = preData.equals(curData); + if (dataBool) { + Sheet sheet = writeSheetHolder.getSheet(); + List mergeRegions = sheet.getMergedRegions(); + boolean isMerged = false; + for (int i = 0; i < mergeRegions.size() && !isMerged; i++) { + CellRangeAddress cellRangeAddr = mergeRegions.get(i); + // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元 + if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) { + sheet.removeMergedRegion(i); + cellRangeAddr.setLastRow(curRowIndex); + sheet.addMergedRegion(cellRangeAddr); + isMerged = true; + } + } + // 若上一个单元格未被合并,则新增合并单元 + if (!isMerged) { + CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex); + sheet.addMergedRegion(cellRangeAddress); + } + } + } + } + + + public class HeaderStyleCustomCellWriteHandler extends AbstractCellWriteHandler { + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { + // 设置行高 + int rowIndex = row.getRowNum(); + short height = 400; + row.setHeight(height); + } + + private CellStyle initCellStyle(Workbook workbook) { + WriteCellStyle contentWriteCellStyle = EasyExcelUtil.getHeadStyle(); + CellStyle headWriteCellStyle = StyleUtil.buildCellStyle(workbook, null, contentWriteCellStyle); + return headWriteCellStyle; + } + + + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + Cell cell = context.getCell(); + int rowIndex = cell.getRowIndex(); + + int cellIndex = cell.getColumnIndex(); + + // 自定义宽度处理 + if (!context.getHead()) { + int columnWidth = cell.getStringCellValue().getBytes().length; + switch (cellIndex) { + case 0: + columnWidth = 30; + break; + case 1: + columnWidth = 40; + break; + case 2: + columnWidth = 80; + break; + default: + break; + } + + if (columnWidth > 255) { + columnWidth = 255; + } + context.getWriteSheetHolder().getSheet().setColumnWidth(cellIndex, columnWidth * 256); + } + // 自定义表头样式处理 + + if (context.getHead() != null && context.getHead().booleanValue()) { + WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); + Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); + CellStyle cellStyle = initCellStyle(workbook); + + XSSFCellStyle xssfCellStyle = (XSSFCellStyle) workbook.createCellStyle(); + xssfCellStyle.cloneStyleFrom(cellStyle); + xssfCellStyle.getFont().setBold(true); + + xssfCellStyle.setAlignment(HorizontalAlignment.LEFT); + xssfCellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 255, 0))); + xssfCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + cell.setCellStyle(xssfCellStyle); + context.getFirstCellData().setWriteCellStyle(null); //必须 + + + } + + if (context.getHead() == null || !context.getHead().booleanValue()) { + + if (cellIndex == 1 || cellIndex == 2) { + WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); + Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); + +// WriteCellStyle contentWriteCellStyle = EasyExcelUtil.getBodyStyle(); +// CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, null, contentWriteCellStyle); +// +// XSSFCellStyle xssfCellStyle = (XSSFCellStyle) workbook.createCellStyle(); +// xssfCellStyle.cloneStyleFrom(cellStyle); +// xssfCellStyle.setAlignment(HorizontalAlignment.LEFT); +// xssfCellStyle.setFont(new XSSFFont()); +// xssfCellStyle.getFont().setBold(false); +// xssfCellStyle.getFont().setFontName("宋体"); +// xssfCellStyle.getFont().setFontHeightInPoints((short) 11); +// +// context.getFirstCellData().setWriteCellStyle(null); //必须 +// cell.setCellStyle(xssfCellStyle); + + + WriteCellData writeCellData = context.getFirstCellData(); + WriteCellStyle customCellStyle = EasyExcelUtil.getBodyStyle(); + + WriteFont customFont = new WriteFont(); + customFont.setFontName("宋体"); + customFont.setFontHeightInPoints((short) 11); + customFont.setBold(false); + customCellStyle.setWriteFont(customFont); + customCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); + WriteCellStyle.merge(customCellStyle, writeCellData.getOrCreateStyle()); + + } + } + + + } + + } + + + public List> getHeader(String headStr) { + String customer = headStr; + List> list = new ArrayList>(); + List head0 = new ArrayList(); + head0.add(customer); + List head1 = new ArrayList(); + head1.add(customer); + List head2 = new ArrayList(); + head2.add(customer); + + + list.add(head0); + list.add(head1); + list.add(head2); + + return list; + } + + public void buildHeader(int maxColumn, OptionalEbomMainVO header, WriteSheet sheet, ExcelWriter writer, AtomicInteger tableNoCounting) { + if (header == null) { + return; + } + + + WriteCellStyle body = EasyExcelUtil.getBodyStyle(); + if (body.getWriteFont() != null) { + body.getWriteFont().setBold(true); + } - //自定义到处样式 - WriteCellStyle cellStyle = new WriteCellStyle(); - //水平居中 - cellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); - WriteFont writeFont = new WriteFont(); - //加粗 - writeFont.setBold(Boolean.TRUE); - //字体大小 - writeFont.setFontHeightInPoints((short) 14); - cellStyle.setWriteFont(writeFont); WriteTable table = EasyExcel .writerTable(tableNoCounting.get()) .needHead(Boolean.FALSE) -// .registerWriteHandler( -// new OnceAbsoluteMergeStrategy(tableNoCounting.get() - 1, tableNoCounting.getAndIncrement() - 1, 0, maxColumn) -// ) - .registerWriteHandler(new HorizontalCellStyleStrategy(cellStyle, cellStyle)) + .registerWriteHandler( + new OnceAbsoluteMergeStrategy(tableNoCounting.get(), tableNoCounting.get(), 0, maxColumn) + ) + .registerWriteHandler(new CellWriteHandler() { + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + Cell cell = context.getCell(); + int rowIndex = cell.getRowIndex(); + int cellIndex = cell.getColumnIndex(); + if (rowIndex == 0) { + short height = 500; + context.getRow().setHeight(height); + } + } + }) + .registerWriteHandler(new HorizontalCellStyleStrategy(EasyExcelUtil.getHeadStyle(), body)) .build(); - - List cellList = new ArrayList<>(); cellList.add(String.format("%s %s", header.getDeviceNo(), header.getDeviceName())); - List> rowList = new ArrayList<>(); rowList.add(cellList); //写入表格 writer.write(rowList, sheet, table); } + /** * 构建列表部分 */ - public void buildList( List listTable, WriteSheet sheet, ExcelWriter writer, AtomicInteger tableNoCounting) { - //自定义样式 - WriteCellStyle headStyle = new WriteCellStyle(); - //设置header背景颜色为透明 - // headStyle.setFillForegroundColor(IndexedColors.AUTOMATIC.getIndex()); - //水平居中 - headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); - //上下左右四个边框 - headStyle.setBorderBottom(BorderStyle.THIN); - headStyle.setBorderTop(BorderStyle.THIN); - headStyle.setBorderLeft(BorderStyle.THIN); - headStyle.setBorderRight(BorderStyle.THIN); - WriteFont writeFont = new WriteFont(); - //字体加粗 - writeFont.setBold(Boolean.TRUE); - //字号 - writeFont.setFontHeightInPoints((short) 12); - headStyle.setWriteFont(writeFont); - WriteCellStyle contentStyle = new WriteCellStyle(); - //内容上下左右四个边框 - contentStyle.setBorderBottom(BorderStyle.THIN); - contentStyle.setBorderTop(BorderStyle.THIN); - contentStyle.setBorderLeft(BorderStyle.THIN); - contentStyle.setBorderRight(BorderStyle.THIN); - //水平居中 - contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + public void buildList(List listTable, WriteSheet sheet, ExcelWriter writer, AtomicInteger tableNoCounting) { - List items=new Vector<>(); - int row=0; - for(OptionalEbomImportVO item1:listTable){ - String opParentName=item1.getOptionName(); - String optionParentDrawingNoName=item1.getOptionDrawingNo(); + if (CollectionUtil.isEmpty(listTable)) { + return; + } - List list2=item1.getChild(); - List cellList = new ArrayList<>(); - cellList.add( opParentName); + List items = new ArrayList<>(); + for (OptionalEbomImportVO item1 : listTable) { + String opParentName = item1.getOptionName(); + String optionParentDrawingNoName = item1.getOptionDrawingNo(); + List list2 = item1.getChild(); + List cellList = new ArrayList<>(); + cellList.add(opParentName); - List> rowList = new ArrayList<>(); - rowList.add(cellList); - WriteTable table0 = EasyExcel - .writerTable(tableNoCounting.getAndIncrement()) - .needHead(Boolean.FALSE) - .registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle)) - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) - // .head(rowList) - // .registerWriteHandler(new HorizontalCellStyleStrategy(cellStyle, cellStyle)) - // .registerWriteHandler(new PreviewExcelExportHelper.CellColorSheetWriteHandler()) -// .registerWriteHandler( -// new OnceAbsoluteMergeStrategy(tableNoCounting.get()-1, tableNoCounting.get(), 0, 2) -// ) + if (CollectionUtil.isNotEmpty(items)) { + tableNoCounting.getAndIncrement(); + WriteTable table = EasyExcel.writerTable(tableNoCounting.get()) + .head(getHeader(opParentName)) + .needHead(Boolean.TRUE)//需要Header + .registerWriteHandler(EasyExcelUtil.getDefaultStyle())//传入自定义样式 + .registerWriteHandler(new HeaderStyleCustomCellWriteHandler()) + .registerWriteHandler(new ColumnMergeStrategy(0, new int[]{0, 1})) .build(); - - writer.write(rowList, sheet, table0); - - - if(CollectionUtil.isNotEmpty(items)){ - WriteTable table = EasyExcel.writerTable(tableNoCounting.getAndIncrement()) - .needHead(Boolean.FALSE)//需要Header - // .head(rowList) - //添加自适应列宽策略 - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) - .registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle))//传入自定义样式 - - // .includeColumnFiledNames(fields)//选择需要哪些属性 - .build(); - writer.write(items, sheet, table); - } - + writer.write(items, sheet, table); items.clear(); - - for(OptionalEbomImportVO item2:list2){{ - String opChildName=item2.getOptionName(); - String optionChildDrawingNoName=item2.getOptionDrawingNo(); - List list3=item2.getChild(); - for(OptionalEbomImportChildVO item3:list3){ - ImportExcelField excelField=new ImportExcelField(); - excelField.setCellFirst(optionParentDrawingNoName); - excelField.setCellSecond(String.format("%s %s",optionChildDrawingNoName,opChildName)); - excelField.setCellThird(String.format("%s %s:(%s)",item3.getDrawingNo(),item3.getMaterialName(),item3.getChooseStatus()==1?"标配":"可选")); - items.add(excelField); - row++; - } - - } - - - } - } + for (OptionalEbomImportVO item2 : list2) { + { + String opChildName = item2.getOptionName(); + String optionChildDrawingNoName = item2.getOptionDrawingNo(); + List list3 = item2.getChild(); + for (OptionalEbomImportChildVO item3 : list3) { + ImportExcelField excelField = new ImportExcelField(); + excelField.setCellFirst(optionParentDrawingNoName); + excelField.setCellSecond(String.format("%s %s", optionChildDrawingNoName, opChildName)); + excelField.setCellThird(String.format("%s %s:(%s)", item3.getDrawingNo(), item3.getMaterialName(), item3.getChooseStatus() == 1 ? "标配" : "可选")); + items.add(excelField); + + } + } + } + } } - - } diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewExcelExportHelper.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewExcelExportHelper.java index bcc6ad5e..e280721b 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewExcelExportHelper.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewExcelExportHelper.java @@ -93,6 +93,7 @@ public class PreviewExcelExportHelper { rowList.clear(); writer.write(rowList, sheet, table); + } diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewProduceExcelExportHelper.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewProduceExcelExportHelper.java new file mode 100644 index 00000000..1e8a9d34 --- /dev/null +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewProduceExcelExportHelper.java @@ -0,0 +1,318 @@ +package com.nflg.product.bomnew.excel; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.write.handler.AbstractCellWriteHandler; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; +import com.alibaba.excel.write.merge.AbstractMergeStrategy; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.WriteTable; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import com.nflg.product.bomnew.constant.OptionalBomConstant; +import com.nflg.product.bomnew.pojo.vo.*; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; + +import javax.servlet.http.HttpServletResponse; +import java.io.OutputStream; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 生产导出 + */ +public class PreviewProduceExcelExportHelper { + + + public static class HeaderStyleCustomCellWriteHandler extends AbstractCellWriteHandler { + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { + // 设置行高 + int rowIndex = row.getRowNum(); + + short height = 600; + row.setHeight(height); + } + + private CellStyle initCellStyle(Workbook workbook) { + + + WriteCellStyle contentWriteCellStyle = EasyExcelUtil.getHeadStyle(); + CellStyle headWriteCellStyle = StyleUtil.buildCellStyle(workbook, null, contentWriteCellStyle); + return headWriteCellStyle; + } + + + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + Cell cell = context.getCell(); + int rowIndex = cell.getRowIndex(); + int cellIndex = cell.getColumnIndex(); + + // 自定义宽度处理 +// if (context.getHead() && cell.getRowIndex() == 0) { +// int columnWidth = cell.getStringCellValue().getBytes().length; +// switch (cellIndex) { +// case 0: +// case 2: +// case 3: +// case 1: +// columnWidth = 40; +// break; +// default: +// break; +// } +// +// if (columnWidth > 255) { +// columnWidth = 255; +// } +// context.getWriteSheetHolder().getSheet().setColumnWidth(cellIndex, columnWidth * 256); +// } + + // 自定义样式处理 + if (context.getHead()) { + WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); + Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); + CellStyle cellStyle = initCellStyle(workbook); + XSSFCellStyle xssfCellStyle = (XSSFCellStyle) workbook.createCellStyle(); + xssfCellStyle.cloneStyleFrom(cellStyle); + + xssfCellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 243, 202))); + xssfCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + + cell.setCellStyle(xssfCellStyle); + context.getFirstCellData().setWriteCellStyle(null); //必须 + } + } + + } + + public List> getHeader1() { + String customer = "选配"; + List> list = new ArrayList>(); + List head0 = new ArrayList(); + head0.add(customer); + List head1 = new ArrayList(); + head1.add(customer); + List head2 = new ArrayList(); + head2.add(customer); + List head3 = new ArrayList(); + head3.add(customer); + + list.add(head0); + list.add(head1); + list.add(head2); + list.add(head3); + return list; + } + + public List> getHeader0(OptionalEbomConfigVO main) { + /** + * 选配清单 + * |机型编号: 机型名称: + * | 合并单元格 空行 + * |机型名称|选项名称|物料编码|物料描述 + */ + String customer = StrUtil.format("{}选配清单", main.getDeviceName()); + List> list = new ArrayList>(); + List head0 = new ArrayList(); + head0.add(customer); + head0.add("机型编号:"); + head0.add(""); + head0.add("机型名称"); + head0.add("标配"); + + List head1 = new ArrayList(); + head1.add(customer); + head1.add(main.getDeviceNo()); + head1.add(""); + head1.add("选项名称"); + head1.add("标配"); + + List head2 = new ArrayList(); + head2.add(customer); + head2.add("机型名称:"); + head2.add(""); + head2.add("物料编码"); + head2.add("标配"); + + List head3 = new ArrayList(); + head3.add(customer); + head3.add(main.getDeviceName()); + head3.add(""); + head3.add("物料描述"); + head3.add("标配"); + list.add(head0); + list.add(head1); + list.add(head2); + list.add(head3); + return list; + } + + public void export(OutputStream filePath, OptionalEbomConfigTmpAggregVO voObj) { + + //使用一个计数器记录当前已经写了几个表格 + AtomicInteger tableNoCounting = new AtomicInteger(0); + ExcelWriter writer = EasyExcel.write(filePath)//指定写入的流,以及需要EasyExcel自带动态生成的类的类对象 + .excelType(ExcelTypeEnum.XLSX)//指定Excel文件类型,如xlsx、xls等 + .autoCloseStream(Boolean.FALSE) + .build(); + + WriteSheet sheet = EasyExcel + .writerSheet("生产预览导出")//指定写入的sheet + .needHead(false)//是否需要head,也就是每一个字段对应的字段名,这里不需要, 需要EasyExcel去生成字段名的地方只有列表数据部分 + .build(); + + buildList0(voObj, sheet, writer, tableNoCounting); + buildList1(voObj, sheet, writer, tableNoCounting); + writer.finish(); + } + + + public void buildList0(OptionalEbomConfigTmpAggregVO header, WriteSheet sheet, ExcelWriter writer, AtomicInteger tableNoCounting) { + + WriteTable table = EasyExcel + .writerTable(tableNoCounting.get()) + .head(getHeader0(header.getDeviceInfo())) + .needHead(Boolean.TRUE) + .registerWriteHandler(EasyExcelUtil.getDefaultStyle()) + // .registerWriteHandler(new PreviewTmpExcelExportHelper.MultiColumnMergeStrategy()) + .registerWriteHandler(new ExportDeviceHelper.ColumnMergeStrategy(0,new int[]{0}) ) + .registerWriteHandler(new PreviewTmpExcelExportHelper.HeaderStyleCustomCellWriteHandler()) //顶部表头样式通用 + .build(); + + List list = getStandList(header.getSingleList(), header.getMulList()); + writer.write(list, sheet, table); + + + } + + + public void buildList1(OptionalEbomConfigTmpAggregVO header, WriteSheet sheet, ExcelWriter writer, AtomicInteger tableNoCounting) { + tableNoCounting.getAndIncrement(); + List> tbHeader = getHeader1(); + WriteTable table = EasyExcel + .writerTable(tableNoCounting.get()) + .head(tbHeader) + .needHead(Boolean.TRUE) + .registerWriteHandler(EasyExcelUtil.getDefaultStyle()) + // .registerWriteHandler(new PreviewTmpExcelExportHelper.MultiColumnMergeStrategy()) + .registerWriteHandler(new ExportDeviceHelper.ColumnMergeStrategy(0,new int[]{0}) ) + .registerWriteHandler(new HeaderStyleCustomCellWriteHandler()) //单独处理表头样式 + .build(); + + List list = getNonList(header.getSingleList(), header.getMulList()); + writer.write(list, sheet, table); + + + } + + + public void download(HttpServletResponse response, OptionalEbomConfigTmpAggregVO voObj) throws Exception { + + String fileName = StrUtil.format("{}-{}-生产导出", voObj.getDeviceInfo().getDeviceName(), System.currentTimeMillis()); + + EasyExcelUtil.setExportHeader(response, fileName); +// List list = getList(voObj.getSingleList(), voObj.getMulList()); +// EasyExcel.write(response.getOutputStream()).head(getHeader(voObj.getDeviceInfo())) +// .autoCloseStream(Boolean.FALSE) +// .registerWriteHandler(new MultiColumnMergeStrategy()) +// .registerWriteHandler(EasyExcelUtil.getDefaultStyle()) +// .registerWriteHandler(new CustomCellWriteHandler()) +// // .registerWriteHandler(new CustomCellWriteHandler2()) +// .sheet("预览导出") +// .doWrite(list); + } + + + private List getNonList(List singleList, List mulList) { + List items = new ArrayList<>(); + for (OptionalEbomImportVO item1 : singleList) { + String opParentName = item1.getOptionName(); + String optionParentDrawingNoName = item1.getOptionDrawingNo(); + List list2 = item1.getChild(); + for (OptionalEbomImportVO item2 : list2) { + String opChildName = item2.getOptionName(); + String optionChildDrawingNoName = item2.getOptionDrawingNo(); + List list3 = item2.getChild(); + + if (CollectionUtil.isNotEmpty(list3)) { + for (OptionalEbomImportChildVO item3 : list3) { + if (Objects.equals(item3.getChooseStatus(), OptionalBomConstant.ChooseStatusEnum.CHOOSE_STATUS_NO.getValue())) { + ExcelExportField excelField = new ExcelExportField(); + excelField.setCellFirst(StrUtil.format("{}\n{}", opParentName, optionParentDrawingNoName)); + excelField.setCellSecond(StrUtil.format("{}\n{}", opChildName, optionChildDrawingNoName)); + excelField.setCellThird(StrUtil.format("{}", item3.getMaterialNo())); + excelField.setCellFourth(StrUtil.format("{}\n{}", item3.getMaterialName(), item3.getDrawingNo())); + items.add(excelField); + } + } + } + + } + + } + + if (CollectionUtil.isNotEmpty(mulList)) { + //添加配置 + for (OptionalEbomImportChildVO item1 : mulList) { + ExcelExportField excelField = new ExcelExportField(); + excelField.setCellFirst("附加配件"); + excelField.setCellSecond(StrUtil.format("{}\n{}", item1.getMaterialName(), item1.getMaterialNo())); + excelField.setCellThird(StrUtil.format("{}", item1.getMaterialNo())); + excelField.setCellFourth(item1.getMaterialDesc()); + items.add(excelField); + } + } + return items; + } + + private List getStandList(List singleList, List mulList) { + List items = new ArrayList<>(); + for (OptionalEbomImportVO item1 : singleList) { + String opParentName = item1.getOptionName(); + String optionParentDrawingNoName = item1.getOptionDrawingNo(); + List list2 = item1.getChild(); + for (OptionalEbomImportVO item2 : list2) { + String opChildName = item2.getOptionName(); + String optionChildDrawingNoName = item2.getOptionDrawingNo(); + List list3 = item2.getChild(); + + if (CollectionUtil.isNotEmpty(list3)) { + for (OptionalEbomImportChildVO item3 : list3) { + if (item3.getChooseStatus().equals(OptionalBomConstant.ChooseStatusEnum.CHOOSE_STATUS_YES.getValue())) { + ExcelExportField excelField = new ExcelExportField(); + excelField.setCellFirst(StrUtil.format("{}\n{}", opParentName, optionParentDrawingNoName)); + excelField.setCellSecond(StrUtil.format("{}\n{}", opChildName, optionChildDrawingNoName)); + excelField.setCellThird(StrUtil.format("{}", item3.getMaterialNo())); + excelField.setCellFourth(StrUtil.format("{}\n{}", item3.getMaterialName(), item3.getDrawingNo())); + items.add(excelField); + } + } + } + + } + + } + + return items; + } + + +} + + diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewTmpExcelExportHelper.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewTmpExcelExportHelper.java new file mode 100644 index 00000000..1e1a2cb9 --- /dev/null +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/PreviewTmpExcelExportHelper.java @@ -0,0 +1,479 @@ +package com.nflg.product.bomnew.excel; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.util.BooleanUtils; +import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.handler.AbstractCellWriteHandler; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.handler.WriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; +import com.alibaba.excel.write.merge.AbstractMergeStrategy; +import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.WriteTable; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.alibaba.fastjson.JSON; +import com.nflg.product.bomnew.pojo.vo.*; +import io.swagger.annotations.ApiModelProperty; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletResponse; +import java.io.OutputStream; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 预览导出 + */ +public class PreviewTmpExcelExportHelper { + + public static class HeaderStyleCustomCellWriteHandler extends AbstractCellWriteHandler { + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { + // 设置行高 + int rowIndex = row.getRowNum(); + // System.out.println("当前行: " + rowIndex); + short height = 600; + row.setHeight(height); + } + + private CellStyle initCellStyle(Workbook workbook) { + // CellStyle headWriteCellStyle = workbook.createCellStyle(); + +// //设置底边框; +// headWriteCellStyle.setBorderBottom(BorderStyle.THIN); +// //设置底边框颜色; +// headWriteCellStyle.setBottomBorderColor((short) 0); +// //设置左边框; +// headWriteCellStyle.setBorderLeft(BorderStyle.THIN); +// //设置左边框颜色; +// headWriteCellStyle.setLeftBorderColor((short) 0); +// //设置右边框; +// headWriteCellStyle.setBorderRight(BorderStyle.THIN); +// //设置右边框颜色; +// headWriteCellStyle.setRightBorderColor((short) 0); +// //设置顶边框; +// headWriteCellStyle.setBorderTop(BorderStyle.THIN); +// //设置顶边框颜色; +// headWriteCellStyle.setTopBorderColor((short) 0); +// +// //设置水平对齐的样式为居中对齐; +// headWriteCellStyle.setAlignment(HorizontalAlignment.CENTER); +// //设置垂直对齐的样式为居中对齐; +// headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); +// +// Font font = workbook.createFont(); +// font.setFontName("宋体"); // 字体样式 +// font.setBold(false); // 是否加粗 +// font.setFontHeightInPoints((short) 11); // 字体大小 +// headWriteCellStyle.setFont(font); + + + WriteCellStyle contentWriteCellStyle = EasyExcelUtil.getHeadStyle(); + CellStyle headWriteCellStyle = StyleUtil.buildCellStyle(workbook,null, contentWriteCellStyle); + return headWriteCellStyle; + } + + + + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + Cell cell = context.getCell(); + int rowIndex = cell.getRowIndex(); + int cellIndex = cell.getColumnIndex(); + + // 自定义宽度处理 + if (context.getHead() && cell.getRowIndex() == 1) { + int columnWidth = cell.getStringCellValue().getBytes().length; + switch (cellIndex) { + case 0: + case 2: + case 3: + case 1: + columnWidth = 40; + break; + default: + break; + } + + if (columnWidth > 255) { + columnWidth = 255; + } + context.getWriteSheetHolder().getSheet().setColumnWidth(cellIndex, columnWidth * 256); + } + // 自定义样式处理 + //单独处理表头样式 4行表头生产预览 + if (context.getHead() && (rowIndex == 4 || rowIndex==3 || rowIndex==1)) { + WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); + Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); + CellStyle cellStyle = initCellStyle(workbook); + + XSSFCellStyle xssfCellStyle = (XSSFCellStyle) workbook.createCellStyle(); + xssfCellStyle.cloneStyleFrom(cellStyle); + xssfCellStyle.getFont().setBold(false); + switch (rowIndex){ + case 1: + xssfCellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(217, 217, 217))); + xssfCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + if(cellIndex==0|| cellIndex==2){ + xssfCellStyle.setAlignment(HorizontalAlignment.RIGHT); + xssfCellStyle.getFont().setBold(true); + } + break; + case 3: + xssfCellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(227, 242, 217))); + xssfCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + break; + case 4: + xssfCellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(250, 218, 222))); + xssfCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + break; + + } + cell.setCellStyle(xssfCellStyle); + context.getFirstCellData().setWriteCellStyle(null); //必须 + } + + } + + } +// public class CustomCellWriteHandler implements CellWriteHandler { +// +// @Override +// public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { +// // 设置行高测试 +// int rowIndex = row.getRowNum(); +// System.out.println("当前行: " + rowIndex); +// short height = 600; +// row.setHeight(height); +// } +// +// @Override +// public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, +// List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { +// int rowIndex = cell.getRowIndex(); +// int cellIndex = cell.getColumnIndex(); +// +// +// // 自定义宽度处理 +// if (isHead && cell.getRowIndex() == 1) { +// int columnWidth = cell.getStringCellValue().getBytes().length; +// switch (cellIndex) { +// case 0: +// case 2: +// case 3: +// case 1: +// columnWidth = 40; +// break; +// default: +// break; +// } +// +// if (columnWidth > 255) { +// columnWidth = 255; +// } +// writeSheetHolder.getSheet().setColumnWidth(cellIndex, columnWidth * 256); +// +// +// } +// +// +// } +// +// +// } + + +// +// public class DetectionSheetWriteHandler implements SheetWriteHandler { +// +// private String dataTime; +// public DetectionSheetWriteHandler(){} +// +// @Override +// public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { +// +// } +// +// @Override +// public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { +// Workbook workbook = writeWorkbookHolder.getWorkbook(); +// Sheet sheet = workbook.getSheetAt(0); +// //设置第一行标题 +// Row row1 = sheet.createRow(1); +// row1.setHeight((short) 800); +// Cell row1Cell1 = row1.createCell(0); +// row1Cell1.setCellValue(" 统 计 表"); +// CellStyle row1CellStyle = workbook.createCellStyle(); +// row1CellStyle.setVerticalAlignment(VerticalAlignment.CENTER); +// row1CellStyle.setAlignment(HorizontalAlignment.CENTER); +// Font row1Font = workbook.createFont(); +// row1Font.setBold(true); +// row1Font.setFontName("宋体"); +// row1Font.setFontHeightInPoints((short) 18); +// row1CellStyle.setFont(row1Font); +// row1Cell1.setCellStyle(row1CellStyle); +// //合并单元格,起始行,结束行,起始列,结束列 +// sheet.addMergedRegionUnsafe(new CellRangeAddress(1, 1, 0, 5)); +//// sheet.addMergedRegionUnsafe(new CellRangeAddress(1, 1, 22, 23)); +// +//// 设置第二行标题 +// Row row2 = sheet.createRow(2); +// row2.setHeight((short) 400); +// Cell row2Cell1 = row2.createCell(0); +// row2Cell1.setCellValue("时间范围:"+ dataTime); +// CellStyle row2CellStyle = workbook.createCellStyle(); +// row2CellStyle.setVerticalAlignment(VerticalAlignment.CENTER); +// row2CellStyle.setAlignment(HorizontalAlignment.RIGHT); +// Font row2Font = workbook.createFont(); +// row2Font.setFontName("宋体"); +// row2Font.setFontHeightInPoints((short) 10); +// row2CellStyle.setFont(row2Font); +// row2Cell1.setCellStyle(row2CellStyle); +// sheet.addMergedRegionUnsafe(new CellRangeAddress(2, 2, 0, 5)); +// +// } +// } +// + + + public void export(OutputStream filePath, OptionalEbomConfigTmpAggregVO voObj) { + + List list = getList(voObj.getSingleList(), voObj.getMulList()); + + EasyExcel.write(filePath).head(getHeader(voObj.getDeviceInfo())) + .excelType(ExcelTypeEnum.XLSX) + .autoCloseStream(Boolean.FALSE) + // .registerWriteHandler(new MultiColumnMergeStrategy()) + .registerWriteHandler(new ExportDeviceHelper.ColumnMergeStrategy(0,new int[]{0}) ) + .registerWriteHandler(EasyExcelUtil.getDefaultStyle()) + .registerWriteHandler(new HeaderStyleCustomCellWriteHandler() ) + + .sheet("预览导出") + .doWrite(list); + + } + + + + public void download(HttpServletResponse response, OptionalEbomConfigTmpAggregVO voObj) throws Exception { + + String fileName=StrUtil.format("{}-{}-预览导出",voObj.getDeviceInfo().getDeviceName(),System.currentTimeMillis()); + + EasyExcelUtil.setExportHeader(response, fileName); + List list = getList(voObj.getSingleList(), voObj.getMulList()); + EasyExcel.write(response.getOutputStream()).head(getHeader(voObj.getDeviceInfo())) + .autoCloseStream(Boolean.FALSE) + .excelType(ExcelTypeEnum.XLSX) + + .registerWriteHandler(new ExportDeviceHelper.ColumnMergeStrategy(0,new int[]{0}) ) + .registerWriteHandler(EasyExcelUtil.getDefaultStyle()) + .registerWriteHandler(new HeaderStyleCustomCellWriteHandler() ) + + .sheet("预览导出") + .doWrite(list); + } + + + + + + + public static List> getHeader(OptionalEbomConfigVO main) { + /** + * 选配清单 + * |机型编号: 机型名称: + * | 合并单元格 空行 + * |机型名称|选项名称|物料编码|物料描述 + */ + String customer = StrUtil.format("{}选配清单", main.getDeviceName()); + List> list = new ArrayList>(); + List head0 = new ArrayList(); + head0.add(customer); + head0.add("机型编号:"); + head0.add(""); + head0.add("机型名称"); + + List head1 = new ArrayList(); + head1.add(customer); + head1.add(main.getDeviceNo()); + head1.add(""); + head1.add("选项名称"); + List head2 = new ArrayList(); + head2.add(customer); + head2.add("机型名称:"); + head2.add(""); + head2.add("物料编码"); + + List head3 = new ArrayList(); + head3.add(customer); + head3.add(main.getDeviceName()); + head3.add(""); + head3.add("物料描述"); + list.add(head0); + list.add(head1); + list.add(head2); + list.add(head3); + return list; + } + + + private List getList(List singleList, List mulList) { + List items = new ArrayList<>(); + for (OptionalEbomImportVO item1 : singleList) { + String opParentName = item1.getOptionName(); + String optionParentDrawingNoName = item1.getOptionDrawingNo(); + List list2 = item1.getChild(); + for (OptionalEbomImportVO item2 : list2) { + String opChildName = item2.getOptionName(); + String optionChildDrawingNoName = item2.getOptionDrawingNo(); + List list3 = item2.getChild(); + + + if (CollectionUtil.isNotEmpty(list3)) { + for (OptionalEbomImportChildVO item3 : list3) { + ExcelExportField excelField = new ExcelExportField(); + excelField.setCellFirst(StrUtil.format("{}\n{}", opParentName, optionParentDrawingNoName)); + excelField.setCellSecond(StrUtil.format("{}\n{}", opChildName, optionChildDrawingNoName)); + excelField.setCellThird(StrUtil.format("{}", item3.getMaterialNo())); + excelField.setCellFourth(StrUtil.format("{}\n{}", item3.getMaterialName(), item3.getDrawingNo())); + items.add(excelField); + } + } + + } + + } + + //添加配置 + for (OptionalEbomImportChildVO item1 : mulList) { + ExcelExportField excelField = new ExcelExportField(); + excelField.setCellFirst("附加配件"); + excelField.setCellSecond(StrUtil.format("{}\n{}", item1.getMaterialName(), item1.getMaterialNo())); + excelField.setCellThird(StrUtil.format("{}", item1.getMaterialNo())); + excelField.setCellFourth(item1.getMaterialDesc()); + items.add(excelField); + + } + + return items; + } + + +// public static class MultiColumnMergeStrategy extends AbstractMergeStrategy { +// +// +// private Map> nameRowMap = new HashMap<>(); +// +// @Override +// protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { +// int columnIndex = cell.getColumnIndex(); +// +// if (columnIndex == 0) { +// String currentValue = cell.getStringCellValue(); +// if (currentValue == null || currentValue.isEmpty()) { +// return; +// } +// +// int currentRowIndex = cell.getRowIndex(); +// List rowList = nameRowMap.getOrDefault(currentValue, new ArrayList<>()); +// rowList.add(currentRowIndex); +// nameRowMap.put(currentValue, rowList); +// +// mergeRows(sheet, currentValue, rowList, columnIndex); +// } +// +// if (columnIndex == 0) { +// String currentValue = cell.getStringCellValue(); +// if (currentValue == null || currentValue.isEmpty()) { +// return; +// } +// +// int currentRowIndex = cell.getRowIndex(); +// List rowList = nameRowMap.getOrDefault(currentValue, new ArrayList<>()); +// rowList.add(currentRowIndex); +// nameRowMap.put(currentValue, rowList); +// +// mergeRows(sheet, currentValue, rowList, columnIndex); +// } +// } +// +// private void mergeRows(Sheet sheet, String value, List rowList, int columnIndex) { +// if (rowList.size() <= 1) { +// return; +// } +// +// int startRow = rowList.get(0); +// int endRow = rowList.get(rowList.size() - 1); +// +// // 检查是否存在重叠合并区域 +// CellRangeAddress existingRegion = findOverlappingRegion(sheet, startRow, endRow, columnIndex); +// if (existingRegion != null) { +// // 扩展现有合并区域以适应新的合并行 +// startRow = Math.min(existingRegion.getFirstRow(), startRow); +// endRow = Math.max(existingRegion.getLastRow(), endRow); +// +// // 移除现有合并区域 +// removeMergedRegion(sheet, existingRegion); +// } +// +// if (startRow < endRow) { +// CellRangeAddress range = new CellRangeAddress(startRow, endRow, columnIndex, columnIndex); +// sheet.addMergedRegionUnsafe(range); +// } +// } +// +// private CellRangeAddress findOverlappingRegion(Sheet sheet, int startRow, int endRow, int columnIndex) { +// for (CellRangeAddress region : sheet.getMergedRegions()) { +// if (region.getFirstColumn() == columnIndex && region.getLastColumn() == columnIndex) { +// // 只考虑指定列的合并区域 +// if (startRow <= region.getLastRow() && endRow >= region.getFirstRow()) { +// return region; +// } +// } +// } +// return null; +// } +// +// private void removeMergedRegion(Sheet sheet, CellRangeAddress region) { +// int index = -1; +// for (int i = 0; i < sheet.getNumMergedRegions(); i++) { +// CellRangeAddress mergedRegion = sheet.getMergedRegion(i); +// if (mergedRegion.equals(region)) { +// index = i; +// break; +// } +// } +// if (index >= 0) { +// sheet.removeMergedRegion(index); +// } +// } +// +// +// } + + } + + diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/dto/OptionalMbomCompareDTO.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/dto/OptionalMbomCompareDTO.java index a3daeba5..b154eca8 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/dto/OptionalMbomCompareDTO.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/dto/OptionalMbomCompareDTO.java @@ -13,7 +13,8 @@ import java.time.LocalDateTime; import java.time.LocalDate; import java.util.Date; @Data -@ApiModel("用户选配比对是否相同") + +@ApiModel("com.nflg.product.bomnew.pojo.dto.OptionalMbomCompareDTO") @Accessors(chain = true) public class OptionalMbomCompareDTO implements Serializable { /**主键*/ @ApiModelProperty(value = "主键") diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/query/OptionalEbomImportChildQuery.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/query/OptionalEbomImportChildQuery.java index ce7b3295..bc22c613 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/query/OptionalEbomImportChildQuery.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/pojo/query/OptionalEbomImportChildQuery.java @@ -18,7 +18,7 @@ import java.time.LocalDate; import java.util.Date; @Data -@ApiModel("ebom选配件表") +@ApiModel("com.nflg.product.bomnew.pojo.queryebom.OptionalEbomImportChildQuery选配件表") @Accessors(chain = true) public class OptionalEbomImportChildQuery implements Serializable { @@ -49,4 +49,10 @@ public class OptionalEbomImportChildQuery implements Serializable { @ApiModelProperty(value = "结束时间") private String endTime; + + @ApiModelProperty(value = "0查询隐藏 1 查询显示 空全部") + private Integer enable; + + + } diff --git a/nflg_project_dev/nflg-bom-new/src/main/resources/mapper/master/OptionalEbomImportChildMapper.xml b/nflg_project_dev/nflg-bom-new/src/main/resources/mapper/master/OptionalEbomImportChildMapper.xml index fd791427..00c0e14e 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/resources/mapper/master/OptionalEbomImportChildMapper.xml +++ b/nflg_project_dev/nflg-bom-new/src/main/resources/mapper/master/OptionalEbomImportChildMapper.xml @@ -38,6 +38,12 @@ row_id,parent_row_id,root_row_id,material_no,material_name,material_desc,drawing from t_optional_ebom_import_child where root_row_id = #{query.rootRowId} + + + + and is_enable=${query.enable} + + and material_no like concat('%', '${query.materialNo}', '%') @@ -47,7 +53,10 @@ row_id,parent_row_id,root_row_id,material_no,material_name,material_desc,drawing and drawing_no like concat('%', '${query.drawingNo}', '%') - + + + + = #{query.startTime} and created_time < #{query.endTime}]]> diff --git a/nflg_project_dev/nflg-bom-new/src/main/resources/template/importDataTemplate.xlsx b/nflg_project_dev/nflg-bom-new/src/main/resources/template/importDataTemplate.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..20102e604c59c165240246ac19c706d77a82d11c GIT binary patch literal 12939 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 literal 0 HcmV?d00001