fix #I2AOQW

This commit is contained in:
Looly 2020-12-27 04:31:46 +08:00
parent 8e1b7d1fa8
commit ee5331f53e
6 changed files with 97 additions and 48 deletions

View File

@ -21,7 +21,7 @@
* 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题issue#1332@Github * 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题issue#1332@Github
* 【core 】 修复RuntimeUtil.getUsableMemory非static问题issue#I2AQ2M@Gitee * 【core 】 修复RuntimeUtil.getUsableMemory非static问题issue#I2AQ2M@Gitee
* 【core 】 修复ArrayUtil.equals方法严格判断问题issue#I2AO8B@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) # 5.5.4 (2020-12-16)

View File

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

View File

@ -2,7 +2,6 @@ package cn.hutool.poi.excel.sax;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.sax.handler.RowHandler; import cn.hutool.poi.excel.sax.handler.RowHandler;
import cn.hutool.poi.exceptions.POIException; import cn.hutool.poi.exceptions.POIException;
@ -26,7 +25,7 @@ import java.util.Iterator;
public class Excel07SaxReader implements ExcelSaxReader<Excel07SaxReader> { public class Excel07SaxReader implements ExcelSaxReader<Excel07SaxReader> {
// sheet r:Id前缀 // sheet r:Id前缀
private static final String RID_PREFIX = "rId"; public static final String RID_PREFIX = "rId";
private final SheetDataSaxHandler handler; private final SheetDataSaxHandler handler;
/** /**
@ -146,21 +145,13 @@ public class Excel07SaxReader implements ExcelSaxReader<Excel07SaxReader> {
* 开始读取ExcelSheet编号从0开始计数 * 开始读取ExcelSheet编号从0开始计数
* *
* @param xssfReader {@link XSSFReader}Excel读取器 * @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 * @return this
* @throws POIException POI异常 * @throws POIException POI异常
* @since 5.4.4 * @since 5.4.4
*/ */
private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRid) throws POIException { private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRid) throws POIException {
// 将sheetId转换为rid this.handler.sheetIndex = getSheetIndex(xssfReader, idOrRid);
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));
InputStream sheetInputStream = null; InputStream sheetInputStream = null;
try { try {
if (this.handler.sheetIndex > -1) { if (this.handler.sheetIndex > -1) {
@ -190,5 +181,35 @@ public class Excel07SaxReader implements ExcelSaxReader<Excel07SaxReader> {
} }
return this; 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 // --------------------------------------------------------------------------------------- Private method end
} }

View File

@ -29,7 +29,7 @@ public class SheetDataSaxHandler extends DefaultHandler {
protected StylesTable stylesTable; protected StylesTable stylesTable;
// excel 2007 的共享字符串表,对应sharedString.xml // excel 2007 的共享字符串表,对应sharedString.xml
protected SharedStringsTable sharedStringsTable; protected SharedStringsTable sharedStringsTable;
// sheet的索引 // sheet的索引从0开始
protected int sheetIndex; protected int sheetIndex;
// 当前非空行 // 当前非空行

View File

@ -17,7 +17,7 @@ import java.util.Map;
/** /**
* 在Sax方式读取Excel时读取sheet标签中sheetId和rid的对应关系类似于: * 在Sax方式读取Excel时读取sheet标签中sheetId和rid的对应关系类似于:
* <pre> * <pre>
* &lt;sheet name="Sheet6" sheetId="4" r:id="6"/&gt; * &lt;sheet name="Sheet6" sheetId="4" r:id="rId6"/&gt;
* </pre> * </pre>
* <p> * <p>
* 读取结果为 * 读取结果为
@ -36,8 +36,8 @@ public class SheetRidReader extends DefaultHandler {
private final static String SHEET_ID_ATTR = "sheetId"; private final static String SHEET_ID_ATTR = "sheetId";
private final static String NAME_ATTR = "name"; private final static String NAME_ATTR = "name";
private final Map<String, String> ID_RID_MAP = new HashMap<>(); private final Map<Integer, Integer> ID_RID_MAP = new HashMap<>();
private final Map<String, String> NAME_RID_MAP = new HashMap<>(); private final Map<String, Integer> NAME_RID_MAP = new HashMap<>();
/** /**
* 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系 * 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系
@ -61,51 +61,74 @@ public class SheetRidReader extends DefaultHandler {
} }
/** /**
* 根据sheetId获取rid * 根据sheetId获取rid从1开始
* *
* @param sheetId Sheet的ID * @param sheetId Sheet的ID从1开始
* @return rid * @return rid从1开始
*/ */
public String getRidBySheetId(String sheetId) { public Integer getRidBySheetId(int sheetId) {
return ID_RID_MAP.get(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 * @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); 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 @Override
public void startElement(String uri, String localName, String qName, Attributes attributes) { public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (TAG_NAME.equalsIgnoreCase(localName)) { if (TAG_NAME.equalsIgnoreCase(localName)) {
final int length = attributes.getLength(); final String ridStr = attributes.getValue(SHEET_ID_ATTR);
String sheetId = null; if(StrUtil.isEmpty(ridStr)){
String rid = null; return;
String name = null; }
for (int i = 0; i < length; i++) { final int rid = Integer.parseInt(StrUtil.removePrefixIgnoreCase(ridStr, Excel07SaxReader.RID_PREFIX));
final String attrName = attributes.getQName(i);
switch (attrName) { // sheet名和rid映射
case SHEET_ID_ATTR: final String name = attributes.getValue(NAME_ATTR);
sheetId = attributes.getValue(i); if (StrUtil.isNotEmpty(name)) {
break; NAME_RID_MAP.put(name, rid);
case RID_ATTR: }
rid = attributes.getValue(i);
break; // sheetId和rid映射
case NAME_ATTR: final String sheetIdStr = attributes.getValue(SHEET_ID_ATTR);
name = attributes.getValue(i); if(StrUtil.isNotEmpty(sheetIdStr)){
break; ID_RID_MAP.put(Integer.parseInt(sheetIdStr), rid);
}
if (StrUtil.isNotEmpty(sheetId)) {
ID_RID_MAP.put(sheetId, rid);
}
if (StrUtil.isNotEmpty(name)) {
NAME_RID_MAP.put(name, rid);
}
} }
} }
} }

View File

@ -58,6 +58,11 @@ public class ExcelSaxReadTest {
@Test @Test
public void readBySaxTest() { public void readBySaxTest() {
ExcelUtil.readBySax("blankAndDateTest.xlsx", "0", createRowHandler());
}
@Test
public void readBySaxByRidTest() {
ExcelUtil.readBySax("blankAndDateTest.xlsx", 0, createRowHandler()); ExcelUtil.readBySax("blankAndDateTest.xlsx", 0, createRowHandler());
} }