diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/poi/excel/handler/ExcelFillCellMergeStrategy.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/poi/excel/handler/ExcelFillCellMergeStrategy.java new file mode 100644 index 0000000000..6b08ca5e74 --- /dev/null +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/poi/excel/handler/ExcelFillCellMergeStrategy.java @@ -0,0 +1,114 @@ +package com.epmet.commons.tools.utils.poi.excel.handler; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +import java.util.List; + +/** + * desc:单元格合并策略 + * @author liujianjun + */ +public class ExcelFillCellMergeStrategy implements CellWriteHandler { + + private int[] mergeColumnIndex; + private int mergeRowIndex; + + public ExcelFillCellMergeStrategy() { + } + + public ExcelFillCellMergeStrategy(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) { + // 隐藏id列 + writeSheetHolder.getSheet().setColumnHidden(0, true); + } + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> list, Cell cell, Head head, Integer integer, Boolean aBoolean) { + int curRowIndex = cell.getRowIndex(); + int curColIndex = cell.getColumnIndex(); + int size = list.size(); + System.out.println(size); + if (mergeColumnIndex == null) { + if (curRowIndex > 2) { + mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); + } + }else{ + 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) { + //writeSheetHolder.getExcelWriteHeadProperty(). + // 当前行的第一个Cell + Cell curFirstCell = cell.getSheet().getRow(curRowIndex).getCell(0); + Object curFirstData = curFirstCell.getCellType() == CellType.STRING ? curFirstCell.getStringCellValue() : curFirstCell.getNumericCellValue(); + // 上一行的第一个Cell + Cell preFirstCell = cell.getSheet().getRow(curRowIndex - 1).getCell(0); + Object preFirstData = preFirstCell.getCellType() == CellType.STRING ? preFirstCell.getStringCellValue() : preFirstCell.getNumericCellValue(); + + if (curFirstData.equals(preFirstData)) { + Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); + Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); + Object preData = preCell.getCellType() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue(); + // 将当前单元格数据与上一个单元格数据比较 + Boolean dataBool = preData.equals(curData); + //此处需要注意:因为我是按照序号确定是否需要合并的,所以获取每一行第一列数据和上一行第一列数据进行比较,如果相等合并 + Boolean bool = cell.getRow().getCell(0).getStringCellValue().equals(cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue()); + if (dataBool && bool) { + 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); + } + } + } + } + +} diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/poi/excel/handler/ExcelMergeStrategy.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/poi/excel/handler/ExcelMergeStrategy.java new file mode 100644 index 0000000000..141c7de5d7 --- /dev/null +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/poi/excel/handler/ExcelMergeStrategy.java @@ -0,0 +1,213 @@ +package com.epmet.commons.tools.utils.poi.excel.handler; + +/** + * desc: + * + * @author: LiuJanJun + * @date: 2022/4/26 1:36 下午 + * @version: 1.0 + */ + +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.CellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +import java.util.List; +import java.util.Objects; +import java.util.stream.IntStream; + +/** + * 相同值合并策略 + */ + +public class ExcelMergeStrategy implements CellWriteHandler { + + /** + * 合并起始行 + */ + + private int mergeRowIndex; + /** + * 多少行合并一次 + */ + + private int eachRow; + + /** + * 合并字段的下标 + */ + + private int[] mergeColumnIndex; + + public ExcelMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex, int eachRow) { + + if (mergeRowIndex < 0) { + + throw new IllegalArgumentException("mergeRowIndex must be greater than 0"); + + } + + if (eachRow < 0) { + + throw new IllegalArgumentException("eachRow must be greater than 0"); + + } + + this.mergeRowIndex = mergeRowIndex; + + this.mergeColumnIndex = mergeColumnIndex; + + this.eachRow = eachRow; + + } + + @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 afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + + int curRowIndex = cell.getRowIndex(); + +//当前列 + + int curColIndex = cell.getColumnIndex(); + +//合并条件: + +//1.当前行>合并起始行,默认标题行(0)不参加合并 + +//2.间隔行(eachRow)的上下两条不参加合并 + +//2.1间隔行(eachRow)==0时,不设置间隔 + + if (isMerge(curRowIndex)) { + + IntStream.range(0, mergeColumnIndex.length).anyMatch(i -> { + + if (curColIndex == mergeColumnIndex[i]) { + + mergeWithPrevRow(writeSheetHolder, cellData, cell, curRowIndex, curColIndex); + + return true; + + } + + return false; + + }); + + } + + } + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + } + + /** + * 判断是否合并 + *

+ * 1.当前位置必须大于开始位置:curRowIndex > mergeRowIndex + *

+ * 2.根据eachRow 判断数据分割的间隔 + *

+ * 2.1如果根据eachRow=0,默认不合并 + *

+ * 2.2如果1如果根据eachRow>0,分割后的第一条数据不会与之前的合并:(curRowIndex-mergeRowIndex)%eachRow==0 + * + * @return + */ + + private boolean isMerge(Integer curRowIndex) { + if ((curRowIndex > mergeRowIndex) && eachRow > 0) { + + if ((curRowIndex - mergeRowIndex) % eachRow == 0) { + + return false; + + } + + return true; + + } + return false; + + } + + private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, int curRowIndex, int curColIndex) { + +//获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并 + + Object curData = cellData.getType() == CellDataTypeEnum.STRING ? cellData.getStringValue() : cellData.getNumberValue(); + + Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); + + Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : + + preCell.getNumericCellValue(); + +// 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行 + + if (Objects.equals(curData, preData)) { + + 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); + + } + + } + + } + +} + diff --git a/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/ConditionResultDTO.java b/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/ConditionResultDTO.java index fe2e7b03cb..4d0a000b8a 100644 --- a/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/ConditionResultDTO.java +++ b/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/ConditionResultDTO.java @@ -91,5 +91,10 @@ public class ConditionResultDTO implements Serializable { private String funType; private List options; + + /** + * 这个表 是否支持添加 即是否是多对一 eg:居民需求是多个对一个 + */ + private boolean supportAdd; } diff --git a/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcCustomExportResultDTO.java b/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcCustomExportResultDTO.java index 3b5ad1cdf2..31f09c2be0 100644 --- a/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcCustomExportResultDTO.java +++ b/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcCustomExportResultDTO.java @@ -1,8 +1,10 @@ package com.epmet.dto.result; +import com.epmet.commons.tools.constant.NumConstant; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.util.CollectionUtils; import java.io.Serializable; import java.util.ArrayList; @@ -26,6 +28,10 @@ public class IcCustomExportResultDTO implements Serializable { private List> headers = new ArrayList<>(); + + private Integer headerRow; + + /** * sql中要返回的 列名 顺序跟表头顺序一致 */ @@ -42,9 +48,22 @@ public class IcCustomExportResultDTO implements Serializable { public static class SqlColumn { private String itemId; private String tableName; + private Boolean manyToOne; private String columnName; private String optionSourceType; - private String optionSourceValue; } + /** + * desc:获取有几行头 + * @return + */ + public Integer getHeaderRow() { + if (CollectionUtils.isEmpty(headers)){ + return NumConstant.ZERO; + } + return headers.stream().mapToInt(List::size).max().orElse(0); + } + + + } diff --git a/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcExportTemplateForExportResultDTO.java b/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcExportTemplateForExportResultDTO.java index 3e00f6e072..d8ad9b8e5a 100644 --- a/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcExportTemplateForExportResultDTO.java +++ b/epmet-module/oper-customize/oper-customize-client/src/main/java/com/epmet/dto/result/IcExportTemplateForExportResultDTO.java @@ -57,6 +57,9 @@ public class IcExportTemplateForExportResultDTO implements Serializable { private String columnName; private String optionSourceValue; - private String optionSourceType; + /** + * 是否支持添加 即是否是多对一 eg:居民需求是多个对一个 + */ + private boolean supportAdd; } diff --git a/epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/service/impl/IcExportTemplateServiceImpl.java b/epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/service/impl/IcExportTemplateServiceImpl.java index 50fb337bcd..5bb93a162a 100644 --- a/epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/service/impl/IcExportTemplateServiceImpl.java +++ b/epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/service/impl/IcExportTemplateServiceImpl.java @@ -229,7 +229,7 @@ public class IcExportTemplateServiceImpl extends BaseServiceImpl> resultTemp, IcExportTemplateForExportResultDTO root, List> headerList, List showSqlColumns, List hiddenSqlColumns, Set hasExistColumnSet) { if (StringUtils.isNotBlank(root.getColumnName())) { - showSqlColumns.add(new IcCustomExportResultDTO.SqlColumn(root.getItemId(),root.getTableName(), root.getColumnName(),root.getOptionSourceType(),root.getOptionSourceValue())); + showSqlColumns.add(new IcCustomExportResultDTO.SqlColumn(root.getItemId(),root.getTableName(),root.isSupportAdd(), root.getColumnName(),root.getOptionSourceValue())); if (StringUtils.isNotBlank(root.getOptionSourceValue())&&root.getOptionSourceValue().contains(StrConstant.QUESTION_MARK)) { String[] paramArr = root.getOptionSourceValue().split(StrConstant.QUESTION_MARK_TRANSFER)[NumConstant.ONE].split(StrConstant.AND_MARK); //先remote中再添加 然后移除item中有的 diff --git a/epmet-module/oper-customize/oper-customize-server/src/main/resources/mapper/IcExportTemplateDao.xml b/epmet-module/oper-customize/oper-customize-server/src/main/resources/mapper/IcExportTemplateDao.xml index 29b847ff64..fb453591f5 100644 --- a/epmet-module/oper-customize/oper-customize-server/src/main/resources/mapper/IcExportTemplateDao.xml +++ b/epmet-module/oper-customize/oper-customize-server/src/main/resources/mapper/IcExportTemplateDao.xml @@ -20,8 +20,17 @@