mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix bug
This commit is contained in:
@@ -5,7 +5,12 @@ import org.apache.poi.ss.usermodel.Cell;
|
||||
/**
|
||||
* 单元格编辑器接口<br>
|
||||
* 在读取Excel值时,有时我们需要针对所有单元格统一处理结果值(如null转默认值)的情况,实现接口并调用<br>
|
||||
* reader.setCellEditor()设置编辑器
|
||||
* reader.setCellEditor()设置编辑器<br>
|
||||
* 此接口可完成以下功能:
|
||||
* <ul>
|
||||
* <li>对单元格进行编辑,如修改样式等。</li>
|
||||
* <li>对单元格的值进行编辑,如根据单元格修改不同值,然后返回</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
@@ -17,7 +22,7 @@ public interface CellEditor {
|
||||
*
|
||||
* @param cell 单元格对象,可以获取单元格行、列样式等信息
|
||||
* @param value 单元格值
|
||||
* @return 编辑后的对象
|
||||
* @return 编辑后的值
|
||||
*/
|
||||
Object edit(Cell cell, Object value);
|
||||
}
|
||||
|
@@ -1,23 +1,14 @@
|
||||
package cn.hutool.poi.excel.cell;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.poi.excel.ExcelUtil;
|
||||
import cn.hutool.poi.excel.StyleSet;
|
||||
import cn.hutool.poi.excel.cell.editors.TrimEditor;
|
||||
import cn.hutool.poi.excel.cell.setters.CellSetterFactory;
|
||||
import cn.hutool.poi.excel.cell.values.ErrorCellValue;
|
||||
import cn.hutool.poi.excel.cell.values.NumericCellValue;
|
||||
import cn.hutool.poi.excel.cell.editors.TrimEditor;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
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;
|
||||
@@ -30,6 +21,7 @@ import org.apache.poi.ss.util.SheetUtil;
|
||||
*/
|
||||
public class CellUtil {
|
||||
|
||||
// region ----- getCellValue
|
||||
/**
|
||||
* 获取单元格值
|
||||
*
|
||||
@@ -128,7 +120,9 @@ public class CellUtil {
|
||||
|
||||
return null == cellEditor ? value : cellEditor.edit(cell, value);
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region ----- setCellValue
|
||||
/**
|
||||
* 设置单元格值<br>
|
||||
* 根据传入的styleSet自动匹配样式<br>
|
||||
@@ -182,6 +176,27 @@ public class CellUtil {
|
||||
return;
|
||||
}
|
||||
|
||||
if (null != cellEditor) {
|
||||
value = cellEditor.edit(cell, value);
|
||||
}
|
||||
|
||||
setCellValue(cell, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置单元格值<br>
|
||||
* 根据传入的styleSet自动匹配样式<br>
|
||||
* 当为头部样式时默认赋值头部样式,但是头部中如果有数字、日期等类型,将按照数字、日期样式设置
|
||||
*
|
||||
* @param cell 单元格
|
||||
* @param value 值或{@link CellSetter}
|
||||
* @since 5.6.4
|
||||
*/
|
||||
public static void setCellValue(final Cell cell, final Object value) {
|
||||
if (null == cell) {
|
||||
return;
|
||||
}
|
||||
|
||||
// issue#1659@Github
|
||||
// 在使用BigWriter(SXSSF)模式写出数据时,单元格值为直接值,非引用值(is标签)
|
||||
// 而再使用ExcelWriter(XSSF)编辑时,会写出引用值,导致失效。
|
||||
@@ -190,12 +205,11 @@ public class CellUtil {
|
||||
cell.setBlank();
|
||||
}
|
||||
|
||||
if (null != cellEditor) {
|
||||
value = cellEditor.edit(cell, value);
|
||||
}
|
||||
CellSetterFactory.createCellSetter(value).setValue(cell);
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region ----- getCell
|
||||
/**
|
||||
* 获取单元格,如果单元格不存在,返回{@link NullCell}
|
||||
*
|
||||
@@ -233,52 +247,9 @@ public class CellUtil {
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 判断指定的单元格是否是合并单元格
|
||||
*
|
||||
* @param sheet {@link Sheet}
|
||||
* @param locationRef 单元格地址标识符,例如A11,B5
|
||||
* @return 是否是合并单元格
|
||||
* @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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定的单元格是否是合并单元格
|
||||
*
|
||||
* @param cell {@link Cell}
|
||||
* @return 是否是合并单元格
|
||||
* @since 5.1.5
|
||||
*/
|
||||
public static boolean isMergedRegion(final Cell cell) {
|
||||
return isMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定的单元格是否是合并单元格
|
||||
*
|
||||
* @param sheet {@link Sheet}
|
||||
* @param x 列号,从0开始
|
||||
* @param y 行号,从0开始
|
||||
* @return 是否是合并单元格
|
||||
*/
|
||||
public static boolean isMergedRegion(final Sheet sheet, final int x, final int y) {
|
||||
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 true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// region ----- getCellRangeAddress
|
||||
/**
|
||||
* 获取合并单元格{@link CellRangeAddress},如果不是返回null
|
||||
*
|
||||
@@ -326,7 +297,53 @@ public class CellUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region ----- merging 合并单元格
|
||||
/**
|
||||
* 判断指定的单元格是否是合并单元格
|
||||
*
|
||||
* @param sheet {@link Sheet}
|
||||
* @param locationRef 单元格地址标识符,例如A11,B5
|
||||
* @return 是否是合并单元格
|
||||
* @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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定的单元格是否是合并单元格
|
||||
*
|
||||
* @param cell {@link Cell}
|
||||
* @return 是否是合并单元格
|
||||
* @since 5.1.5
|
||||
*/
|
||||
public static boolean isMergedRegion(final Cell cell) {
|
||||
return isMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定的单元格是否是合并单元格
|
||||
*
|
||||
* @param sheet {@link Sheet}
|
||||
* @param x 列号,从0开始
|
||||
* @param y 行号,从0开始
|
||||
* @return 是否是合并单元格
|
||||
*/
|
||||
public static boolean isMergedRegion(final Sheet sheet, final int x, final int y) {
|
||||
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 true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并单元格,可以根据设置的值来合并行和列
|
||||
@@ -426,6 +443,7 @@ public class CellUtil {
|
||||
getCellIfMergedRegion(sheet, x, y),
|
||||
() -> SheetUtil.getCell(sheet, y, x));
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 为特定单元格添加批注
|
||||
@@ -433,29 +451,46 @@ public class CellUtil {
|
||||
* @param cell 单元格
|
||||
* @param commentText 批注内容
|
||||
* @param commentAuthor 作者
|
||||
*/
|
||||
public static void setComment(final Cell cell, final String commentText, final String commentAuthor) {
|
||||
setComment(cell, commentText, commentAuthor, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为特定单元格添加批注
|
||||
*
|
||||
* @param cell 单元格
|
||||
* @param commentText 批注内容
|
||||
* @param commentAuthor 作者,{@code null}表示无作者
|
||||
* @param anchor 批注的位置、大小等信息,null表示使用默认
|
||||
* @since 5.4.8
|
||||
*/
|
||||
public static void setComment(final Cell cell, final String commentText, final String commentAuthor, ClientAnchor anchor) {
|
||||
final Sheet sheet = cell.getSheet();
|
||||
final Workbook wb = sheet.getWorkbook();
|
||||
final Drawing<?> drawing = sheet.createDrawingPatriarch();
|
||||
final CreationHelper factory = wb.getCreationHelper();
|
||||
final CreationHelper factory = sheet.getWorkbook().getCreationHelper();
|
||||
if (anchor == null) {
|
||||
anchor = factory.createClientAnchor();
|
||||
// 默认位置,在注释的单元格的右方
|
||||
anchor.setCol1(cell.getColumnIndex() + 1);
|
||||
anchor.setCol2(cell.getColumnIndex() + 3);
|
||||
anchor.setRow1(cell.getRowIndex());
|
||||
anchor.setRow2(cell.getRowIndex() + 2);
|
||||
// 自适应
|
||||
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
|
||||
}
|
||||
final Comment comment = drawing.createCellComment(anchor);
|
||||
|
||||
final Comment comment = sheet.createDrawingPatriarch().createCellComment(anchor);
|
||||
// https://stackoverflow.com/questions/28169011/using-sxssfapache-poi-and-adding-comment-does-not-generate-proper-excel-file
|
||||
// 修正在XSSFCell中未设置地址导致错位问题
|
||||
comment.setAddress(cell.getAddress());
|
||||
comment.setString(factory.createRichTextString(commentText));
|
||||
comment.setAuthor(StrUtil.emptyIfNull(commentAuthor));
|
||||
if(null != commentAuthor){
|
||||
comment.setAuthor(commentAuthor);
|
||||
}
|
||||
cell.setCellComment(comment);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 获取合并单元格,非合并单元格返回{@code null}<br>
|
||||
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
|
||||
|
@@ -0,0 +1,48 @@
|
||||
package cn.hutool.poi.excel;
|
||||
|
||||
import cn.hutool.poi.excel.cell.CellUtil;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I6MBS5<br>
|
||||
* 经过测试,发现BigExcelWriter中的comment会错位<br>
|
||||
* 修正方式见: https://stackoverflow.com/questions/28169011/using-sxssfapache-poi-and-adding-comment-does-not-generate-proper-excel-file
|
||||
*/
|
||||
public class IssueI6MBS5Test {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void setCommentTest() {
|
||||
final ExcelWriter writer = ExcelUtil.getBigWriter("d:/test/setCommentTest.xlsx");
|
||||
final Cell cell = writer.getOrCreateCell(0, 0);
|
||||
CellUtil.setCellValue(cell, "cellValue");
|
||||
CellUtil.setComment(cell, "commonText", "ascend");
|
||||
|
||||
writer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void setCommentTest2() {
|
||||
final File file = new File("D:\\test\\CellUtilTest.xlsx");
|
||||
try (final Workbook workbook = WorkbookUtil.createBook(true)) {
|
||||
final Sheet sheet = workbook.createSheet();
|
||||
final Row row = sheet.createRow(0);
|
||||
final Cell cell = row.createCell(0);
|
||||
CellUtil.setCellValue(cell, "cellValue");
|
||||
CellUtil.setComment(cell, "commonText", "ascend", null);
|
||||
workbook.write(Files.newOutputStream(file.toPath()));
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user