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 】 修复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)

View File

@ -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异常包装
*/

View File

@ -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> {
* 开始读取ExcelSheet编号从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
}

View File

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

View File

@ -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);
}
}
}

View File

@ -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());
}