This commit is contained in:
Looly 2024-06-03 12:23:47 +08:00
parent 35f3383a1c
commit 6b4c3b1e4d
13 changed files with 272 additions and 298 deletions

View File

@ -12,20 +12,20 @@
package org.dromara.hutool.poi.excel;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dromara.hutool.core.data.id.IdUtil;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.net.url.UrlEncoder;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.poi.excel.cell.CellLocation;
import org.dromara.hutool.poi.excel.cell.CellUtil;
import org.dromara.hutool.poi.excel.style.StyleUtil;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.Closeable;
import java.io.File;
@ -229,8 +229,8 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
* @since 5.1.4
*/
public Cell getCell(final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return getCell(cellLocation.getX(), cellLocation.getY());
final CellReference cellReference = new CellReference(locationRef);
return getCell(cellReference.getCol(), cellReference.getRow());
}
/**
@ -253,8 +253,8 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
* @since 5.1.4
*/
public Cell getOrCreateCell(final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return getOrCreateCell(cellLocation.getX(), cellLocation.getY());
final CellReference cellReference = new CellReference(locationRef);
return getOrCreateCell(cellReference.getCol(), cellReference.getRow());
}
/**
@ -278,8 +278,8 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
* @since 5.1.4
*/
public Cell getCell(final String locationRef, final boolean isCreateIfNotExist) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return getCell(cellLocation.getX(), cellLocation.getY(), isCreateIfNotExist);
final CellReference cellReference = new CellReference(locationRef);
return getCell(cellReference.getCol(), cellReference.getRow(), isCreateIfNotExist);
}
/**
@ -319,8 +319,8 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
* @since 5.1.4
*/
public CellStyle getOrCreateCellStyle(final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return getOrCreateCellStyle(cellLocation.getX(), cellLocation.getY());
final CellReference cellReference = new CellReference(locationRef);
return getOrCreateCellStyle(cellReference.getCol(), cellReference.getRow());
}
/**
@ -344,8 +344,8 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
* @since 5.1.4
*/
public CellStyle createCellStyle(final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return createCellStyle(cellLocation.getX(), cellLocation.getY());
final CellReference cellReference = new CellReference(locationRef);
return createCellStyle(cellReference.getCol(), cellReference.getRow());
}
/**

View File

@ -17,8 +17,6 @@ import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.poi.PoiChecker;
import org.dromara.hutool.poi.excel.cell.CellLocation;
import org.dromara.hutool.poi.excel.cell.CellLocationUtil;
import org.dromara.hutool.poi.excel.sax.ExcelSaxReader;
import org.dromara.hutool.poi.excel.sax.ExcelSaxUtil;
import org.dromara.hutool.poi.excel.sax.handler.RowHandler;
@ -454,38 +452,4 @@ public class ExcelUtil {
throw new DependencyException(ObjUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG);
}
}
/**
* 将Sheet列号变为列名
*
* @param index 列号, 从0开始
* @return 0-A; 1-B...26-AA
* @since 4.1.20
*/
public static String indexToColName(final int index) {
return CellLocationUtil.indexToColName(index);
}
/**
* 根据表元的列名转换为列号
*
* @param colName 列名, 从A开始
* @return A1-0; B1-1...AA1-26
* @since 4.1.20
*/
public static int colNameToIndex(final String colName) {
return CellLocationUtil.colNameToIndex(colName);
}
/**
* 将Excel中地址标识符例如A11B5等转换为行列表示<br>
* 例如A11 - x:0,y:10B5-x:1,y:4
*
* @param locationRef 单元格地址标识符例如A11B5
* @return 坐标点x表示行从0开始y表示列从0开始
* @since 5.1.4
*/
public static CellLocation toLocation(final String locationRef) {
return CellLocationUtil.toLocation(locationRef);
}
}

View File

@ -16,6 +16,7 @@ import org.apache.poi.common.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
@ -34,7 +35,7 @@ import org.dromara.hutool.core.map.multi.Table;
import org.dromara.hutool.core.reflect.FieldUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import org.dromara.hutool.poi.excel.cell.CellLocation;
import org.dromara.hutool.poi.excel.cell.CellRangeUtil;
import org.dromara.hutool.poi.excel.cell.CellUtil;
import org.dromara.hutool.poi.excel.style.Align;
@ -681,7 +682,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
final int rowIndex = this.currentRow.get();
merge(rowIndex, rowIndex, 0, lastColumn, content, isSetHeaderStyle);
merge(CellRangeUtil.ofSingleRow(rowIndex, lastColumn), content, isSetHeaderStyle);
// 设置内容后跳到下一行
if (null != content) {
@ -694,16 +695,13 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
* 合并某行的单元格并写入对象到单元格<br>
* 样式为默认标题样式可使用{@link #getHeadCellStyle()}方法调用后自定义默认样式
*
* @param firstRow 起始行0开始
* @param lastRow 结束行0开始
* @param firstColumn 起始列0开始
* @param lastColumn 结束列0开始
* @param cellRangeAddress 合并单元格范围定义了起始行列和结束行列
* @param content 合并单元格后的内容
* @param isSetHeaderStyle 是否为合并后的单元格设置默认标题样式只提取边框样式
* @return this
* @since 4.0.10
*/
public ExcelWriter merge(final int firstRow, final int lastRow, final int firstColumn, final int lastColumn, final Object content, final boolean isSetHeaderStyle) {
public ExcelWriter merge(final CellRangeAddress cellRangeAddress, final Object content, final boolean isSetHeaderStyle) {
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
CellStyle style = null;
@ -711,30 +709,27 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
style = styleSet.getStyleByValueType(content, isSetHeaderStyle);
}
return merge(firstRow, lastRow, firstColumn, lastColumn, content, style);
return merge(cellRangeAddress, content, style);
}
/**
* 合并单元格并写入对象到单元格,使用指定的样式<br>
* 指定样式传入null则不使用任何样式
*
* @param firstRow 起始行0开始
* @param lastRow 结束行0开始
* @param firstColumn 起始列0开始
* @param lastColumn 结束列0开始
* @param cellRangeAddress 合并单元格范围定义了起始行列和结束行列
* @param content 合并单元格后的内容
* @param cellStyle 合并后单元格使用的样式可以为null
* @return this
* @since 5.6.5
*/
public ExcelWriter merge(final int firstRow, final int lastRow, final int firstColumn, final int lastColumn, final Object content, final CellStyle cellStyle) {
public ExcelWriter merge(final CellRangeAddress cellRangeAddress, final Object content, final CellStyle cellStyle) {
Assert.isFalse(this.isClosed, "ExcelWriter has been closed!");
CellUtil.mergingCells(this.getSheet(), firstRow, lastRow, firstColumn, lastColumn, cellStyle);
CellUtil.mergingCells(this.getSheet(), cellRangeAddress, cellStyle);
// 设置内容
if (null != content) {
final Cell cell = getOrCreateCell(firstColumn, firstRow);
final Cell cell = getOrCreateCell(cellRangeAddress.getFirstColumn(), cellRangeAddress.getFirstRow());
CellUtil.setCellValue(cell, content, cellStyle, this.cellEditor);
}
return this;
@ -1198,8 +1193,8 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
* @since 5.1.4
*/
public ExcelWriter writeCellValue(final String locationRef, final Object value) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return writeCellValue(cellLocation.getX(), cellLocation.getY(), value);
final CellReference cellReference = new CellReference(locationRef);
return writeCellValue(cellReference.getCol(), cellReference.getRow(), value);
}
/**
@ -1247,8 +1242,8 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
* @since 5.1.4
*/
public ExcelWriter setStyle(final CellStyle style, final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return setStyle(style, cellLocation.getX(), cellLocation.getY());
final CellReference cellReference = new CellReference(locationRef);
return setStyle(style, cellReference.getCol(), cellReference.getRow());
}
/**

View File

@ -1,99 +0,0 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.poi.excel.cell;
import java.io.Serializable;
import java.util.Objects;
/**
* 单元格位置
*
* @author Looly
* @since 5.1.4
*/
public class CellLocation implements Serializable {
private static final long serialVersionUID = 1L;
private int x;
private int y;
/**
* 构造
*
* @param x 列号从0开始
* @param y 行号从0开始
*/
public CellLocation(final int x, final int y) {
this.x = x;
this.y = y;
}
/**
* 获取x
*
* @return x
*/
public int getX() {
return x;
}
/**
* 设置x
*
* @param x x
*/
public void setX(final int x) {
this.x = x;
}
/**
* 获取y
* @return y
*/
public int getY() {
return y;
}
/**
* 设置y
* @param y y
*/
public void setY(final int y) {
this.y = y;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final CellLocation that = (CellLocation) o;
return x == that.x && y == that.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
@Override
public String toString() {
return "CellLocation{" +
"x=" + x +
", y=" + y +
'}';
}
}

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2024. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.poi.excel.cell;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
/**
* {@link CellRangeAddress} 工具类<br>
* {@link CellRangeAddress} 表示表格的一个区域通过定义起始行和列以及结束行和列圈定范围如设置合并单元格等
*
* @author Looly
* @since 6.0.0
*/
public class CellRangeUtil {
/**
* 根据字符串表示法创建一个CellRangeAddress对象
* <p>
* 该方法提供了一种通过直接使用字符串引用来创建CellRangeAddress对象的便捷方式
* 字符串引用应符合Excel中单元格范围的常规表示法"B1" "A1:B2"
*
* @param ref 代表单元格范围的字符串格式为"A1:B2"
* @return 根据给定字符串创建的CellRangeAddress对象
* @see CellRangeAddress#valueOf(String)
*/
public static CellRangeAddress of(final String ref) {
return CellRangeAddress.valueOf(ref);
}
/**
* 根据给定的行和列索引创建一个CellRangeAddress对象
* 这个方法提供了一种简洁的方式来表示一个Excel表格中特定的区域由起始行和列以及结束行和列定义
*
* @param firstRow 起始行的索引从0开始计数
* @param lastRow 结束行的索引从0开始计数必须大于firstRow
* @param firstCol 起始列的索引从0开始计数
* @param lastCol 结束列的索引从0开始计数必须大于firstCol
* @return 返回一个新的CellRangeAddress对象表示由参数定义的区域
*/
public static CellRangeAddress of(final int firstRow, final int lastRow, final int firstCol, final int lastCol) {
return new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
}
/**
* 根据给定的行和列索引创建一个单行的CellRangeAddress对象从首列开始
* 这个方法提供了一种简洁的方式来表示一个Excel表格中特定的区域由起始行和列以及结束行和列定义
*
* @param row 行的索引从0开始计数
* @param lastCol 结束列的索引从0开始计数必须大于firstCol
* @return 返回一个新的CellRangeAddress对象表示由参数定义的区域
*/
public static CellRangeAddress ofSingleRow(final int row, final int lastCol) {
return ofSingleRow(row, 0, lastCol);
}
/**
* 根据给定的行和列索引创建一个单行的CellRangeAddress对象
* 这个方法提供了一种简洁的方式来表示一个Excel表格中特定的区域由起始行和列以及结束行和列定义
*
* @param row 行的索引从0开始计数
* @param firstCol 起始列的索引从0开始计数
* @param lastCol 结束列的索引从0开始计数必须大于firstCol
* @return 返回一个新的CellRangeAddress对象表示由参数定义的区域
*/
public static CellRangeAddress ofSingleRow(final int row, final int firstCol, final int lastCol) {
return of(row, row, firstCol, lastCol);
}
/**
* 根据给定的行和列索引创建一个单列CellRangeAddress对象从首行开始
* 这个方法提供了一种简洁的方式来表示一个Excel表格中特定的区域由起始行和列以及结束行和列定义
*
* @param lastRow 结束行的索引从0开始计数必须大于firstRow
* @param col 列的索引从0开始计数
* @return 返回一个新的CellRangeAddress对象表示由参数定义的区域
*/
public static CellRangeAddress ofSingleColumn(final int lastRow, final int col) {
return ofSingleColumn(0, lastRow, col);
}
/**
* 根据给定的行和列索引创建一个单列CellRangeAddress对象
* 这个方法提供了一种简洁的方式来表示一个Excel表格中特定的区域由起始行和列以及结束行和列定义
*
* @param firstRow 起始行的索引从0开始计数
* @param lastRow 结束行的索引从0开始计数必须大于firstRow
* @param col 列的索引从0开始计数
* @return 返回一个新的CellRangeAddress对象表示由参数定义的区域
*/
public static CellRangeAddress ofSingleColumn(final int firstRow, final int lastRow, final int col) {
return of(firstRow, lastRow, col, col);
}
// region ----- getCellRangeAddress
/**
* 获取合并单元格{@link CellRangeAddress}如果不是返回null
*
* @param sheet {@link Sheet}
* @param locationRef 单元格地址标识符例如A11B5
* @return {@link CellRangeAddress}
* @since 5.8.0
*/
public static CellRangeAddress getCellRangeAddress(final Sheet sheet, final String locationRef) {
final CellReference cellReference = new CellReference(locationRef);
return getCellRangeAddress(sheet, cellReference.getCol(), cellReference.getRow());
}
/**
* 获取合并单元格{@link CellRangeAddress}如果不是返回null
*
* @param cell {@link Cell}
* @return {@link CellRangeAddress}
* @since 5.8.0
*/
public static CellRangeAddress getCellRangeAddress(final Cell cell) {
return getCellRangeAddress(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex());
}
/**
* 获取合并单元格{@link CellRangeAddress}如果不是返回null
*
* @param sheet {@link Sheet}
* @param x 列号从0开始
* @param y 行号从0开始
* @return {@link CellRangeAddress}
* @since 5.8.0
*/
public static CellRangeAddress getCellRangeAddress(final Sheet sheet, final int x, final int y) {
if (sheet != null) {
final int sheetMergeCount = sheet.getNumMergedRegions();
CellRangeAddress ca;
for (int i = 0; i < sheetMergeCount; i++) {
ca = sheet.getMergedRegion(i);
if (y >= ca.getFirstRow() && y <= ca.getLastRow()
&& x >= ca.getFirstColumn() && x <= ca.getLastColumn()) {
return ca;
}
}
}
return null;
}
// endregion
}

View File

@ -12,16 +12,16 @@
package org.dromara.hutool.poi.excel.cell;
import org.dromara.hutool.core.regex.ReUtil;
import org.apache.poi.ss.util.CellReference;
import org.dromara.hutool.core.text.StrUtil;
/**
* 单元格位置工具类提供包括行号转行名称列号转列名称等功能
* 单元格位置{@link CellReference}工具类提供包括行号转行名称列号转列名称等功能
*
* @author looly
* @since 6.0.0
*/
public class CellLocationUtil {
public class CellReferenceUtil {
/**
* 将Sheet列号变为列名
*
@ -66,14 +66,12 @@ public class CellLocationUtil {
/**
* 将Excel中地址标识符例如A11B5等转换为行列表示<br>
* 例如A11 - x:0,y:10B5-x:1,y:4
* 例如A11 - col:0,row:10B5-col:1,row:4
*
* @param locationRef 单元格地址标识符例如A11B5
* @return 坐标点x表示行从0开始y表示列从0开始
* @return 坐标点
*/
public static CellLocation toLocation(final String locationRef) {
final int x = colNameToIndex(locationRef);
final int y = ReUtil.getFirstNumber(locationRef) - 1;
return new CellLocation(x, y);
public static CellReference toCellReference(final String locationRef) {
return new CellReference(locationRef);
}
}

View File

@ -12,18 +12,18 @@
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.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.poi.excel.ExcelUtil;
import org.dromara.hutool.poi.excel.StyleSet;
import org.dromara.hutool.poi.excel.cell.editors.TrimEditor;
import org.dromara.hutool.poi.excel.cell.setters.CellSetterFactory;
import org.dromara.hutool.poi.excel.cell.values.ErrorCellValue;
import org.dromara.hutool.poi.excel.cell.values.NumericCellValue;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.ss.util.SheetUtil;
/**
* Excel表格中单元格工具类
@ -261,56 +261,6 @@ public class CellUtil {
}
// endregion
// region ----- getCellRangeAddress
/**
* 获取合并单元格{@link CellRangeAddress}如果不是返回null
*
* @param sheet {@link Sheet}
* @param locationRef 单元格地址标识符例如A11B5
* @return {@link CellRangeAddress}
* @since 5.8.0
*/
public static CellRangeAddress getCellRangeAddress(final Sheet sheet, final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return getCellRangeAddress(sheet, cellLocation.getX(), cellLocation.getY());
}
/**
* 获取合并单元格{@link CellRangeAddress}如果不是返回null
*
* @param cell {@link Cell}
* @return {@link CellRangeAddress}
* @since 5.8.0
*/
public static CellRangeAddress getCellRangeAddress(final Cell cell) {
return getCellRangeAddress(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex());
}
/**
* 获取合并单元格{@link CellRangeAddress}如果不是返回null
*
* @param sheet {@link Sheet}
* @param x 列号从0开始
* @param y 行号从0开始
* @return {@link CellRangeAddress}
* @since 5.8.0
*/
public static CellRangeAddress getCellRangeAddress(final Sheet sheet, final int x, final int y) {
if (sheet != null) {
final int sheetMergeCount = sheet.getNumMergedRegions();
CellRangeAddress ca;
for (int i = 0; i < sheetMergeCount; i++) {
ca = sheet.getMergedRegion(i);
if (y >= ca.getFirstRow() && y <= ca.getLastRow()
&& x >= ca.getFirstColumn() && x <= ca.getLastColumn()) {
return ca;
}
}
}
return null;
}
// endregion
// region ----- merging 合并单元格
/**
* 判断指定的单元格是否是合并单元格
@ -321,8 +271,8 @@ public class CellUtil {
* @since 5.1.5
*/
public static boolean isMergedRegion(final Sheet sheet, final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return isMergedRegion(sheet, cellLocation.getX(), cellLocation.getY());
final CellReference cellReference = new CellReference(locationRef);
return isMergedRegion(sheet, cellReference.getCol(), cellReference.getRow());
}
/**
@ -361,35 +311,22 @@ public class CellUtil {
* 合并单元格可以根据设置的值来合并行和列
*
* @param sheet 表对象
* @param firstRow 起始行0开始
* @param lastRow 结束行0开始
* @param firstColumn 起始列0开始
* @param lastColumn 结束列0开始
* @param cellRangeAddress 合并单元格范围定义了起始行列和结束行列
* @return 合并后的单元格号
*/
public static int mergingCells(final Sheet sheet, final int firstRow, final int lastRow, final int firstColumn, final int lastColumn) {
return mergingCells(sheet, firstRow, lastRow, firstColumn, lastColumn, null);
public static int mergingCells(final Sheet sheet, final CellRangeAddress cellRangeAddress) {
return mergingCells(sheet, cellRangeAddress, null);
}
/**
* 合并单元格可以根据设置的值来合并行和列
*
* @param sheet 表对象
* @param firstRow 起始行0开始
* @param lastRow 结束行0开始
* @param firstColumn 起始列0开始
* @param lastColumn 结束列0开始
* @param cellRangeAddress 合并单元格范围定义了起始行列和结束行列
* @param cellStyle 单元格样式只提取边框样式null表示无样式
* @return 合并后的单元格号
*/
public static int mergingCells(final Sheet sheet, final int firstRow, final int lastRow, final int firstColumn, final int lastColumn, final CellStyle cellStyle) {
final CellRangeAddress cellRangeAddress = new CellRangeAddress(//
firstRow, // first row (0-based)
lastRow, // last row (0-based)
firstColumn, // first column (0-based)
lastColumn // last column (0-based)
);
public static int mergingCells(final Sheet sheet, final CellRangeAddress cellRangeAddress, final CellStyle cellStyle) {
setMergeCellStyle(cellStyle, cellRangeAddress, sheet);
return sheet.addMergedRegion(cellRangeAddress);
}
@ -404,8 +341,8 @@ public class CellUtil {
* @since 5.1.5
*/
public static Object getMergedRegionValue(final Sheet sheet, final String locationRef) {
final CellLocation cellLocation = ExcelUtil.toLocation(locationRef);
return getMergedRegionValue(sheet, cellLocation.getX(), cellLocation.getY());
final CellReference cellReference = new CellReference(locationRef);
return getMergedRegionValue(sheet, cellReference.getCol(), cellReference.getRow());
}
/**

View File

@ -12,12 +12,12 @@
package org.dromara.hutool.poi.excel.reader;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.poi.excel.ExcelUtil;
import org.dromara.hutool.poi.excel.RowUtil;
import org.dromara.hutool.poi.excel.cell.CellEditor;
import org.apache.poi.ss.usermodel.Sheet;
import org.dromara.hutool.poi.excel.cell.CellReferenceUtil;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@ -137,7 +137,7 @@ public abstract class AbstractSheetReader<T> implements SheetReader<T> {
*/
protected String aliasHeader(final Object headerObj, final int index) {
if (null == headerObj) {
return ExcelUtil.indexToColName(index);
return CellReferenceUtil.indexToColName(index);
}
final String header = headerObj.toString();

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2024. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.poi.excel.style;
import org.apache.poi.ss.usermodel.CellStyle;
public interface StyleSet {
CellStyle getStyleFor(int x, int y, Object cellValue);
}

View File

@ -12,7 +12,8 @@
package org.dromara.hutool.poi.excel;
import org.dromara.hutool.poi.excel.cell.CellLocation;
import org.apache.poi.ss.util.CellReference;
import org.dromara.hutool.poi.excel.cell.CellReferenceUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -23,39 +24,39 @@ public class ExcelUtilTest {
@Test
public void indexToColNameTest() {
Assertions.assertEquals("A", ExcelUtil.indexToColName(0));
Assertions.assertEquals("B", ExcelUtil.indexToColName(1));
Assertions.assertEquals("C", ExcelUtil.indexToColName(2));
Assertions.assertEquals("A", CellReferenceUtil.indexToColName(0));
Assertions.assertEquals("B", CellReferenceUtil.indexToColName(1));
Assertions.assertEquals("C", CellReferenceUtil.indexToColName(2));
Assertions.assertEquals("AA", ExcelUtil.indexToColName(26));
Assertions.assertEquals("AB", ExcelUtil.indexToColName(27));
Assertions.assertEquals("AC", ExcelUtil.indexToColName(28));
Assertions.assertEquals("AA", CellReferenceUtil.indexToColName(26));
Assertions.assertEquals("AB", CellReferenceUtil.indexToColName(27));
Assertions.assertEquals("AC", CellReferenceUtil.indexToColName(28));
Assertions.assertEquals("AAA", ExcelUtil.indexToColName(702));
Assertions.assertEquals("AAB", ExcelUtil.indexToColName(703));
Assertions.assertEquals("AAC", ExcelUtil.indexToColName(704));
Assertions.assertEquals("AAA", CellReferenceUtil.indexToColName(702));
Assertions.assertEquals("AAB", CellReferenceUtil.indexToColName(703));
Assertions.assertEquals("AAC", CellReferenceUtil.indexToColName(704));
}
@Test
public void colNameToIndexTest() {
Assertions.assertEquals(704, ExcelUtil.colNameToIndex("AAC"));
Assertions.assertEquals(703, ExcelUtil.colNameToIndex("AAB"));
Assertions.assertEquals(702, ExcelUtil.colNameToIndex("AAA"));
Assertions.assertEquals(704, CellReferenceUtil.colNameToIndex("AAC"));
Assertions.assertEquals(703, CellReferenceUtil.colNameToIndex("AAB"));
Assertions.assertEquals(702, CellReferenceUtil.colNameToIndex("AAA"));
Assertions.assertEquals(28, ExcelUtil.colNameToIndex("AC"));
Assertions.assertEquals(27, ExcelUtil.colNameToIndex("AB"));
Assertions.assertEquals(26, ExcelUtil.colNameToIndex("AA"));
Assertions.assertEquals(28, CellReferenceUtil.colNameToIndex("AC"));
Assertions.assertEquals(27, CellReferenceUtil.colNameToIndex("AB"));
Assertions.assertEquals(26, CellReferenceUtil.colNameToIndex("AA"));
Assertions.assertEquals(2, ExcelUtil.colNameToIndex("C"));
Assertions.assertEquals(1, ExcelUtil.colNameToIndex("B"));
Assertions.assertEquals(0, ExcelUtil.colNameToIndex("A"));
Assertions.assertEquals(2, CellReferenceUtil.colNameToIndex("C"));
Assertions.assertEquals(1, CellReferenceUtil.colNameToIndex("B"));
Assertions.assertEquals(0, CellReferenceUtil.colNameToIndex("A"));
}
@Test
public void toLocationTest() {
final CellLocation a11 = ExcelUtil.toLocation("A11");
Assertions.assertEquals(0, a11.getX());
Assertions.assertEquals(10, a11.getY());
public void cellReferenceTest() {
final CellReference a11 = new CellReference("A11");
Assertions.assertEquals(0, a11.getCol());
Assertions.assertEquals(10, a11.getRow());
}
@Test

View File

@ -12,6 +12,11 @@
package org.dromara.hutool.poi.excel.writer;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.file.FileUtil;
@ -22,10 +27,6 @@ import org.dromara.hutool.poi.excel.ExcelUtil;
import org.dromara.hutool.poi.excel.ExcelWriter;
import org.dromara.hutool.poi.excel.TestBean;
import org.dromara.hutool.poi.excel.style.StyleUtil;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -102,7 +103,7 @@ public class BigExcelWriteTest {
writer.write(rows);
// 合并单元格后的标题行使用默认标题样式
writer.merge(7, 10, 4, 10, "测试Merge", false);
writer.merge(new CellRangeAddress(7, 10, 4, 10), "测试Merge", false);
// 关闭writer释放内存
writer.close();

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.poi.excel.writer;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.file.FileUtil;
@ -187,7 +188,7 @@ public class ExcelWriteTest {
writer.write(rows);
// 合并单元格后的标题行使用默认标题样式
writer.merge(7, 10, 4, 10, "测试Merge", false);
writer.merge(new CellRangeAddress(7, 10, 4, 10), "测试Merge", false);
// 关闭writer释放内存
writer.close();
@ -705,14 +706,14 @@ public class ExcelWriteTest {
cellStyle.setFont(font);
// 合并单元格后的标题行使用设置好的样式
writer.merge(0, 1, 0, row1.size() - 1, "标题XXXXXXXX", cellStyle);
writer.merge(new CellRangeAddress(0, 1, 0, row1.size() - 1), "标题XXXXXXXX", cellStyle);
Console.log(writer.getCurrentRow());
//设置复杂表头
writer.merge(2, 3, 0, 0, "序号", true);
writer.merge(2, 2, 1, 2, "AABB", true);
writer.merge(2, 3, 3, 3, "CCCC", true);
writer.merge(2, 2, 4, 5, "DDEE", true);
writer.merge(new CellRangeAddress(2, 3, 0, 0), "序号", true);
writer.merge(new CellRangeAddress(2, 2, 1, 2), "AABB", true);
writer.merge(new CellRangeAddress(2, 3, 3, 3), "CCCC", true);
writer.merge(new CellRangeAddress(2, 2, 4, 5), "DDEE", true);
writer.setCurrentRow(3);
final List<String> sechead = ListUtil.of("AA", "BB", "DD", "EE");
@ -775,7 +776,7 @@ public class ExcelWriteTest {
//合并单元格后的标题行使用默认标题样式
writer.merge(7, "测试标题");
writer.merge(3, 4, 0, 0, new XSSFRichTextString("9999"), true);
writer.merge(new CellRangeAddress(3, 4, 0, 0), new XSSFRichTextString("9999"), true);
writer.write(list, true);
writer.close();
}
@ -789,7 +790,7 @@ public class ExcelWriteTest {
final String path = "d:/test/mergeForDate.xlsx";
FileUtil.del(FileUtil.file(path));
final ExcelWriter writer = ExcelUtil.getWriter(path);
writer.merge(0, 3, 0, 2, DateUtil.now(), false);
writer.merge(new CellRangeAddress(0, 3, 0, 2), DateUtil.now(), false);
writer.close();
}
@ -870,7 +871,7 @@ public class ExcelWriteTest {
FileUtil.del(tempFile);
final BigExcelWriter writer = new BigExcelWriter(tempFile);
writer.merge(0, 1, 2, 2, 3.99, false);
writer.merge(new CellRangeAddress(0, 1, 2, 2), 3.99, false);
writer.close();
}

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.poi.excel.writer;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.poi.excel.ExcelUtil;
@ -84,9 +85,9 @@ public class Issue2221Test {
writer.setOnlyAlias(true);
// 设置合并的单元格
writer.merge(0, 1, 0, 0, "日期", true);
writer.merge(0, 0, 1, 2, "运行次数", true);
writer.merge(0, 0, 3, 4, "新增人数", true);
writer.merge(new CellRangeAddress(0, 1, 0, 0), "日期", true);
writer.merge(new CellRangeAddress(0, 0, 1, 2), "运行次数", true);
writer.merge(new CellRangeAddress(0, 0, 3, 4), "新增人数", true);
// 写入数据
final List<Map<Object, Object>> data = ListUtil.view(