diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c8d2a66..68eb83149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ## 5.1.5 ### 新特性 +* 【poi 】 Excel合并单元格读取同一个值,不再为空 + ### Bug修复 ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java index 63ecd1396..8c6c911f7 100644 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java @@ -1,7 +1,9 @@ package cn.hutool.db.dialect; /** - * 方言名 + * 方言名
+ * 方言枚举列出了Hutool支持的所有数据库方言 + * * @author Looly * */ diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java b/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java index c32b50994..f5ca1de29 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java @@ -531,7 +531,7 @@ public class SqlBuilder implements Builder{ * @return 插入或更新的数据库字段列表 */ public String[] getFieldArray() { - return this.fields.toArray(new String[this.fields.size()]); + return this.fields.toArray(new String[0]); } /** @@ -558,7 +558,7 @@ public class SqlBuilder implements Builder{ * @return 占位符对应的值列表 */ public Object[] getParamValueArray() { - return this.paramValues.toArray(new Object[this.paramValues.size()]); + return this.paramValues.toArray(new Object[0]); } /** diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/RowUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/RowUtil.java index 39c7618de..1a5684ed7 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/RowUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/RowUtil.java @@ -49,7 +49,7 @@ public class RowUtil { if (length < 0) { return new ArrayList<>(0); } - final List cellValues = new ArrayList<>((int) length); + final List cellValues = new ArrayList<>(length); Object cellValue; boolean isAllNull = true; for (short i = 0; i < length; i++) { diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java index 07092d5db..b369e5a1e 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java @@ -2,6 +2,7 @@ package cn.hutool.poi.excel.cell; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.StyleSet; import cn.hutool.poi.excel.editors.TrimEditor; import org.apache.poi.ss.usermodel.Cell; @@ -102,6 +103,12 @@ public class CellUtil { cellType = cell.getCellTypeEnum(); } + if(CellType.BLANK == cellType){ + // 空白单元格可能为合并单元格 + cell = getMergedRegionCell(cell); + cellType = cell.getCellType(); + } + Object value; switch (cellType) { case NUMERIC: @@ -239,17 +246,42 @@ public class CellUtil { /** * 判断指定的单元格是否是合并单元格 * - * @param sheet {@link Sheet} - * @param row 行号 - * @param column 列号 + * @param sheet {@link Sheet} + * @param locationRef 单元格地址标识符,例如A11,B5 + * @return 是否是合并单元格 + * @since 5.1.5 + */ + public static boolean isMergedRegion(Sheet sheet, 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(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(Sheet sheet, int row, int column) { + public static boolean isMergedRegion(Sheet sheet, int x, int y) { final int sheetMergeCount = sheet.getNumMergedRegions(); CellRangeAddress ca; for (int i = 0; i < sheetMergeCount; i++) { ca = sheet.getMergedRegion(i); - if (row >= ca.getFirstRow() && row <= ca.getLastRow() && column >= ca.getFirstColumn() && column <= ca.getLastColumn()) { + if (y >= ca.getFirstRow() && y <= ca.getLastRow() + && x >= ca.getFirstColumn() && x <= ca.getLastColumn()) { return true; } } @@ -284,17 +316,57 @@ public class CellUtil { return sheet.addMergedRegion(cellRangeAddress); } + /** + * 获取合并单元格的值
+ * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 + * + * @param sheet {@link Sheet} + * @param locationRef 单元格地址标识符,例如A11,B5 + * @return 合并单元格的值 + * @since 5.1.5 + */ + public static Object getMergedRegionValue(Sheet sheet, String locationRef) { + final CellLocation cellLocation = ExcelUtil.toLocation(locationRef); + return getMergedRegionValue(sheet, cellLocation.getX(), cellLocation.getY()); + } + /** * 获取合并单元格的值
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 * * @param sheet {@link Sheet} - * @param y 行号,从0开始,可以是合并单元格范围中的任意一行 * @param x 列号,从0开始,可以是合并单元格范围中的任意一列 + * @param y 行号,从0开始,可以是合并单元格范围中的任意一行 * @return 合并单元格的值 * @since 4.6.3 */ public static Object getMergedRegionValue(Sheet sheet, int x, int y) { + return getCellValue(getMergedRegionCell(sheet, x, y)); + } + + /** + * 获取合并单元格
+ * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 + * + * @param cell {@link Cell} + * @return 合并单元格 + * @since 5.1.5 + */ + public static Cell getMergedRegionCell(Cell cell) { + return getMergedRegionCell(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()); + } + + /** + * 获取合并单元格
+ * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 + * + * @param sheet {@link Sheet} + * @param x 列号,从0开始,可以是合并单元格范围中的任意一列 + * @param y 行号,从0开始,可以是合并单元格范围中的任意一行 + * @return 合并单元格,如果非合并单元格,返回坐标对应的单元格 + * @since 5.1.5 + */ + public static Cell getMergedRegionCell(Sheet sheet, int x, int y) { final List addrs = sheet.getMergedRegions(); int firstColumn; @@ -309,12 +381,12 @@ public class CellUtil { if (y >= firstRow && y <= lastRow) { if (x >= firstColumn && x <= lastColumn) { - return getCellValue(SheetUtil.getCell(sheet, firstRow, firstColumn)); + return SheetUtil.getCell(sheet, firstRow, firstColumn); } } } - return null; + return SheetUtil.getCell(sheet, y, x); } // -------------------------------------------------------------------------------------------------------------- Private method start diff --git a/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java b/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java index d224de536..d1693e332 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java @@ -1,21 +1,20 @@ package cn.hutool.poi.word; -import java.awt.Font; -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.poi.xwpf.usermodel.ParagraphAlignment; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.xwpf.usermodel.XWPFParagraph; -import org.apache.poi.xwpf.usermodel.XWPFRun; - import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ArrayUtil; +import org.apache.poi.xwpf.usermodel.ParagraphAlignment; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; + +import java.awt.Font; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; /** * Word生成器 diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java index fb12b0afc..2f3816802 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java @@ -15,16 +15,15 @@ import cn.hutool.poi.excel.ExcelUtil; /** * Excel读取单元测试 - * - * @author Looly * + * @author Looly */ public class ExcelReadTest { - + @Test public void aliasTest() { ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("alias.xlsx")); - + //读取单个单元格内容测试 Object value = reader.readCellValue(1, 2); Assert.assertEquals("仓库", value); @@ -77,13 +76,13 @@ public class ExcelReadTest { Assert.assertEquals(11L, readAll.get(1).get(2)); Assert.assertEquals(41.5D, readAll.get(1).get(3)); } - + @Test public void excelReadAsTextTest() { ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("aaa.xlsx")); Assert.assertNotNull(reader.readAsText(false)); } - + @Test public void excel03ReadTest() { ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("aaa.xls")); @@ -141,7 +140,7 @@ public class ExcelReadTest { Assert.assertEquals("男", all.get(0).getGender()); Assert.assertEquals(Integer.valueOf(11), all.get(0).getAge()); } - + @Test @Ignore public void excelReadToBeanListTest2() { @@ -150,7 +149,7 @@ public class ExcelReadTest { reader.addHeaderAlias("年龄", "age"); reader.addHeaderAlias("性别", "gender"); - List all = reader.read(0,2, Person.class); + List all = reader.read(0, 2, Person.class); for (Person person : all) { Console.log(person); } @@ -193,11 +192,20 @@ public class ExcelReadTest { @Test @Ignore - public void readDoubleTest(){ + public void readDoubleTest() { ExcelReader reader = ExcelUtil.getReader("f:/test/doubleTest.xls"); final List> read = reader.read(); for (List list : read) { Console.log(list.get(8)); } } + + @Test + public void mergeReadTest() { + final ExcelReader reader = ExcelUtil.getReader("merge_test.xlsx"); + final List> read = reader.read(); + // 验证合并单元格在两行中都可以取到值 + Assert.assertEquals(11L, read.get(1).get(2)); + Assert.assertEquals(11L, read.get(2).get(2)); + } } diff --git a/hutool-poi/src/test/resources/merge_test.xlsx b/hutool-poi/src/test/resources/merge_test.xlsx new file mode 100644 index 000000000..a6b335a5b Binary files /dev/null and b/hutool-poi/src/test/resources/merge_test.xlsx differ