|
@@ -0,0 +1,137 @@
|
|
|
+package cn.vber.common.excel.utils;
|
|
|
+
|
|
|
+import cn.idev.excel.metadata.Head;
|
|
|
+import cn.idev.excel.write.handler.SheetWriteHandler;
|
|
|
+import cn.idev.excel.write.handler.WorkbookWriteHandler;
|
|
|
+import cn.idev.excel.write.handler.context.WorkbookWriteHandlerContext;
|
|
|
+import cn.idev.excel.write.merge.AbstractMergeStrategy;
|
|
|
+import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
|
|
|
+import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.poi.ss.usermodel.*;
|
|
|
+import org.apache.poi.ss.util.CellRangeAddress;
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFColor;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+public class CkCoopMergeStrategy extends AbstractMergeStrategy implements WorkbookWriteHandler {
|
|
|
+
|
|
|
+ private final List<Integer> totalRows;
|
|
|
+ private final Map<Integer, List<Integer>> coopRows;
|
|
|
+ private final List<CellRangeAddress> cellList = new ArrayList<>();
|
|
|
+ private Integer cellNum;
|
|
|
+ private final AtomicBoolean merged = new AtomicBoolean(false);
|
|
|
+
|
|
|
+ public CkCoopMergeStrategy(List<Integer> totalRows, Map<Integer, List<Integer>> coopRows,String coopType) {
|
|
|
+ this.totalRows = totalRows;
|
|
|
+ this.coopRows = coopRows;
|
|
|
+ this.cellNum = coopType.equals("coop") ? 14 : 19;
|
|
|
+ // 预处理需要合并的区域
|
|
|
+ handleMergeRegions();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterWorkbookDispose(final WorkbookWriteHandlerContext context) {
|
|
|
+ // 使用原子操作确保合并只执行一次
|
|
|
+ Sheet sheet = context.getWriteContext().writeSheetHolder().getSheet();
|
|
|
+ if (merged.compareAndSet(false, true)) {
|
|
|
+ // 在表格创建完成后统一添加合并区域
|
|
|
+ if (!cellList.isEmpty()) {
|
|
|
+ for (CellRangeAddress item : cellList) {
|
|
|
+ try {
|
|
|
+ sheet.addMergedRegion(item);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("添加合并区域失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 设置指定行1-14列的背景色
|
|
|
+ *
|
|
|
+ * @param sheet Excel工作表
|
|
|
+ * @param rowIndex 行索引
|
|
|
+ * @param hexColor 十六进制颜色值
|
|
|
+ */
|
|
|
+ private void setRowBackgroundColor(Sheet sheet, int rowIndex,int cellNum, String hexColor) {
|
|
|
+ // 获取或创建行
|
|
|
+ Row row = sheet.getRow(rowIndex);
|
|
|
+ if (row == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建单元格样式
|
|
|
+ CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
|
|
|
+
|
|
|
+ // 设置背景色
|
|
|
+ if (hexColor != null && hexColor.startsWith("#")) {
|
|
|
+ byte[] rgb = new byte[3];
|
|
|
+ rgb[0] = (byte) Integer.parseInt(hexColor.substring(1, 3), 16); // Red
|
|
|
+ rgb[1] = (byte) Integer.parseInt(hexColor.substring(3, 5), 16); // Green
|
|
|
+ rgb[2] = (byte) Integer.parseInt(hexColor.substring(5, 7), 16); // Blue
|
|
|
+
|
|
|
+ XSSFColor xssfColor = new XSSFColor(rgb, null);
|
|
|
+ cellStyle.setFillForegroundColor(xssfColor);
|
|
|
+ } else {
|
|
|
+ // 默认颜色
|
|
|
+ cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
|
|
+ }
|
|
|
+
|
|
|
+ cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
|
|
+
|
|
|
+ // 为1-14列设置样式(对应索引0-13)
|
|
|
+ for (int i = 0; i < cellNum; i++) {
|
|
|
+ row.createCell(i).setCellStyle(cellStyle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 预处理需要合并的单元格区域
|
|
|
+ */
|
|
|
+ private void handleMergeRegions() {
|
|
|
+ cellList.clear();
|
|
|
+
|
|
|
+ if (totalRows != null && !totalRows.isEmpty()) {
|
|
|
+ for (Integer rowIndexObj : totalRows) {
|
|
|
+ if (rowIndexObj != null) {
|
|
|
+ int rowIndex = rowIndexObj;
|
|
|
+ // 添加到待合并列表中,而不是立即合并
|
|
|
+ cellList.add(new CellRangeAddress(rowIndex, rowIndex, 0, 2));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理coopRows的合并区域 (仅合并第一列)
|
|
|
+ if (coopRows != null && !coopRows.isEmpty()) {
|
|
|
+ for ( List<Integer> value : coopRows.values()) {
|
|
|
+ Integer startRow = value.get(0);
|
|
|
+ Integer endRow = value.get(1);
|
|
|
+
|
|
|
+ // 确保存在有效的合并范围(起始行小于结束行)
|
|
|
+ if (startRow < endRow) {
|
|
|
+ // 合并第一列(索引为0)从startRow到endRow
|
|
|
+ cellList.add(new CellRangeAddress(startRow, endRow, 0, 0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void merge(Sheet sheet, Cell cell, Head head, Integer integer) {
|
|
|
+// if (totalRows != null && !totalRows.isEmpty()) {
|
|
|
+// for (Integer rowIndexObj : totalRows) {
|
|
|
+// if (rowIndexObj != null) {
|
|
|
+// // 根据当前行,设置1-14列的背景色为指定的16进制值
|
|
|
+// setRowBackgroundColor(sheet, rowIndexObj, this.cellNum,"#5B9BD5");
|
|
|
+//
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+ }
|
|
|
+}
|