mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
b8991dbb76
commit
275092af2f
@ -97,7 +97,7 @@ public class GlobalSerializeMapping {
|
|||||||
* @return 自定义的序列化器或者{@code null}
|
* @return 自定义的序列化器或者{@code null}
|
||||||
*/
|
*/
|
||||||
public static JSONSerializer<? extends JSON, ?> getSerializer(final Type type) {
|
public static JSONSerializer<? extends JSON, ?> getSerializer(final Type type) {
|
||||||
if (null == serializerMap) {
|
if (null == serializerMap || null == type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return serializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
return serializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
||||||
@ -110,7 +110,7 @@ public class GlobalSerializeMapping {
|
|||||||
* @return 自定义的反序列化器或者{@code null}
|
* @return 自定义的反序列化器或者{@code null}
|
||||||
*/
|
*/
|
||||||
public static JSONDeserializer<?> getDeserializer(final Type type) {
|
public static JSONDeserializer<?> getDeserializer(final Type type) {
|
||||||
if (null == deserializerMap) {
|
if (null == deserializerMap || null == type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return deserializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
return deserializerMap.get(ObjUtil.defaultIfNull(type, NullType.INSTANCE));
|
||||||
|
@ -141,4 +141,21 @@ public class SheetUtil {
|
|||||||
throw new UnsupportedOperationException("Only XSSFSheet supports addIgnoredErrors");
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,16 +19,15 @@ package org.dromara.hutool.poi.excel.cell;
|
|||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
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.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.CellEditor;
|
||||||
import org.dromara.hutool.poi.excel.cell.editors.TrimEditor;
|
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.CellSetter;
|
||||||
import org.dromara.hutool.poi.excel.cell.setters.CellSetterFactory;
|
import org.dromara.hutool.poi.excel.cell.setters.CellSetterFactory;
|
||||||
import org.dromara.hutool.poi.excel.cell.values.CompositeCellValue;
|
import org.dromara.hutool.poi.excel.cell.values.CompositeCellValue;
|
||||||
import org.dromara.hutool.poi.excel.style.StyleSet;
|
import org.dromara.hutool.poi.excel.style.StyleSet;
|
||||||
|
import org.dromara.hutool.poi.excel.style.StyleUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel表格中单元格工具类
|
* Excel表格中单元格工具类
|
||||||
@ -194,6 +193,18 @@ public class CellUtil {
|
|||||||
|
|
||||||
// region ----- getCell
|
// 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}
|
* 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回{@code null}
|
||||||
*
|
*
|
||||||
@ -318,54 +329,33 @@ public class CellUtil {
|
|||||||
* @return 合并后的单元格号
|
* @return 合并后的单元格号
|
||||||
*/
|
*/
|
||||||
public static int mergingCells(final Sheet sheet, final CellRangeAddress cellRangeAddress, final CellStyle cellStyle) {
|
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);
|
return sheet.addMergedRegion(cellRangeAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取合并单元格的值<br>
|
* 获取合并单元格中的第一个单元格<br>
|
||||||
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
|
* 传入的cell可以是合并单元格范围内的任意一个单元格
|
||||||
*
|
|
||||||
* @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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取合并单元格的值<br>
|
|
||||||
* 传入的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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取合并单元格<br>
|
|
||||||
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
|
|
||||||
*
|
*
|
||||||
* @param cell {@link Cell}
|
* @param cell {@link Cell}
|
||||||
* @return 合并单元格
|
* @return 合并单元格
|
||||||
* @since 5.1.5
|
* @since 5.1.5
|
||||||
*/
|
*/
|
||||||
public static Cell getMergedRegionCell(final Cell cell) {
|
public static Cell getFirstCellOfMerged(final Cell cell) {
|
||||||
if (null == cell) {
|
if (null == cell) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ObjUtil.defaultIfNull(
|
|
||||||
getCellIfMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()),
|
final MergedCell mergedCell = getMergedCell(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex());
|
||||||
cell);
|
if (null != mergedCell) {
|
||||||
|
return mergedCell.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -378,10 +368,16 @@ public class CellUtil {
|
|||||||
* @return 合并单元格,如果非合并单元格,返回坐标对应的单元格
|
* @return 合并单元格,如果非合并单元格,返回坐标对应的单元格
|
||||||
* @since 5.1.5
|
* @since 5.1.5
|
||||||
*/
|
*/
|
||||||
public static Cell getMergedRegionCell(final Sheet sheet, final int x, final int y) {
|
public static MergedCell getMergedCell(final Sheet sheet, final int x, final int y) {
|
||||||
return ObjUtil.defaultIfNull(
|
if (null == sheet) {
|
||||||
getCellIfMergedRegion(sheet, x, y),
|
return null;
|
||||||
() -> SheetUtil.getCell(sheet, y, x));
|
}
|
||||||
|
|
||||||
|
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
|
// endregion
|
||||||
|
|
||||||
@ -440,46 +436,4 @@ public class CellUtil {
|
|||||||
cell.getRow().removeCell(cell);
|
cell.getRow().removeCell(cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------- Private method start
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取合并单元格,非合并单元格返回{@code null}<br>
|
|
||||||
* 传入的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
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -77,7 +77,7 @@ public class CompositeCellValue implements CellValue<Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 尝试获取合并单元格,如果是合并单元格,则重新获取单元格类型
|
// 尝试获取合并单元格,如果是合并单元格,则重新获取单元格类型
|
||||||
final Cell mergedCell = CellUtil.getMergedRegionCell(cell);
|
final Cell mergedCell = CellUtil.getFirstCellOfMerged(cell);
|
||||||
if (mergedCell != cell) {
|
if (mergedCell != cell) {
|
||||||
cell = mergedCell;
|
cell = mergedCell;
|
||||||
cellType = cell.getCellType();
|
cellType = cell.getCellType();
|
||||||
|
@ -32,6 +32,24 @@ import java.io.Serializable;
|
|||||||
public class CellBorderStyle implements Serializable {
|
public class CellBorderStyle implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据CellStyle创建单元格边框样式对象。
|
||||||
|
*
|
||||||
|
* @param cellStyle 单元格样式
|
||||||
|
* @return CellBorderStyle
|
||||||
|
*/
|
||||||
|
public static CellBorderStyle of(final CellStyle cellStyle) {
|
||||||
|
return new CellBorderStyle()
|
||||||
|
.setTopStyle(cellStyle.getBorderTop())
|
||||||
|
.setTopColor(cellStyle.getTopBorderColor())
|
||||||
|
.setRightStyle(cellStyle.getBorderRight())
|
||||||
|
.setRightColor(cellStyle.getRightBorderColor())
|
||||||
|
.setBottomStyle(cellStyle.getBorderBottom())
|
||||||
|
.setBottomColor(cellStyle.getBottomBorderColor())
|
||||||
|
.setLeftStyle(cellStyle.getBorderLeft())
|
||||||
|
.setLeftColor(cellStyle.getLeftBorderColor());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建单元格边框样式对象,四边框样式保持一致。
|
* 创建单元格边框样式对象,四边框样式保持一致。
|
||||||
*
|
*
|
||||||
|
@ -37,7 +37,7 @@ public interface StyleSet {
|
|||||||
*
|
*
|
||||||
* @param reference 单元格引用,包含单元格位置等信息
|
* @param reference 单元格引用,包含单元格位置等信息
|
||||||
* @param cellValue 单元格值
|
* @param cellValue 单元格值
|
||||||
* @param isHeader 是否为表头,扁头定义的特殊样式
|
* @param isHeader 是否为表头,表头定义的特殊样式
|
||||||
* @return 单元格样式
|
* @return 单元格样式
|
||||||
*/
|
*/
|
||||||
CellStyle getStyleFor(CellReference reference, Object cellValue, boolean isHeader);
|
CellStyle getStyleFor(CellReference reference, Object cellValue, boolean isHeader);
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
package org.dromara.hutool.poi.excel.style;
|
package org.dromara.hutool.poi.excel.style;
|
||||||
|
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
|
import org.apache.poi.ss.util.RegionUtil;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFColor;
|
import org.apache.poi.xssf.usermodel.XSSFColor;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
@ -156,6 +158,41 @@ public class StyleUtil {
|
|||||||
return cellBorderStyle.setTo(cellStyle);
|
return cellBorderStyle.setTo(cellStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据{@link CellStyle}设置指定范围边框样式
|
||||||
|
*
|
||||||
|
* @param sheet {@link Sheet}
|
||||||
|
* @param cellRangeAddress 边框样式范围
|
||||||
|
* @param cellBorderStyle 边框风格,包括边框样式、颜色
|
||||||
|
*/
|
||||||
|
public static void setBorderStyle(final Sheet sheet, final CellRangeAddress cellRangeAddress, final CellBorderStyle cellBorderStyle) {
|
||||||
|
if (null != cellBorderStyle) {
|
||||||
|
RegionUtil.setBorderTop(cellBorderStyle.getTopStyle(), cellRangeAddress, sheet);
|
||||||
|
RegionUtil.setBorderRight(cellBorderStyle.getRightStyle(), cellRangeAddress, sheet);
|
||||||
|
RegionUtil.setBorderBottom(cellBorderStyle.getBottomStyle(), cellRangeAddress, sheet);
|
||||||
|
RegionUtil.setBorderLeft(cellBorderStyle.getLeftStyle(), cellRangeAddress, sheet);
|
||||||
|
|
||||||
|
RegionUtil.setTopBorderColor(cellBorderStyle.getTopColor(), cellRangeAddress, sheet);
|
||||||
|
RegionUtil.setRightBorderColor(cellBorderStyle.getRightColor(), cellRangeAddress, sheet);
|
||||||
|
RegionUtil.setLeftBorderColor(cellBorderStyle.getLeftColor(), cellRangeAddress, sheet);
|
||||||
|
RegionUtil.setBottomBorderColor(cellBorderStyle.getBottomColor(), cellRangeAddress, sheet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据{@link CellStyle}设置指定范围边框样式
|
||||||
|
*
|
||||||
|
* @param sheet {@link Sheet}
|
||||||
|
* @param cellRangeAddress {@link CellRangeAddress}
|
||||||
|
* @param cellStyle {@link CellStyle}
|
||||||
|
*/
|
||||||
|
public static void setBorderStyle(final Sheet sheet, final CellRangeAddress cellRangeAddress, final CellStyle cellStyle) {
|
||||||
|
if (null != cellStyle) {
|
||||||
|
final CellBorderStyle cellBorderStyle = CellBorderStyle.of(cellStyle);
|
||||||
|
setBorderStyle(sheet, cellRangeAddress, cellBorderStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// region ----- color
|
// region ----- color
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +21,6 @@ import org.apache.poi.ss.util.CellRangeAddress;
|
|||||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
import org.dromara.hutool.core.collection.CollUtil;
|
|
||||||
import org.dromara.hutool.core.io.IORuntimeException;
|
import org.dromara.hutool.core.io.IORuntimeException;
|
||||||
import org.dromara.hutool.core.io.IoUtil;
|
import org.dromara.hutool.core.io.IoUtil;
|
||||||
import org.dromara.hutool.core.io.file.FileUtil;
|
import org.dromara.hutool.core.io.file.FileUtil;
|
||||||
@ -37,7 +36,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
@ -644,9 +642,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
|||||||
public ExcelWriter merge(final CellRangeAddress cellRangeAddress, final Object content, final CellStyle cellStyle) {
|
public ExcelWriter merge(final CellRangeAddress cellRangeAddress, final Object content, final CellStyle cellStyle) {
|
||||||
checkClosed();
|
checkClosed();
|
||||||
|
|
||||||
if(cellRangeAddress.getNumberOfCells() > 1){
|
|
||||||
CellUtil.mergingCells(this.getSheet(), cellRangeAddress, cellStyle);
|
CellUtil.mergingCells(this.getSheet(), cellRangeAddress, cellStyle);
|
||||||
}
|
|
||||||
|
|
||||||
// 设置内容
|
// 设置内容
|
||||||
if (null != content) {
|
if (null != content) {
|
||||||
@ -766,41 +762,9 @@ public class ExcelWriter extends ExcelBase<ExcelWriter, ExcelWriteConfig> {
|
|||||||
* @param rowGroup 分组行
|
* @param rowGroup 分组行
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("resource")
|
public ExcelWriter writeHeader(final int x, final int y, final int rowCount, final RowGroup rowGroup) {
|
||||||
public ExcelWriter writeHeader(int x, int y, int rowCount, final RowGroup rowGroup) {
|
checkClosed();
|
||||||
|
this.getSheetDataWriter().writeHeader(x, y, rowCount, rowGroup);
|
||||||
// 写主标题
|
|
||||||
final String name = rowGroup.getName();
|
|
||||||
final List<RowGroup> children = rowGroup.getChildren();
|
|
||||||
if (null != name) {
|
|
||||||
if(!CollUtil.isEmpty(children)){
|
|
||||||
// 有子节点,标题行只占用除子节点占用的行数
|
|
||||||
rowCount = Math.max(1, rowCount - rowGroup.childrenMaxRowCount());
|
|
||||||
//nameRowCount = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果无子节点,则标题行占用所有行
|
|
||||||
final CellRangeAddress cellAddresses = CellRangeUtil.of(y, y + rowCount - 1, x, x + rowGroup.maxColumnCount() - 1);
|
|
||||||
final CellStyle style = rowGroup.getStyle();
|
|
||||||
if(null == style){
|
|
||||||
merge(cellAddresses, name, true);
|
|
||||||
} else{
|
|
||||||
merge(cellAddresses, name, style);
|
|
||||||
}
|
|
||||||
// 子分组写到下N行
|
|
||||||
y += rowCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写分组
|
|
||||||
final int childrenMaxRowCount = rowGroup.childrenMaxRowCount();
|
|
||||||
if(childrenMaxRowCount > 0){
|
|
||||||
for (final RowGroup child : children) {
|
|
||||||
// 子分组行高填充为当前分组最大值
|
|
||||||
writeHeader(x, y, childrenMaxRowCount, child);
|
|
||||||
x += child.maxColumnCount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -18,20 +18,26 @@ package org.dromara.hutool.poi.excel.writer;
|
|||||||
|
|
||||||
import org.apache.poi.common.usermodel.Hyperlink;
|
import org.apache.poi.common.usermodel.Hyperlink;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.CellStyle;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.dromara.hutool.core.bean.BeanUtil;
|
import org.dromara.hutool.core.bean.BeanUtil;
|
||||||
|
import org.dromara.hutool.core.collection.CollUtil;
|
||||||
import org.dromara.hutool.core.collection.ListUtil;
|
import org.dromara.hutool.core.collection.ListUtil;
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
|
|
||||||
import org.dromara.hutool.core.map.multi.Table;
|
import org.dromara.hutool.core.map.multi.Table;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
import org.dromara.hutool.poi.excel.RowGroup;
|
||||||
import org.dromara.hutool.poi.excel.RowUtil;
|
import org.dromara.hutool.poi.excel.RowUtil;
|
||||||
|
import org.dromara.hutool.poi.excel.cell.CellRangeUtil;
|
||||||
import org.dromara.hutool.poi.excel.cell.CellUtil;
|
import org.dromara.hutool.poi.excel.cell.CellUtil;
|
||||||
import org.dromara.hutool.poi.excel.cell.editors.CellEditor;
|
import org.dromara.hutool.poi.excel.cell.editors.CellEditor;
|
||||||
import org.dromara.hutool.poi.excel.style.StyleSet;
|
import org.dromara.hutool.poi.excel.style.StyleSet;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@ -53,7 +59,7 @@ public class SheetDataWriter {
|
|||||||
* 标题项对应列号缓存,每次写标题更新此缓存<br>
|
* 标题项对应列号缓存,每次写标题更新此缓存<br>
|
||||||
* 此缓存用于用户多次write时,寻找标题位置
|
* 此缓存用于用户多次write时,寻找标题位置
|
||||||
*/
|
*/
|
||||||
private Map<String, Integer> headLocationCache;
|
private Map<String, Integer> headerLocationCache;
|
||||||
/**
|
/**
|
||||||
* 当前行,用于标记初始可写数据的行和部分写完后当前的行
|
* 当前行,用于标记初始可写数据的行和部分写完后当前的行
|
||||||
*/
|
*/
|
||||||
@ -75,6 +81,7 @@ public class SheetDataWriter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置样式表
|
* 设置样式表
|
||||||
|
*
|
||||||
* @param styleSet 样式表
|
* @param styleSet 样式表
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
@ -83,6 +90,67 @@ public class SheetDataWriter {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标题位置映射缓存
|
||||||
|
*
|
||||||
|
* @param headerLocationCache 标题位置映射缓存,key为表明名,value为列号
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public SheetDataWriter setHeaderLocationCache(final Map<String, Integer> headerLocationCache) {
|
||||||
|
this.headerLocationCache = headerLocationCache;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写出分组标题行
|
||||||
|
*
|
||||||
|
* @param x 开始的列,下标从0开始
|
||||||
|
* @param y 开始的行,下标从0开始
|
||||||
|
* @param rowCount 当前分组行所占行数,此数值为标题占用行数+子分组占用的最大行数,不确定传1
|
||||||
|
* @param rowGroup 分组行
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public SheetDataWriter writeHeader(int x, int y, int rowCount, final RowGroup rowGroup) {
|
||||||
|
|
||||||
|
// 写主标题
|
||||||
|
final String name = rowGroup.getName();
|
||||||
|
final List<RowGroup> children = rowGroup.getChildren();
|
||||||
|
if (null != name) {
|
||||||
|
if(CollUtil.isNotEmpty(children)){
|
||||||
|
// 有子节点,标题行只占用除子节点占用的行数
|
||||||
|
rowCount = Math.max(1, rowCount - rowGroup.childrenMaxRowCount());
|
||||||
|
//nameRowCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果无子节点,则标题行占用所有行
|
||||||
|
final CellRangeAddress cellRangeAddresses = CellRangeUtil.of(y, y + rowCount - 1, x, x + rowGroup.maxColumnCount() - 1);
|
||||||
|
CellStyle style = rowGroup.getStyle();
|
||||||
|
if (null == style && null != this.styleSet) {
|
||||||
|
style = styleSet.getStyleFor(new CellReference(cellRangeAddresses.getFirstRow(), cellRangeAddresses.getFirstColumn()), name, true);
|
||||||
|
}
|
||||||
|
CellUtil.mergingCells(this.sheet, cellRangeAddresses, style);
|
||||||
|
final Cell cell = CellUtil.getOrCreateCell(this.sheet, cellRangeAddresses.getFirstColumn(), cellRangeAddresses.getFirstRow());
|
||||||
|
if(null != cell){
|
||||||
|
CellUtil.setCellValue(cell, name, style, this.config.getCellEditor());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子分组写到下N行
|
||||||
|
y += rowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写分组
|
||||||
|
final int childrenMaxRowCount = rowGroup.childrenMaxRowCount();
|
||||||
|
if(childrenMaxRowCount > 0){
|
||||||
|
for (final RowGroup child : children) {
|
||||||
|
// 子分组行高填充为当前分组最大值
|
||||||
|
writeHeader(x, y, childrenMaxRowCount, child);
|
||||||
|
x += child.maxColumnCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写出一行,根据rowBean数据类型不同,写出情况如下:
|
* 写出一行,根据rowBean数据类型不同,写出情况如下:
|
||||||
*
|
*
|
||||||
@ -153,13 +221,13 @@ public class SheetDataWriter {
|
|||||||
// 记录原数据key和别名对应列号
|
// 记录原数据key和别名对应列号
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (final Object key : aliasTable.rowKeySet()) {
|
for (final Object key : aliasTable.rowKeySet()) {
|
||||||
this.headLocationCache.putIfAbsent(StrUtil.toString(key), i);
|
this.headerLocationCache.putIfAbsent(StrUtil.toString(key), i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果已经写出标题行,根据标题行找对应的值写入
|
// 如果已经写出标题行,根据标题行找对应的值写入
|
||||||
if (MapUtil.isNotEmpty(this.headLocationCache)) {
|
if (MapUtil.isNotEmpty(this.headerLocationCache)) {
|
||||||
final Row row = RowUtil.getOrCreateRow(this.sheet, this.currentRow.getAndIncrement());
|
final Row row = RowUtil.getOrCreateRow(this.sheet, this.currentRow.getAndIncrement());
|
||||||
final CellEditor cellEditor = this.config.getCellEditor();
|
final CellEditor cellEditor = this.config.getCellEditor();
|
||||||
Integer columnIndex;
|
Integer columnIndex;
|
||||||
@ -176,7 +244,7 @@ public class SheetDataWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写出一行标题数据<br>
|
* 写出一行标题数据,标题数据不替换别名<br>
|
||||||
* 本方法只是将数据写入Workbook中的Sheet,并不写出到文件<br>
|
* 本方法只是将数据写入Workbook中的Sheet,并不写出到文件<br>
|
||||||
* 写出的起始行为当前行号,可使用{@link #getCurrentRow()}方法调用,根据写出的的行数,当前行号自动+1
|
* 写出的起始行为当前行号,可使用{@link #getCurrentRow()}方法调用,根据写出的的行数,当前行号自动+1
|
||||||
*
|
*
|
||||||
@ -184,21 +252,20 @@ public class SheetDataWriter {
|
|||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public SheetDataWriter writeHeaderRow(final Iterable<?> rowData) {
|
public SheetDataWriter writeHeaderRow(final Iterable<?> rowData) {
|
||||||
this.headLocationCache = new SafeConcurrentHashMap<>();
|
|
||||||
|
|
||||||
final int rowNum = this.currentRow.getAndIncrement();
|
final int rowNum = this.currentRow.getAndIncrement();
|
||||||
final Row row = this.config.insertRow ? this.sheet.createRow(rowNum) : RowUtil.getOrCreateRow(this.sheet, rowNum);
|
final Row row = this.config.insertRow ? this.sheet.createRow(rowNum) : RowUtil.getOrCreateRow(this.sheet, rowNum);
|
||||||
|
|
||||||
|
final Map<String, Integer> headerLocationCache = new LinkedHashMap<>();
|
||||||
final CellEditor cellEditor = this.config.getCellEditor();
|
final CellEditor cellEditor = this.config.getCellEditor();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Cell cell;
|
Cell cell;
|
||||||
for (final Object value : rowData) {
|
for (final Object value : rowData) {
|
||||||
cell = CellUtil.getOrCreateCell(row, i);
|
cell = CellUtil.getOrCreateCell(row, i);
|
||||||
CellUtil.setCellValue(cell, value, this.styleSet, true, cellEditor);
|
CellUtil.setCellValue(cell, value, this.styleSet, true, cellEditor);
|
||||||
this.headLocationCache.put(StrUtil.toString(value), i);
|
headerLocationCache.put(StrUtil.toString(value), i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return this;
|
return setHeaderLocationCache(headerLocationCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,6 +284,7 @@ public class SheetDataWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- currentRow ops
|
// region ----- currentRow ops
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得当前行
|
* 获得当前行
|
||||||
*
|
*
|
||||||
@ -275,10 +343,10 @@ public class SheetDataWriter {
|
|||||||
*/
|
*/
|
||||||
private Integer getColumnIndex(final Table.Cell<?, ?, ?> cell) {
|
private Integer getColumnIndex(final Table.Cell<?, ?, ?> cell) {
|
||||||
// 首先查找原名对应的列号
|
// 首先查找原名对应的列号
|
||||||
Integer location = this.headLocationCache.get(StrUtil.toString(cell.getRowKey()));
|
Integer location = this.headerLocationCache.get(StrUtil.toString(cell.getRowKey()));
|
||||||
if (null == location) {
|
if (null == location) {
|
||||||
// 未找到,则查找别名对应的列号
|
// 未找到,则查找别名对应的列号
|
||||||
location = this.headLocationCache.get(StrUtil.toString(cell.getColumnKey()));
|
location = this.headerLocationCache.get(StrUtil.toString(cell.getColumnKey()));
|
||||||
}
|
}
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,17 @@ public class ExcelWriteTest {
|
|||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void mergeNotExistCellTest(){
|
||||||
|
final ExcelWriter writer = ExcelUtil.getWriter()
|
||||||
|
.merge(5);
|
||||||
|
|
||||||
|
writer
|
||||||
|
.flush(FileUtil.file("d:/test/mergeNotExist.xlsx"), true)
|
||||||
|
.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
public void mergeTest2() {
|
public void mergeTest2() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user