mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix bug
This commit is contained in:
parent
653ba7ff1d
commit
545c20912a
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
### 新特性
|
### 新特性
|
||||||
### Bug修复
|
### Bug修复
|
||||||
|
* 【core 】 修复CombinationAnnotationElement数组判断问题(issue#752@Github)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package cn.hutool.core.annotation;
|
package cn.hutool.core.annotation;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
@ -7,14 +9,12 @@ import java.lang.annotation.Inherited;
|
|||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组合注解 对JDK的原生注解机制做一个增强,支持类似Spring的组合注解。<br>
|
* 组合注解 对JDK的原生注解机制做一个增强,支持类似Spring的组合注解。<br>
|
||||||
* 核心实现使用了递归获取指定元素上的注解以及注解的注解,以实现复合注解的获取。
|
* 核心实现使用了递归获取指定元素上的注解以及注解的注解,以实现复合注解的获取。
|
||||||
@ -65,13 +65,13 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
|||||||
@Override
|
@Override
|
||||||
public Annotation[] getAnnotations() {
|
public Annotation[] getAnnotations() {
|
||||||
final Collection<Annotation> annotations = this.annotationMap.values();
|
final Collection<Annotation> annotations = this.annotationMap.values();
|
||||||
return annotations.toArray(new Annotation[annotations.size()]);
|
return annotations.toArray(new Annotation[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Annotation[] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
final Collection<Annotation> annotations = this.declaredAnnotationMap.values();
|
final Collection<Annotation> annotations = this.declaredAnnotationMap.values();
|
||||||
return annotations.toArray(new Annotation[annotations.size()]);
|
return annotations.toArray(new Annotation[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,7 +85,7 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
|||||||
parseDeclared(declaredAnnotations);
|
parseDeclared(declaredAnnotations);
|
||||||
|
|
||||||
final Annotation[] annotations = element.getAnnotations();
|
final Annotation[] annotations = element.getAnnotations();
|
||||||
if(ObjectUtil.equal(declaredAnnotations, annotations)) {
|
if(Arrays.equals(declaredAnnotations, annotations)) {
|
||||||
this.annotationMap = this.declaredAnnotationMap;
|
this.annotationMap = this.declaredAnnotationMap;
|
||||||
}else {
|
}else {
|
||||||
this.annotationMap = new HashMap<>();
|
this.annotationMap = new HashMap<>();
|
||||||
|
@ -2700,8 +2700,7 @@ public class ArrayUtil {
|
|||||||
* @since 3.0.9
|
* @since 3.0.9
|
||||||
*/
|
*/
|
||||||
public static <T> T[] toArray(Collection<T> collection, Class<T> componentType) {
|
public static <T> T[] toArray(Collection<T> collection, Class<T> componentType) {
|
||||||
final T[] array = newArray(componentType, collection.size());
|
return collection.toArray(newArray(componentType, 0));
|
||||||
return collection.toArray(array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------- remove
|
// ---------------------------------------------------------------------- remove
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package cn.hutool.core.util;
|
package cn.hutool.core.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Editor;
|
import cn.hutool.core.lang.Editor;
|
||||||
import cn.hutool.core.lang.Filter;
|
import cn.hutool.core.lang.Filter;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ArrayUtil} 数组工具单元测试
|
* {@link ArrayUtil} 数组工具单元测试
|
||||||
@ -20,8 +23,10 @@ public class ArrayUtilTest {
|
|||||||
Assert.assertTrue(ArrayUtil.isEmpty(a));
|
Assert.assertTrue(ArrayUtil.isEmpty(a));
|
||||||
Assert.assertTrue(ArrayUtil.isEmpty((Object) a));
|
Assert.assertTrue(ArrayUtil.isEmpty((Object) a));
|
||||||
int[] b = null;
|
int[] b = null;
|
||||||
|
//noinspection ConstantConditions
|
||||||
Assert.assertTrue(ArrayUtil.isEmpty(b));
|
Assert.assertTrue(ArrayUtil.isEmpty(b));
|
||||||
Object c = null;
|
Object c = null;
|
||||||
|
//noinspection ConstantConditions
|
||||||
Assert.assertTrue(ArrayUtil.isEmpty(c));
|
Assert.assertTrue(ArrayUtil.isEmpty(c));
|
||||||
|
|
||||||
Object d = new Object[]{"1", "2", 3, 4D};
|
Object d = new Object[]{"1", "2", 3, 4D};
|
||||||
@ -31,7 +36,9 @@ public class ArrayUtilTest {
|
|||||||
isEmpty = ArrayUtil.isEmpty(d);
|
isEmpty = ArrayUtil.isEmpty(d);
|
||||||
Assert.assertTrue(isEmpty);
|
Assert.assertTrue(isEmpty);
|
||||||
d = null;
|
d = null;
|
||||||
|
//noinspection ConstantConditions
|
||||||
isEmpty = ArrayUtil.isEmpty(d);
|
isEmpty = ArrayUtil.isEmpty(d);
|
||||||
|
//noinspection ConstantConditions
|
||||||
Assert.assertTrue(isEmpty);
|
Assert.assertTrue(isEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +124,7 @@ public class ArrayUtilTest {
|
|||||||
String[] keys = {"a", "b", "c"};
|
String[] keys = {"a", "b", "c"};
|
||||||
Integer[] values = {1, 2, 3};
|
Integer[] values = {1, 2, 3};
|
||||||
Map<String, Integer> map = ArrayUtil.zip(keys, values, true);
|
Map<String, Integer> map = ArrayUtil.zip(keys, values, true);
|
||||||
Assert.assertEquals(map.toString(), "{a=1, b=2, c=3}");
|
Assert.assertEquals(Objects.requireNonNull(map).toString(), "{a=1, b=2, c=3}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -248,4 +255,14 @@ public class ArrayUtilTest {
|
|||||||
String[] array = {"aa", "bb", "cc", "dd", "bb", "dd"};
|
String[] array = {"aa", "bb", "cc", "dd", "bb", "dd"};
|
||||||
Assert.assertEquals("[aa, bb, cc, dd, bb, dd]", ArrayUtil.toString(array));
|
Assert.assertEquals("[aa, bb, cc, dd, bb, dd]", ArrayUtil.toString(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toArrayTest(){
|
||||||
|
final ArrayList<String> list = CollUtil.newArrayList("A", "B", "C", "D");
|
||||||
|
final String[] array = ArrayUtil.toArray(list, String.class);
|
||||||
|
Assert.assertEquals("A", array[0]);
|
||||||
|
Assert.assertEquals("B", array[1]);
|
||||||
|
Assert.assertEquals("C", array[2]);
|
||||||
|
Assert.assertEquals("D", array[3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,8 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- versions -->
|
<!-- versions -->
|
||||||
<poi.version>4.1.1</poi.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<xerces.version>2.12.0</xerces.version>
|
<xerces.version>2.12.0</xerces.version>
|
||||||
<easyexcel.version>2.1.6</easyexcel.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -49,12 +48,5 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba</groupId>
|
|
||||||
<artifactId>easyexcel</artifactId>
|
|
||||||
<version>${easyexcel.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cn.hutool.poi.excel.sax;
|
package cn.hutool.poi.excel.sax;
|
||||||
|
|
||||||
import cn.hutool.core.exceptions.DependencyException;
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
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;
|
||||||
@ -13,14 +12,9 @@ import org.apache.poi.xssf.model.StylesTable;
|
|||||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
import org.xml.sax.ContentHandler;
|
import org.xml.sax.ContentHandler;
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
import org.xml.sax.Locator;
|
import org.xml.sax.Locator;
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
import org.xml.sax.XMLReader;
|
|
||||||
import org.xml.sax.helpers.XMLReaderFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -35,8 +29,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> implements ContentHandler {
|
public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> implements ContentHandler {
|
||||||
|
|
||||||
// saxParser
|
|
||||||
private static final String CLASS_SAXPARSER = "org.apache.xerces.parsers.SAXParser";
|
|
||||||
/**
|
/**
|
||||||
* Cell单元格元素
|
* Cell单元格元素
|
||||||
*/
|
*/
|
||||||
@ -46,7 +38,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
*/
|
*/
|
||||||
private static final String ROW_ELEMENT = "row";
|
private static final String ROW_ELEMENT = "row";
|
||||||
/**
|
/**
|
||||||
* Cell中的行列号
|
* Cell中的行列号(Reference),行模式下此为行号属性名,列模式下为列号属性名
|
||||||
*/
|
*/
|
||||||
private static final String R_ATTR = "r";
|
private static final String R_ATTR = "r";
|
||||||
/**
|
/**
|
||||||
@ -54,7 +46,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
*/
|
*/
|
||||||
private static final String T_ELEMENT = "t";
|
private static final String T_ELEMENT = "t";
|
||||||
/**
|
/**
|
||||||
* SST(SharedStringsTable) 的索引
|
* SST(SharedStringsTable) 的索引,样式index
|
||||||
*/
|
*/
|
||||||
private static final String S_ATTR_VALUE = "s";
|
private static final String S_ATTR_VALUE = "s";
|
||||||
// 列中属性值
|
// 列中属性值
|
||||||
@ -69,7 +61,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
// 当前列
|
// 当前列
|
||||||
private int curCell;
|
private int curCell;
|
||||||
// 上一次的内容
|
// 上一次的内容
|
||||||
private String lastContent;
|
private StringBuilder lastContent = new StringBuilder(64);
|
||||||
// 单元数据类型
|
// 单元数据类型
|
||||||
private CellDataType cellDataType;
|
private CellDataType cellDataType;
|
||||||
// 当前列坐标, 如A1,B5
|
// 当前列坐标, 如A1,B5
|
||||||
@ -160,7 +152,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
this.sheetIndex = rid;
|
this.sheetIndex = rid;
|
||||||
// 根据 rId# 或 rSheet# 查找sheet
|
// 根据 rId# 或 rSheet# 查找sheet
|
||||||
sheetInputStream = xssfReader.getSheet(RID_PREFIX + (rid + 1));
|
sheetInputStream = xssfReader.getSheet(RID_PREFIX + (rid + 1));
|
||||||
parse(sheetInputStream);
|
ExcelSaxUtil.readFrom(sheetInputStream, this);
|
||||||
} else {
|
} else {
|
||||||
this.sheetIndex = -1;
|
this.sheetIndex = -1;
|
||||||
// 遍历所有sheet
|
// 遍历所有sheet
|
||||||
@ -170,7 +162,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
curRow = 0;
|
curRow = 0;
|
||||||
this.sheetIndex++;
|
this.sheetIndex++;
|
||||||
sheetInputStream = sheetInputStreams.next();
|
sheetInputStream = sheetInputStreams.next();
|
||||||
parse(sheetInputStream);
|
ExcelSaxUtil.readFrom(sheetInputStream, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
@ -191,8 +183,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
@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 (C_ELEMENT.equals(qName)) {
|
if (C_ELEMENT.equals(localName)) {
|
||||||
|
|
||||||
// 获取当前列坐标
|
// 获取当前列坐标
|
||||||
String tempCurCoordinate = attributes.getValue(R_ATTR);
|
String tempCurCoordinate = attributes.getValue(R_ATTR);
|
||||||
// 前一列为null,则将其设置为"@",A为第一列,ascii码为65,前一列即为@,ascii码64
|
// 前一列为null,则将其设置为"@",A为第一列,ascii码为65,前一列即为@,ascii码64
|
||||||
@ -208,38 +199,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
setCellType(attributes);
|
setCellType(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastContent = "";
|
lastContent.setLength(0);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置单元格的类型
|
|
||||||
*
|
|
||||||
* @param attribute 属性
|
|
||||||
*/
|
|
||||||
private void setCellType(Attributes attribute) {
|
|
||||||
// 单元格存储格式的索引,对应style.xml中的numFmts元素的子元素索引
|
|
||||||
int numFmtIndex;
|
|
||||||
// numFmtString的值
|
|
||||||
numFmtString = "";
|
|
||||||
this.cellDataType = CellDataType.of(attribute.getValue(T_ATTR_VALUE));
|
|
||||||
|
|
||||||
// 获取单元格的xf索引,对应style.xml中cellXfs的子元素xf
|
|
||||||
if(null != this.stylesTable){
|
|
||||||
final String xfIndexStr = attribute.getValue(S_ATTR_VALUE);
|
|
||||||
if (null != xfIndexStr) {
|
|
||||||
int xfIndex = Integer.parseInt(xfIndexStr);
|
|
||||||
XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(xfIndex);
|
|
||||||
numFmtIndex = xssfCellStyle.getDataFormat();
|
|
||||||
numFmtString = xssfCellStyle.getDataFormatString();
|
|
||||||
|
|
||||||
if (numFmtString == null) {
|
|
||||||
numFmtString = BuiltinFormats.getBuiltinFormat(numFmtIndex);
|
|
||||||
} else if (CellDataType.NUMBER == this.cellDataType && org.apache.poi.ss.usermodel.DateUtil.isADateFormat(numFmtIndex, numFmtString)) {
|
|
||||||
cellDataType = CellDataType.DATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,13 +213,13 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
// // type标签
|
// // type标签
|
||||||
// // rowCellList.add(curCell++, contentStr);
|
// // rowCellList.add(curCell++, contentStr);
|
||||||
// } else
|
// } else
|
||||||
if (C_ELEMENT.equals(qName)) {
|
if (C_ELEMENT.equals(localName)) {
|
||||||
// cell标签
|
// cell标签
|
||||||
Object value = ExcelSaxUtil.getDataValue(this.cellDataType, contentStr, this.sharedStringsTable, this.numFmtString);
|
Object value = ExcelSaxUtil.getDataValue(this.cellDataType, contentStr, this.sharedStringsTable, this.numFmtString);
|
||||||
// 补全单元格之间的空格
|
// 补全单元格之间的空格
|
||||||
fillBlankCell(preCoordinate, curCoordinate, false);
|
fillBlankCell(preCoordinate, curCoordinate, false);
|
||||||
rowCellList.add(curCell++, value);
|
rowCellList.add(curCell++, value);
|
||||||
} else if (ROW_ELEMENT.equals(qName)) {
|
} else if (ROW_ELEMENT.equals(localName)) {
|
||||||
// 如果是row标签,说明已经到了一行的结尾
|
// 如果是row标签,说明已经到了一行的结尾
|
||||||
// 最大列坐标以第一行的为准
|
// 最大列坐标以第一行的为准
|
||||||
if (curRow == 0) {
|
if (curRow == 0) {
|
||||||
@ -292,7 +252,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
@Override
|
@Override
|
||||||
public void characters(char[] ch, int start, int length) {
|
public void characters(char[] ch, int start, int length) {
|
||||||
// 得到单元格内容的值
|
// 得到单元格内容的值
|
||||||
lastContent = lastContent.concat(new String(ch, start, length));
|
lastContent.append(ch, start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------- Pass method start
|
// --------------------------------------------------------------------------------------- Pass method start
|
||||||
@ -341,18 +301,6 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
// --------------------------------------------------------------------------------------- Pass method end
|
// --------------------------------------------------------------------------------------- Pass method end
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------- Private method start
|
// --------------------------------------------------------------------------------------- Private method start
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理流中的Excel数据
|
|
||||||
*
|
|
||||||
* @param sheetInputStream sheet流
|
|
||||||
* @throws IOException IO异常
|
|
||||||
* @throws SAXException SAX异常
|
|
||||||
*/
|
|
||||||
private void parse(InputStream sheetInputStream) throws IOException, SAXException {
|
|
||||||
fetchSheetReader().parse(new InputSource(sheetInputStream));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 填充空白单元格,如果前一个单元格大于后一个,不需要填充<br>
|
* 填充空白单元格,如果前一个单元格大于后一个,不需要填充<br>
|
||||||
*
|
*
|
||||||
@ -373,24 +321,32 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取sheet的解析器
|
* 设置单元格的类型
|
||||||
*
|
*
|
||||||
* @return {@link XMLReader}
|
* @param attribute 属性
|
||||||
* @throws SAXException SAX异常
|
|
||||||
*/
|
*/
|
||||||
private XMLReader fetchSheetReader() throws SAXException {
|
private void setCellType(Attributes attribute) {
|
||||||
XMLReader xmlReader;
|
// numFmtString的值
|
||||||
try {
|
numFmtString = "";
|
||||||
xmlReader = XMLReaderFactory.createXMLReader(CLASS_SAXPARSER);
|
this.cellDataType = CellDataType.of(attribute.getValue(T_ATTR_VALUE));
|
||||||
} catch (SAXException e) {
|
|
||||||
if (e.getMessage().contains("org.apache.xerces.parsers.SAXParser")) {
|
// 获取单元格的xf索引,对应style.xml中cellXfs的子元素xf
|
||||||
throw new DependencyException(e, "You need to add 'xerces:xercesImpl' to your project and version >= 2.11.0");
|
if(null != this.stylesTable){
|
||||||
} else {
|
final String xfIndexStr = attribute.getValue(S_ATTR_VALUE);
|
||||||
throw e;
|
if (null != xfIndexStr) {
|
||||||
|
int xfIndex = Integer.parseInt(xfIndexStr);
|
||||||
|
final XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(xfIndex);
|
||||||
|
numFmtString = xssfCellStyle.getDataFormatString();
|
||||||
|
// 单元格存储格式的索引,对应style.xml中的numFmts元素的子元素索引
|
||||||
|
int numFmtIndex = xssfCellStyle.getDataFormat();
|
||||||
|
if (numFmtString == null) {
|
||||||
|
numFmtString = BuiltinFormats.getBuiltinFormat(numFmtIndex);
|
||||||
|
} else if (CellDataType.NUMBER == this.cellDataType && org.apache.poi.ss.usermodel.DateUtil.isADateFormat(numFmtIndex, numFmtString)) {
|
||||||
|
cellDataType = CellDataType.DATE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlReader.setContentHandler(this);
|
|
||||||
return xmlReader;
|
|
||||||
}
|
}
|
||||||
// --------------------------------------------------------------------------------------- Private method end
|
// --------------------------------------------------------------------------------------- Private method end
|
||||||
}
|
}
|
@ -1,18 +1,28 @@
|
|||||||
package cn.hutool.poi.excel.sax;
|
package cn.hutool.poi.excel.sax;
|
||||||
|
|
||||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
|
||||||
import org.apache.poi.xssf.model.SharedStringsTable;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
|
||||||
|
|
||||||
import cn.hutool.core.date.DateTime;
|
import cn.hutool.core.date.DateTime;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.exceptions.DependencyException;
|
||||||
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.poi.exceptions.POIException;
|
||||||
|
import org.apache.poi.ooxml.util.SAXHelper;
|
||||||
|
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||||
|
import org.apache.poi.xssf.model.SharedStringsTable;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||||
|
import org.xml.sax.ContentHandler;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.XMLReader;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sax方式读取Excel相关工具类
|
* Sax方式读取Excel相关工具类
|
||||||
*
|
|
||||||
* @author looly
|
|
||||||
*
|
*
|
||||||
|
* @author looly
|
||||||
*/
|
*/
|
||||||
public class ExcelSaxUtil {
|
public class ExcelSaxUtil {
|
||||||
|
|
||||||
@ -23,67 +33,67 @@ public class ExcelSaxUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据数据类型获取数据
|
* 根据数据类型获取数据
|
||||||
*
|
*
|
||||||
* @param cellDataType 数据类型枚举
|
* @param cellDataType 数据类型枚举
|
||||||
* @param value 数据值
|
* @param value 数据值
|
||||||
* @param sharedStringsTable {@link SharedStringsTable}
|
* @param sharedStringsTable {@link SharedStringsTable}
|
||||||
* @param numFmtString 数字格式名
|
* @param numFmtString 数字格式名
|
||||||
* @return 数据值
|
* @return 数据值
|
||||||
*/
|
*/
|
||||||
public static Object getDataValue(CellDataType cellDataType, String value, SharedStringsTable sharedStringsTable, String numFmtString) {
|
public static Object getDataValue(CellDataType cellDataType, String value, SharedStringsTable sharedStringsTable, String numFmtString) {
|
||||||
if (null == value) {
|
if (null == value) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(null == cellDataType) {
|
if (null == cellDataType) {
|
||||||
cellDataType = CellDataType.NULL;
|
cellDataType = CellDataType.NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object result;
|
Object result;
|
||||||
switch (cellDataType) {
|
switch (cellDataType) {
|
||||||
case BOOL:
|
case BOOL:
|
||||||
result = (value.charAt(0) != '0');
|
result = (value.charAt(0) != '0');
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
result = StrUtil.format("\\\"ERROR: {} ", value);
|
result = StrUtil.format("\\\"ERROR: {} ", value);
|
||||||
break;
|
break;
|
||||||
case FORMULA:
|
case FORMULA:
|
||||||
result = StrUtil.format("\"{}\"", value);
|
result = StrUtil.format("\"{}\"", value);
|
||||||
break;
|
break;
|
||||||
case INLINESTR:
|
case INLINESTR:
|
||||||
result = new XSSFRichTextString(value).toString();
|
result = new XSSFRichTextString(value).toString();
|
||||||
break;
|
break;
|
||||||
case SSTINDEX:
|
case SSTINDEX:
|
||||||
try {
|
try {
|
||||||
final int index = Integer.parseInt(value);
|
final int index = Integer.parseInt(value);
|
||||||
//noinspection deprecation
|
//noinspection deprecation
|
||||||
result = new XSSFRichTextString(sharedStringsTable.getEntryAt(index)).getString();
|
result = new XSSFRichTextString(sharedStringsTable.getEntryAt(index)).getString();
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
result = value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NUMBER:
|
||||||
|
result = getNumberValue(value, numFmtString);
|
||||||
|
break;
|
||||||
|
case DATE:
|
||||||
|
try {
|
||||||
|
result = getDateValue(value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result = value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
result = value;
|
result = value;
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
case NUMBER:
|
|
||||||
result = getNumberValue(value, numFmtString);
|
|
||||||
break;
|
|
||||||
case DATE:
|
|
||||||
try {
|
|
||||||
result = getDateValue(value);
|
|
||||||
} catch (Exception e) {
|
|
||||||
result = value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
result = value;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化数字或日期值
|
* 格式化数字或日期值
|
||||||
*
|
*
|
||||||
* @param value 值
|
* @param value 值
|
||||||
* @param numFmtIndex 数字格式索引
|
* @param numFmtIndex 数字格式索引
|
||||||
* @param numFmtString 数字格式名
|
* @param numFmtString 数字格式名
|
||||||
* @return 格式化后的值
|
* @return 格式化后的值
|
||||||
*/
|
*/
|
||||||
@ -100,9 +110,9 @@ public class ExcelSaxUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算两个单元格之间的单元格数目(同一行)
|
* 计算两个单元格之间的单元格数目(同一行)
|
||||||
*
|
*
|
||||||
* @param preRef 前一个单元格位置,例如A1
|
* @param preRef 前一个单元格位置,例如A1
|
||||||
* @param ref 当前单元格位置,例如A8
|
* @param ref 当前单元格位置,例如A8
|
||||||
* @return 同一行中两个单元格之间的空单元格数
|
* @return 同一行中两个单元格之间的空单元格数
|
||||||
*/
|
*/
|
||||||
public static int countNullCell(String preRef, String ref) {
|
public static int countNullCell(String preRef, String ref) {
|
||||||
@ -123,9 +133,41 @@ public class ExcelSaxUtil {
|
|||||||
return res - 1;
|
return res - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从Excel的XML文档中读取内容,并使用{@link ContentHandler}处理
|
||||||
|
*
|
||||||
|
* @param xmlDocStream Excel的XML文档流
|
||||||
|
* @param handler 文档内容处理接口,实现此接口用于回调处理数据
|
||||||
|
* @throws DependencyException 依赖异常
|
||||||
|
* @throws POIException POI异常,包装了SAXException
|
||||||
|
* @throws IORuntimeException IO异常,如流关闭或异常等
|
||||||
|
* @since 5.1.4
|
||||||
|
*/
|
||||||
|
public static void readFrom(InputStream xmlDocStream, ContentHandler handler) throws DependencyException, POIException, IORuntimeException {
|
||||||
|
XMLReader xmlReader;
|
||||||
|
try {
|
||||||
|
//noinspection deprecation
|
||||||
|
xmlReader = SAXHelper.newXMLReader();
|
||||||
|
} catch (SAXException | ParserConfigurationException e) {
|
||||||
|
if (e.getMessage().contains("org.apache.xerces.parsers.SAXParser")) {
|
||||||
|
throw new DependencyException(e, "You need to add 'xerces:xercesImpl' to your project and version >= 2.11.0");
|
||||||
|
} else {
|
||||||
|
throw new POIException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlReader.setContentHandler(handler);
|
||||||
|
try {
|
||||||
|
xmlReader.parse(new InputSource(xmlDocStream));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IORuntimeException(e);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
throw new POIException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取日期
|
* 获取日期
|
||||||
*
|
*
|
||||||
* @param value 单元格值
|
* @param value 单元格值
|
||||||
* @return 日期
|
* @return 日期
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
@ -136,14 +178,14 @@ public class ExcelSaxUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取数字类型值
|
* 获取数字类型值
|
||||||
*
|
*
|
||||||
* @param value 值
|
* @param value 值
|
||||||
* @param numFmtString 格式
|
* @param numFmtString 格式
|
||||||
* @return 数字,可以是Double、Long
|
* @return 数字,可以是Double、Long
|
||||||
* @since 4.1.0
|
* @since 4.1.0
|
||||||
*/
|
*/
|
||||||
private static Number getNumberValue(String value, String numFmtString) {
|
private static Number getNumberValue(String value, String numFmtString) {
|
||||||
if(StrUtil.isBlank(value)) {
|
if (StrUtil.isBlank(value)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
double numValue = Double.parseDouble(value);
|
double numValue = Double.parseDouble(value);
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
package cn.hutool.poi.excel.test;
|
package cn.hutool.poi.excel.test;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.lang.Console;
|
import cn.hutool.core.lang.Console;
|
||||||
@ -13,6 +7,9 @@ import cn.hutool.core.util.StrUtil;
|
|||||||
import cn.hutool.poi.excel.ExcelUtil;
|
import cn.hutool.poi.excel.ExcelUtil;
|
||||||
import cn.hutool.poi.excel.sax.Excel03SaxReader;
|
import cn.hutool.poi.excel.sax.Excel03SaxReader;
|
||||||
import cn.hutool.poi.excel.sax.handler.RowHandler;
|
import cn.hutool.poi.excel.sax.handler.RowHandler;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel sax方式读取
|
* Excel sax方式读取
|
||||||
|
Loading…
x
Reference in New Issue
Block a user