diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/serialize/GlobalSerializeMapping.java b/hutool-json/src/main/java/org/dromara/hutool/json/serialize/GlobalSerializeMapping.java
index 9ca81a3c3..91038bed3 100644
--- a/hutool-json/src/main/java/org/dromara/hutool/json/serialize/GlobalSerializeMapping.java
+++ b/hutool-json/src/main/java/org/dromara/hutool/json/serialize/GlobalSerializeMapping.java
@@ -97,7 +97,7 @@ public class GlobalSerializeMapping {
* @return 自定义的序列化器或者{@code null}
*/
public static JSONSerializer extends JSON, ?> getSerializer(final Type type) {
- if (null == serializerMap) {
+ if (null == serializerMap || null == type) {
return null;
}
return serializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
@@ -110,7 +110,7 @@ public class GlobalSerializeMapping {
* @return 自定义的反序列化器或者{@code null}
*/
public static JSONDeserializer> getDeserializer(final Type type) {
- if (null == deserializerMap) {
+ if (null == deserializerMap || null == type) {
return null;
}
return deserializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/SheetUtil.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/SheetUtil.java
index 153b91619..efe8e96b6 100644
--- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/SheetUtil.java
+++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/SheetUtil.java
@@ -141,4 +141,21 @@ public class SheetUtil {
throw new UnsupportedOperationException("Only XSSFSheet supports addIgnoredErrors");
}
}
+
+ /**
+ * 获取指定坐标点对应的合并单元格范围
+ *
+ * @param sheet {@link Sheet}
+ * @param x x坐标,即列号
+ * @param y 行号
+ * @return CellRangeAddress or null
+ */
+ public static CellRangeAddress getMergedRegion(final Sheet sheet, final int x, final int y) {
+ for (final CellRangeAddress ca : sheet.getMergedRegions()) {
+ if (ca.isInRange(y, x)) {
+ return ca;
+ }
+ }
+ return null;
+ }
}
diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/CellUtil.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/CellUtil.java
index feac78ff6..7463ee93b 100644
--- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/CellUtil.java
+++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/CellUtil.java
@@ -19,16 +19,15 @@ package org.dromara.hutool.poi.excel.cell;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.ss.util.RegionUtil;
-import org.apache.poi.ss.util.SheetUtil;
-import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.poi.excel.RowUtil;
+import org.dromara.hutool.poi.excel.SheetUtil;
import org.dromara.hutool.poi.excel.cell.editors.CellEditor;
import org.dromara.hutool.poi.excel.cell.editors.TrimEditor;
import org.dromara.hutool.poi.excel.cell.setters.CellSetter;
import org.dromara.hutool.poi.excel.cell.setters.CellSetterFactory;
import org.dromara.hutool.poi.excel.cell.values.CompositeCellValue;
import org.dromara.hutool.poi.excel.style.StyleSet;
+import org.dromara.hutool.poi.excel.style.StyleUtil;
/**
* Excel表格中单元格工具类
@@ -194,6 +193,18 @@ public class CellUtil {
// region ----- getCell
+ /**
+ * 获取或创建指定坐标单元格
+ *
+ * @param sheet {@link Sheet}
+ * @param x X坐标,从0计数,即列号
+ * @param y Y坐标,从0计数,即行号
+ * @return {@link Cell}
+ */
+ public static Cell getOrCreateCell(final Sheet sheet, final int x, final int y) {
+ return getCell(sheet, x, y, true);
+ }
+
/**
* 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回{@code null}
*
@@ -318,54 +329,33 @@ public class CellUtil {
* @return 合并后的单元格号
*/
public static int mergingCells(final Sheet sheet, final CellRangeAddress cellRangeAddress, final CellStyle cellStyle) {
- setMergeCellStyle(cellStyle, cellRangeAddress, sheet);
+ if (cellRangeAddress.getNumberOfCells() <= 1) {
+ // 非合并单元格,无需合并
+ return -1;
+ }
+ StyleUtil.setBorderStyle(sheet, cellRangeAddress, cellStyle);
return sheet.addMergedRegion(cellRangeAddress);
}
/**
- * 获取合并单元格的值
- * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
- *
- * @param sheet {@link Sheet}
- * @param locationRef 单元格地址标识符,例如A11,B5
- * @return 合并单元格的值
- * @since 5.1.5
- */
- public static Object getMergedRegionValue(final Sheet sheet, final String locationRef) {
- final CellReference cellReference = new CellReference(locationRef);
- return getMergedRegionValue(sheet, cellReference.getCol(), cellReference.getRow());
- }
-
- /**
- * 获取合并单元格的值
- * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
- *
- * @param sheet {@link Sheet}
- * @param x 列号,从0开始,可以是合并单元格范围中的任意一列
- * @param y 行号,从0开始,可以是合并单元格范围中的任意一行
- * @return 合并单元格的值
- * @since 4.6.3
- */
- public static Object getMergedRegionValue(final Sheet sheet, final int x, final int y) {
- // 合并单元格的识别在getCellValue已经集成,无需重复获取合并单元格
- return getCellValue(SheetUtil.getCell(sheet, x, y));
- }
-
- /**
- * 获取合并单元格
- * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
+ * 获取合并单元格中的第一个单元格
+ * 传入的cell可以是合并单元格范围内的任意一个单元格
*
* @param cell {@link Cell}
* @return 合并单元格
* @since 5.1.5
*/
- public static Cell getMergedRegionCell(final Cell cell) {
+ public static Cell getFirstCellOfMerged(final Cell cell) {
if (null == cell) {
return null;
}
- return ObjUtil.defaultIfNull(
- getCellIfMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()),
- cell);
+
+ final MergedCell mergedCell = getMergedCell(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex());
+ if (null != mergedCell) {
+ return mergedCell.getFirst();
+ }
+
+ return cell;
}
/**
@@ -378,10 +368,16 @@ public class CellUtil {
* @return 合并单元格,如果非合并单元格,返回坐标对应的单元格
* @since 5.1.5
*/
- public static Cell getMergedRegionCell(final Sheet sheet, final int x, final int y) {
- return ObjUtil.defaultIfNull(
- getCellIfMergedRegion(sheet, x, y),
- () -> SheetUtil.getCell(sheet, y, x));
+ public static MergedCell getMergedCell(final Sheet sheet, final int x, final int y) {
+ if (null == sheet) {
+ return null;
+ }
+
+ final CellRangeAddress mergedRegion = SheetUtil.getMergedRegion(sheet, x, y);
+ if (null != mergedRegion) {
+ return MergedCell.of(getCell(sheet, mergedRegion.getFirstColumn(), mergedRegion.getFirstRow(), false), mergedRegion);
+ }
+ return null;
}
// endregion
@@ -440,46 +436,4 @@ public class CellUtil {
cell.getRow().removeCell(cell);
}
}
-
- // -------------------------------------------------------------------------------------------------------------- Private method start
-
- /**
- * 获取合并单元格,非合并单元格返回{@code null}
- * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
- *
- * @param sheet {@link Sheet}
- * @param x 列号,从0开始,可以是合并单元格范围中的任意一列
- * @param y 行号,从0开始,可以是合并单元格范围中的任意一行
- * @return 合并单元格,如果非合并单元格,返回{@code null}
- * @since 5.4.5
- */
- private static Cell getCellIfMergedRegion(final Sheet sheet, final int x, final int y) {
- for (final CellRangeAddress ca : sheet.getMergedRegions()) {
- if (ca.isInRange(y, x)) {
- return SheetUtil.getCell(sheet, ca.getFirstRow(), ca.getFirstColumn());
- }
- }
- return null;
- }
-
- /**
- * 根据{@link CellStyle}设置合并单元格边框样式
- *
- * @param cellStyle {@link CellStyle}
- * @param cellRangeAddress {@link CellRangeAddress}
- * @param sheet {@link Sheet}
- */
- private static void setMergeCellStyle(final CellStyle cellStyle, final CellRangeAddress cellRangeAddress, final Sheet sheet) {
- if (null != cellStyle) {
- RegionUtil.setBorderTop(cellStyle.getBorderTop(), cellRangeAddress, sheet);
- RegionUtil.setBorderRight(cellStyle.getBorderRight(), cellRangeAddress, sheet);
- RegionUtil.setBorderBottom(cellStyle.getBorderBottom(), cellRangeAddress, sheet);
- RegionUtil.setBorderLeft(cellStyle.getBorderLeft(), cellRangeAddress, sheet);
- RegionUtil.setTopBorderColor(cellStyle.getTopBorderColor(), cellRangeAddress, sheet);
- RegionUtil.setRightBorderColor(cellStyle.getRightBorderColor(), cellRangeAddress, sheet);
- RegionUtil.setLeftBorderColor(cellStyle.getLeftBorderColor(), cellRangeAddress, sheet);
- RegionUtil.setBottomBorderColor(cellStyle.getBottomBorderColor(), cellRangeAddress, sheet);
- }
- }
- // -------------------------------------------------------------------------------------------------------------- Private method end
}
diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/MergedCell.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/MergedCell.java
new file mode 100644
index 000000000..940391504
--- /dev/null
+++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/MergedCell.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2024 Hutool Team and hutool.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.dromara.hutool.poi.excel.cell;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+/**
+ * 合并单元格封装
+ *
+ * @author Looly
+ * @since 6.0.0
+ */
+public class MergedCell {
+
+ /**
+ * 创建MergedCell
+ *
+ * @param cell 第一个单元格,即左上角的单元格
+ * @param rowCount 占用行数
+ * @param columnCount 占用列数
+ * @return MergedCell
+ */
+ public static MergedCell of(final Cell cell, final int rowCount, final int columnCount) {
+ final int rowIndex = cell.getRowIndex();
+ final int columnIndex = cell.getColumnIndex();
+ return of(cell, new CellRangeAddress(
+ rowIndex, rowIndex + rowCount - 1,
+ columnIndex, columnIndex + columnCount - 1));
+ }
+
+ /**
+ * 创建MergedCell
+ *
+ * @param cell 第一个单元格,即左上角的单元格
+ * @param range 合并单元格范围
+ * @return MergedCell
+ */
+ public static MergedCell of(final Cell cell, final CellRangeAddress range) {
+ return new MergedCell(cell, range);
+ }
+
+ private final Cell first;
+ private final CellRangeAddress range;
+
+ /**
+ * 构造
+ *
+ * @param first 第一个单元格,即左上角的单元格
+ * @param range 合并单元格范围
+ */
+ public MergedCell(final Cell first, final CellRangeAddress range) {
+ this.first = first;
+ this.range = range;
+ }
+
+ /**
+ * 获取第一个单元格,即左上角的单元格
+ *
+ * @return Cell
+ */
+ public Cell getFirst() {
+ return this.first;
+ }
+
+ /**
+ * 获取合并单元格范围
+ *
+ * @return CellRangeAddress
+ */
+ public CellRangeAddress getRange() {
+ return this.range;
+ }
+
+ /**
+ * 设置单元格样式
+ *
+ * @param cellStyle 单元格样式
+ * @return this
+ */
+ public MergedCell setCellStyle(final CellStyle cellStyle) {
+ this.first.setCellStyle(cellStyle);
+ return this;
+ }
+
+ /**
+ * 设置单元格值
+ *
+ * @param value 值
+ * @return this
+ */
+ public MergedCell setValue(final Object value) {
+ CellUtil.setCellValue(this.first, value);
+ return this;
+ }
+}
diff --git a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/values/CompositeCellValue.java b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/values/CompositeCellValue.java
index 4c967a615..3fe0fd961 100644
--- a/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/values/CompositeCellValue.java
+++ b/hutool-poi/src/main/java/org/dromara/hutool/poi/excel/cell/values/CompositeCellValue.java
@@ -77,7 +77,7 @@ public class CompositeCellValue implements CellValue