fix sax read

This commit is contained in:
Looly 2019-09-27 21:12:30 +08:00
parent 4f811fc984
commit 3d8e01fe56
3 changed files with 205 additions and 153 deletions

View File

@ -6,66 +6,87 @@ import cn.hutool.core.util.PageUtil;
/**
* 分页数据结果集
* @author Looly
*
* @param <T> 结果集项的类型
* @author Looly
*/
public class PageResult<T> extends ArrayList<T>{
public class PageResult<T> extends ArrayList<T> {
private static final long serialVersionUID = 9056411043515781783L;
public static final int DEFAULT_PAGE_SIZE = Page.DEFAULT_PAGE_SIZE;
/** 页码 */
/**
* 页码
*/
private int page;
/** 每页结果数 */
/**
* 每页结果数
*/
private int pageSize;
/** 总页数 */
/**
* 总页数
*/
private int totalPage;
/** 总数 */
/**
* 总数
*/
private int total;
//---------------------------------------------------------- Constructor start
/**
* 构造
* @param page 页码
*/
public PageResult() {
this(0, DEFAULT_PAGE_SIZE);
}
/**
* 构造
*
* @param page 页码
* @param pageSize 每页结果数
*/
public PageResult(int page, int pageSize) {
super(pageSize <= 0 ? DEFAULT_PAGE_SIZE : pageSize);
this.page = page <= 0 ? 0 : page;
this.page = Math.max(page, 0);
this.pageSize = pageSize <= 0 ? DEFAULT_PAGE_SIZE : pageSize;
}
/**
* 构造
* @param page 页码
*
* @param page 页码
* @param pageSize 每页结果数
* @param total 结果总数
* @param total 结果总数
*/
public PageResult(int page, int pageSize, int total) {
this(page, pageSize);
this.total = total;
this.totalPage = PageUtil.totalPage(total,pageSize);
this.totalPage = PageUtil.totalPage(total, pageSize);
}
//---------------------------------------------------------- Constructor end
//---------------------------------------------------------- Getters and Setters start
/**
* @return 页码
*/
public int getPage() {
return page;
}
/**
* 设置页码
*
* @param page 页码
*/
public void setPage(int page) {
this.page = page;
}
/**
* @return 每页结果数
* @deprecated 请使用{@link #getPageSize()}
@ -74,8 +95,10 @@ public class PageResult<T> extends ArrayList<T>{
public int getNumPerPage() {
return pageSize;
}
/**
* 设置每页结果数
*
* @param pageSize 每页结果数
* @deprecated 请使用 {@link #setPageSize(int)}
*/
@ -83,57 +106,63 @@ public class PageResult<T> extends ArrayList<T>{
public void setNumPerPage(int pageSize) {
this.pageSize = pageSize;
}
/**
* @return 每页结果数
*/
public int getPageSize() {
return pageSize;
}
/**
* 设置每页结果数
*
* @param pageSize 每页结果数
*/
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
/**
* @return 总页数
*/
public int getTotalPage() {
return totalPage;
}
/**
* 设置总页数
*
* @param totalPage 总页数
*/
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
/**
* @return 总数
*/
public int getTotal() {
return total;
}
/**
* 设置总数
*
* @param total 总数
*/
public void setTotal(int total) {
this.total = total;
}
//---------------------------------------------------------- Getters and Setters end
/**
* @return 是否第一页
*/
public boolean isFirst(){
public boolean isFirst() {
return this.page == 0;
}
/**
* @return 是否最后一页
*/

View File

@ -6,6 +6,7 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import cn.hutool.core.util.ObjectUtil;
import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
@ -37,26 +38,35 @@ import cn.hutool.poi.exceptions.POIException;
/**
* Excel2003格式的事件-用户模型方式读取器在Hutool中统一将此归类为Sax读取<br>
* 参考http://www.cnblogs.com/wshsdlau/p/5643862.html
*
* @author looly
*
* @author looly
*/
public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> implements HSSFListener {
/** 如果为公式true表示输出公式计算后的结果值false表示输出公式本身 */
/**
* 如果为公式true表示输出公式计算后的结果值false表示输出公式本身
*/
private boolean isOutputFormulaValues = true;
/** 用于解析公式 */
/**
* 用于解析公式
*/
private SheetRecordCollectingListener workbookBuildingListener;
/** 子工作簿,用于公式计算 */
/**
* 子工作簿用于公式计算
*/
private HSSFWorkbook stubWorkbook;
/** 静态字符串表 */
/**
* 静态字符串表
*/
private SSTRecord sstRecord;
private FormatTrackingHSSFListener formatListener;
/** Sheet边界记录此Record中可以获得Sheet名 */
/**
* Sheet边界记录此Record中可以获得Sheet名
*/
private List<BoundSheetRecord> boundSheetRecords = new ArrayList<>();
private boolean isOutputNextStringRecord;
@ -64,7 +74,9 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
// 存储行记录的容器
private List<Object> rowCellList = new ArrayList<>();
/** 自定义需要处理的sheet编号如果-1表示处理所有sheet */
/**
* 自定义需要处理的sheet编号如果-1表示处理所有sheet
*/
private int rid = -1;
// 当前表索引
private int curRid = -1;
@ -73,7 +85,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
/**
* 构造
*
*
* @param rowHandler 行处理器
*/
public Excel03SaxReader(RowHandler rowHandler) {
@ -101,8 +113,8 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
/**
* 读取
*
* @param fs {@link POIFSFileSystem}
*
* @param fs {@link POIFSFileSystem}
* @param rid sheet序号
* @return this
* @throws POIException IO异常包装
@ -132,7 +144,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
/**
* 获得Sheet序号如果处理所有sheet获得最大的Sheet序号从0开始
*
*
* @return sheet序号
*/
public int getSheetIndex() {
@ -141,7 +153,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
/**
* 获得Sheet名如果处理所有sheet获得后一个Sheet名从0开始
*
*
* @return Sheet名
*/
public String getSheetName() {
@ -153,7 +165,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
/**
* HSSFListener 监听方法处理 Record
*
*
* @param record 记录
*/
@Override
@ -195,92 +207,92 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
}
// ---------------------------------------------------------------------------------------------- Private method start
/**
* 处理单元格值
*
*
* @param record 单元格
*/
private void processCellValue(Record record) {
Object value = null;
switch (record.getSid()) {
case BlankRecord.sid:
// 空白记录
BlankRecord brec = (BlankRecord) record;
rowCellList.add(brec.getColumn(), StrUtil.EMPTY);
break;
case BoolErrRecord.sid: // 布尔类型
BoolErrRecord berec = (BoolErrRecord) record;
rowCellList.add(berec.getColumn(), berec.getBooleanValue());
break;
case FormulaRecord.sid: // 公式类型
FormulaRecord frec = (FormulaRecord) record;
if (isOutputFormulaValues) {
if (Double.isNaN(frec.getValue())) {
// Formula result is a string
// This is stored in the next record
isOutputNextStringRecord = true;
} else {
value = formatListener.formatNumberDateCell(frec);
}
} else {
value = '"' + HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression()) + '"';
}
rowCellList.add(frec.getColumn(), value);
break;
case StringRecord.sid:// 单元格中公式的字符串
if (isOutputNextStringRecord) {
// String for formula
StringRecord srec = (StringRecord) record;
value = srec.getString();
isOutputNextStringRecord = false;
}
break;
case LabelRecord.sid:
LabelRecord lrec = (LabelRecord) record;
this.rowCellList.add(lrec.getColumn(), value);
break;
case LabelSSTRecord.sid: // 字符串类型
LabelSSTRecord lsrec = (LabelSSTRecord) record;
if (sstRecord == null) {
rowCellList.add(lsrec.getColumn(), StrUtil.EMPTY);
} else {
value = sstRecord.getString(lsrec.getSSTIndex()).toString();
rowCellList.add(lsrec.getColumn(), value);
}
break;
case NumberRecord.sid: // 数字类型
NumberRecord numrec = (NumberRecord) record;
final String formatString = formatListener.getFormatString(numrec);
if(formatString.contains(StrUtil.DOT)) {
//浮点数
value = numrec.getValue();
}else if(formatString.contains(StrUtil.SLASH) || formatString.contains(StrUtil.COLON)) {
//日期
value = formatListener.formatNumberDateCell(numrec);
}else {
double numValue = numrec.getValue();
final long longPart = (long) numValue;
// 对于无小数部分的数字类型转为Long否则保留原数字
if(longPart == numValue) {
value = longPart;
}else {
value = numValue;
}
}
// 向容器加入列值
rowCellList.add(numrec.getColumn(), value);
break;
default:
break;
switch (record.getSid()) {
case BlankRecord.sid:
// 空白记录
rowCellList.add(((BlankRecord) record).getColumn(), StrUtil.EMPTY);
break;
case BoolErrRecord.sid:
// 布尔类型
final BoolErrRecord berec = (BoolErrRecord) record;
rowCellList.add(berec.getColumn(), berec.getBooleanValue());
break;
case FormulaRecord.sid:
// 公式类型
FormulaRecord formulaRec = (FormulaRecord) record;
if (isOutputFormulaValues) {
if (Double.isNaN(formulaRec.getValue())) {
// Formula result is a string
// This is stored in the next record
isOutputNextStringRecord = true;
} else {
value = formatListener.formatNumberDateCell(formulaRec);
}
} else {
value = StrUtil.wrap(HSSFFormulaParser.toFormulaString(stubWorkbook, formulaRec.getParsedExpression()), "\"");
}
rowCellList.add(formulaRec.getColumn(), value);
break;
case StringRecord.sid:
// 单元格中公式的字符串
if (isOutputNextStringRecord) {
// String for formula
// value = ((StringRecord) record).getString();
isOutputNextStringRecord = false;
}
break;
case LabelRecord.sid:
final LabelRecord lrec = (LabelRecord) record;
value = lrec.getValue();
this.rowCellList.add(lrec.getColumn(), value);
break;
case LabelSSTRecord.sid:
// 字符串类型
LabelSSTRecord lsrec = (LabelSSTRecord) record;
if (null != sstRecord) {
value = sstRecord.getString(lsrec.getSSTIndex()).toString();
}
rowCellList.add(lsrec.getColumn(), ObjectUtil.defaultIfNull(value, StrUtil.EMPTY));
break;
case NumberRecord.sid: // 数字类型
final NumberRecord numrec = (NumberRecord) record;
final String formatString = formatListener.getFormatString(numrec);
if (formatString.contains(StrUtil.DOT)) {
//浮点数
value = numrec.getValue();
} else if (formatString.contains(StrUtil.SLASH) || formatString.contains(StrUtil.COLON)) {
//日期
value = formatListener.formatNumberDateCell(numrec);
} else {
final double doubleValue = numrec.getValue();
final long longPart = (long) doubleValue;
// 对于无小数部分的数字类型转为Long否则保留原数字
if (((double) longPart) == doubleValue) {
value = longPart;
} else {
value = doubleValue;
}
}
// 向容器加入列值
rowCellList.add(numrec.getColumn(), value);
break;
default:
break;
}
}
/**
* 处理行结束后的操作{@link LastCellOfRowDummyRecord}是行结束的标识Record
*
*
* @param lastCell 行结束的标识Record
*/
private void processLastCell(LastCellOfRowDummyRecord lastCell) {
@ -292,7 +304,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
/**
* 是否处理当前sheet
*
*
* @return 是否处理当前sheet
*/
private boolean isProcessCurrentSheet() {

View File

@ -31,24 +31,33 @@ import cn.hutool.poi.exceptions.POIException;
/**
* Sax方式读取Excel文件<br>
* Excel2007格式说明见http://www.cnblogs.com/wangmingshun/p/6654143.html
*
*
* @author Looly
* @since 3.1.2
*
*/
public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> implements ContentHandler {
// saxParser
private static final String CLASS_SAXPARSER = "org.apache.xerces.parsers.SAXParser";
/** Cell单元格元素 */
/**
* Cell单元格元素
*/
private static final String C_ELEMENT = "c";
/** 行元素 */
/**
* 行元素
*/
private static final String ROW_ELEMENT = "row";
/** Cell中的行列号 */
/**
* Cell中的行列号
*/
private static final String R_ATTR = "r";
/** Cell类型 */
/**
* Cell类型
*/
private static final String T_ELEMENT = "t";
/** SSTSharedStringsTable 的索引 */
/**
* SSTSharedStringsTable 的索引
*/
private static final String S_ATTR_VALUE = "s";
// 列中属性值
private static final String T_ATTR_VALUE = "t";
@ -73,9 +82,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
private String maxCellCoordinate;
// 单元格的格式表对应style.xml
private StylesTable stylesTable;
// 单元格存储格式的索引对应style.xml中的numFmts元素的子元素索引
private int numFmtIndex;
// 单元格存储的格式化字符串nmtFmt的formateCode属性的值
// 单元格存储的格式化字符串nmtFmt的formatCode属性的值
private String numFmtString;
// sheet的索引
private int sheetIndex;
@ -83,12 +90,14 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
// 存储每行的列元素
List<Object> rowCellList = new ArrayList<>();
/** 行处理器 */
/**
* 行处理器
*/
private RowHandler rowHandler;
/**
* 构造
*
*
* @param rowHandler 行处理器
*/
public Excel07SaxReader(RowHandler rowHandler) {
@ -97,7 +106,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
/**
* 设置行处理器
*
*
* @param rowHandler 行处理器
* @return this
*/
@ -129,9 +138,9 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
/**
* 开始读取ExcelSheet编号从0开始计数
*
*
* @param opcPackage {@link OPCPackage}Excel包
* @param rid Excel中的sheet rid编号如果为-1处理所有编号的sheet
* @param rid Excel中的sheet rid编号如果为-1处理所有编号的sheet
* @return this
* @throws POIException POI异常
*/
@ -178,7 +187,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
* 读到一个xml开始标签时的回调处理方法
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
public void startElement(String uri, String localName, String qName, Attributes attributes) {
// 单元格元素
if (C_ELEMENT.equals(qName)) {
@ -203,11 +212,12 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
/**
* 设置单元格的类型
*
* @param attribute
* @param attribute 属性
*/
private void setCellType(Attributes attribute) {
// 重置numFmtIndex,numFmtString的值
numFmtIndex = 0;
// 单元格存储格式的索引对应style.xml中的numFmts元素的子元素索引
int numFmtIndex;
// numFmtString的值
numFmtString = "";
this.cellDataType = CellDataType.of(attribute.getValue(T_ATTR_VALUE));
@ -232,13 +242,14 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
* 标签结束的回调处理方法
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
public void endElement(String uri, String localName, String qName) {
final String contentStr = StrUtil.trim(lastContent);
if (T_ELEMENT.equals(qName)) {
// type标签
// rowCellList.add(curCell++, contentStr);
} else if (C_ELEMENT.equals(qName)) {
// if (T_ELEMENT.equals(qName)) {
// // type标签
// // rowCellList.add(curCell++, contentStr);
// } else
if (C_ELEMENT.equals(qName)) {
// cell标签
Object value = ExcelSaxUtil.getDataValue(this.cellDataType, contentStr, this.sharedStringsTable, this.numFmtString);
// 补全单元格之间的空格
@ -259,8 +270,8 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
rowHandler.handle(sheetIndex, curRow, rowCellList);
// 一行结束
// 清空rowCellList,
rowCellList.clear();
// 新建一个新列之前的列抛弃可能被回收或rowHandler处理
rowCellList = new ArrayList<>(curCell + 1);
// 行数增加
curRow++;
// 当前列置0
@ -275,7 +286,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
* s标签结束的回调处理方法
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
public void characters(char[] ch, int start, int length) {
// 得到单元格内容的值
lastContent = lastContent.concat(new String(ch, start, length));
}
@ -290,47 +301,48 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
* ?xml标签的回调处理方法
*/
@Override
public void startDocument() throws SAXException {
public void startDocument() {
// pass
}
@Override
public void endDocument() throws SAXException {
public void endDocument() {
// pass
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
public void startPrefixMapping(String prefix, String uri) {
// pass
}
@Override
public void endPrefixMapping(String prefix) throws SAXException {
public void endPrefixMapping(String prefix) {
// pass
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
public void ignorableWhitespace(char[] ch, int start, int length) {
// pass
}
@Override
public void processingInstruction(String target, String data) throws SAXException {
public void processingInstruction(String target, String data) {
// pass
}
@Override
public void skippedEntity(String name) throws SAXException {
public void skippedEntity(String name) {
// pass
}
// --------------------------------------------------------------------------------------- Pass method end
// --------------------------------------------------------------------------------------- Private method start
/**
* 处理流中的Excel数据
*
*
* @param sheetInputStream sheet流
* @throws IOException IO异常
* @throws IOException IO异常
* @throws SAXException SAX异常
*/
private void parse(InputStream sheetInputStream) throws IOException, SAXException {
@ -342,7 +354,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
*
* @param preCoordinate 前一个单元格坐标
* @param curCoordinate 当前单元格坐标
* @param isEnd 是否为最后一个单元格
* @param isEnd 是否为最后一个单元格
*/
private void fillBlankCell(String preCoordinate, String curCoordinate, boolean isEnd) {
if (false == curCoordinate.equals(preCoordinate)) {
@ -359,12 +371,11 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
/**
* 获取sheet的解析器
*
* @param sharedStringsTable
* @return {@link XMLReader}
* @throws SAXException SAX异常
*/
private XMLReader fetchSheetReader() throws SAXException {
XMLReader xmlReader = null;
XMLReader xmlReader;
try {
xmlReader = XMLReaderFactory.createXMLReader(CLASS_SAXPARSER);
} catch (SAXException e) {