From ee5331f53ecaddb510147ee3c0840bfb59ad288c Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 04:31:46 +0800 Subject: [PATCH] fix #I2AOQW --- CHANGELOG.md | 2 +- .../poi/excel/sax/Excel03SaxReader.java | 2 +- .../poi/excel/sax/Excel07SaxReader.java | 45 +++++++--- .../poi/excel/sax/SheetDataSaxHandler.java | 2 +- .../hutool/poi/excel/sax/SheetRidReader.java | 89 ++++++++++++------- .../cn/hutool/poi/excel/ExcelSaxReadTest.java | 5 ++ 6 files changed, 97 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7a902235..532ada354 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ * 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题(issue#1332@Github) * 【core 】 修复RuntimeUtil.getUsableMemory非static问题(issue#I2AQ2M@Gitee) * 【core 】 修复ArrayUtil.equals方法严格判断问题(issue#I2AO8B@Gitee) -* 【core 】 修复SheetRidReader在获取rid时读取错误问题(issue#I2AOQW@Gitee) +* 【poi 】 修复SheetRidReader在获取rid时读取错误问题(issue#I2AOQW@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.5.4 (2020-12-16) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java index dbd97dd04..e64b43d3f 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java @@ -116,7 +116,7 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader { // sheet r:Id前缀 - private static final String RID_PREFIX = "rId"; + public static final String RID_PREFIX = "rId"; private final SheetDataSaxHandler handler; /** @@ -146,21 +145,13 @@ public class Excel07SaxReader implements ExcelSaxReader { * 开始读取Excel,Sheet编号从0开始计数 * * @param xssfReader {@link XSSFReader},Excel读取器 - * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @param idOrRid Excel中的sheet id或者rid编号,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 * @since 5.4.4 */ private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRid) throws POIException { - // 将sheetId转换为rid - if (NumberUtil.isInteger(idOrRid)) { - final SheetRidReader ridReader = new SheetRidReader(); - final String rid = ridReader.read(xssfReader).getRidBySheetId(idOrRid); - if (StrUtil.isNotEmpty(rid)) { - idOrRid = rid; - } - } - this.handler.sheetIndex = Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRid, RID_PREFIX)); + this.handler.sheetIndex = getSheetIndex(xssfReader, idOrRid); InputStream sheetInputStream = null; try { if (this.handler.sheetIndex > -1) { @@ -190,5 +181,35 @@ public class Excel07SaxReader implements ExcelSaxReader { } return this; } + + /** + * 获取sheet索引,从0开始 + *
    + *
  • 传入'rId'开头,直接去除rId前缀
  • + *
  • 传入纯数字,表示sheetIndex,通过{@link SheetRidReader}转换为rId
  • + *
+ * + * @param xssfReader {@link XSSFReader},Excel读取器 + * @param idOrRid Excel中的sheet id或者rid编号,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @return sheet索引,从0开始 + * @since 5.5.5 + */ + private int getSheetIndex(XSSFReader xssfReader, String idOrRid){ + // rid直接处理 + if(StrUtil.startWithIgnoreCase(idOrRid, RID_PREFIX)){ + return Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRid, RID_PREFIX)); + } + + // sheetIndex需转换为rid + final int sheetIndex = Integer.parseInt(idOrRid); + final SheetRidReader ridReader = new SheetRidReader(); + final Integer rid = ridReader.read(xssfReader).getRidBySheetIdBase0(sheetIndex); + + if(null != rid){ + return rid; + } + + return sheetIndex; + } // --------------------------------------------------------------------------------------- Private method end } \ No newline at end of file diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java index c703691e9..811e1f6cc 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java @@ -29,7 +29,7 @@ public class SheetDataSaxHandler extends DefaultHandler { protected StylesTable stylesTable; // excel 2007 的共享字符串表,对应sharedString.xml protected SharedStringsTable sharedStringsTable; - // sheet的索引 + // sheet的索引,从0开始 protected int sheetIndex; // 当前非空行 diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java index 918a1e937..56c744ec9 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java @@ -17,7 +17,7 @@ import java.util.Map; /** * 在Sax方式读取Excel时,读取sheet标签中sheetId和rid的对应关系,类似于: *
- * <sheet name="Sheet6" sheetId="4" r:id="6"/>
+ * <sheet name="Sheet6" sheetId="4" r:id="rId6"/>
  * 
*

* 读取结果为: @@ -36,8 +36,8 @@ public class SheetRidReader extends DefaultHandler { private final static String SHEET_ID_ATTR = "sheetId"; private final static String NAME_ATTR = "name"; - private final Map ID_RID_MAP = new HashMap<>(); - private final Map NAME_RID_MAP = new HashMap<>(); + private final Map ID_RID_MAP = new HashMap<>(); + private final Map NAME_RID_MAP = new HashMap<>(); /** * 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系 @@ -61,51 +61,74 @@ public class SheetRidReader extends DefaultHandler { } /** - * 根据sheetId获取rid + * 根据sheetId获取rid,从1开始 * - * @param sheetId Sheet的ID - * @return rid + * @param sheetId Sheet的ID,从1开始 + * @return rid,从1开始 */ - public String getRidBySheetId(String sheetId) { + public Integer getRidBySheetId(int sheetId) { return ID_RID_MAP.get(sheetId); } /** - * 根据sheet name获取rid + * 根据sheetId获取rid,从0开始 + * + * @param sheetId Sheet的ID,从0开始 + * @return rid,从0开始 + * @since 5.5.5 + */ + public Integer getRidBySheetIdBase0(int sheetId) { + final Integer rid = getRidBySheetId(sheetId + 1); + if(null != rid){ + return rid - 1; + } + return null; + } + + /** + * 根据sheet name获取rid,从1开始 * * @param sheetName Sheet的name - * @return rid + * @return rid,从1开始 */ - public String getRidByName(String sheetName) { + public Integer getRidByName(String sheetName) { return NAME_RID_MAP.get(sheetName); } + /** + * 根据sheet name获取rid,从0开始 + * + * @param sheetName Sheet的name + * @return rid,从0开始 + * @since 5.5.5 + */ + public Integer getRidByNameBase0(String sheetName) { + final Integer rid = getRidByName(sheetName); + if(null != rid){ + return rid - 1; + } + return null; + } + @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { if (TAG_NAME.equalsIgnoreCase(localName)) { - final int length = attributes.getLength(); - String sheetId = null; - String rid = null; - String name = null; - for (int i = 0; i < length; i++) { - final String attrName = attributes.getQName(i); - switch (attrName) { - case SHEET_ID_ATTR: - sheetId = attributes.getValue(i); - break; - case RID_ATTR: - rid = attributes.getValue(i); - break; - case NAME_ATTR: - name = attributes.getValue(i); - break; - } - if (StrUtil.isNotEmpty(sheetId)) { - ID_RID_MAP.put(sheetId, rid); - } - if (StrUtil.isNotEmpty(name)) { - NAME_RID_MAP.put(name, rid); - } + final String ridStr = attributes.getValue(SHEET_ID_ATTR); + if(StrUtil.isEmpty(ridStr)){ + return; + } + final int rid = Integer.parseInt(StrUtil.removePrefixIgnoreCase(ridStr, Excel07SaxReader.RID_PREFIX)); + + // sheet名和rid映射 + final String name = attributes.getValue(NAME_ATTR); + if (StrUtil.isNotEmpty(name)) { + NAME_RID_MAP.put(name, rid); + } + + // sheetId和rid映射 + final String sheetIdStr = attributes.getValue(SHEET_ID_ATTR); + if(StrUtil.isNotEmpty(sheetIdStr)){ + ID_RID_MAP.put(Integer.parseInt(sheetIdStr), rid); } } } diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java index 785eb2899..337b7a9c7 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java @@ -58,6 +58,11 @@ public class ExcelSaxReadTest { @Test public void readBySaxTest() { + ExcelUtil.readBySax("blankAndDateTest.xlsx", "0", createRowHandler()); + } + + @Test + public void readBySaxByRidTest() { ExcelUtil.readBySax("blankAndDateTest.xlsx", 0, createRowHandler()); }