Looly 5 年 前
コミット
ee5331f53e

+ 1 - 1
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)

+ 1 - 1
hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java

@@ -116,7 +116,7 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader<Excel03Sax
 	 * 读取
 	 *
 	 * @param fs  {@link POIFSFileSystem}
-	 * @param id sheet序号
+	 * @param id sheet序号,从0开始
 	 * @return this
 	 * @throws POIException IO异常包装
 	 */

+ 33 - 12
hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java

@@ -2,7 +2,6 @@ package cn.hutool.poi.excel.sax;
 
 import cn.hutool.core.io.IORuntimeException;
 import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.poi.excel.sax.handler.RowHandler;
 import cn.hutool.poi.exceptions.POIException;
@@ -26,7 +25,7 @@ import java.util.Iterator;
 public class Excel07SaxReader implements ExcelSaxReader<Excel07SaxReader> {
 
 	// 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<Excel07SaxReader> {
 	 * 开始读取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<Excel07SaxReader> {
 		}
 		return this;
 	}
+
+	/**
+	 * 获取sheet索引,从0开始
+	 * <ul>
+	 *     <li>传入'rId'开头,直接去除rId前缀</li>
+	 *     <li>传入纯数字,表示sheetIndex,通过{@link SheetRidReader}转换为rId</li>
+	 * </ul>
+	 *
+	 * @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
 }

+ 1 - 1
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;
 
 	// 当前非空行

+ 56 - 33
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的对应关系,类似于:
  * <pre>
- * &lt;sheet name="Sheet6" sheetId="4" r:id="6"/&gt;
+ * &lt;sheet name="Sheet6" sheetId="4" r:id="rId6"/&gt;
  * </pre>
  * <p>
  * 读取结果为:
@@ -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<String, String> ID_RID_MAP = new HashMap<>();
-	private final Map<String, String> NAME_RID_MAP = new HashMap<>();
+	private final Map<Integer, Integer> ID_RID_MAP = new HashMap<>();
+	private final Map<String, Integer> 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);
 			}
 		}
 	}

+ 5 - 0
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());
 	}