我编写的这个解析工具类有做单元格为空补全的功能,指定解析几个sheet页(有些Excel有隐藏的sheet页是不需要解析的)
调用代码:
XxsAnalysisImportExcel xxs = new XxsAnalysisImportExcel();
List<List<Map<String, Object>>> sheetData = new ArrayList<List<Map<String,Object>>>();
xxs.process(inputStream, sheetData,3);
//获取到解析的每个sheet页数据
List<Map<String, Object>> sheet0 = sheetData.get(0);
ObjectMapper map = new ObjectMapper();
//转换成业务VO
List baseInfo = map.convertValue(sheet0, new TypeReference<List>() {});
工具类:XxsAnalysisImportExcel.java
package com.qizhidao.ecloud.common.utils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.InputStream;
import java.util.*;
/**
-
导入Excel解析
-
@author tanle
-
@since 2019年3月1日
*/
public class XxsAnalysisImportExcel extends DefaultHandler{private Integer sheetIndex = 0;
private Integer curRow = 0;
private Integer curCol = 0;
//当前位置
private Integer preRef = 0;private boolean nextIsString = false;
private String lastContents = “”;
private SharedStringsTable sst;
//标题
List title = new ArrayList();//一行数据
Map<String, Object> obj = new HashMap<String, Object>();//业务数据
List<Map<String, Object>> paramData = new ArrayList<Map<String,Object>>();public void process(String filename,List<List<Map<String, Object>>> sheetData) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
this.sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
Iterator sheets = r.getSheetsData();
while(sheets.hasNext()) {
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
sheetIndex++;
sheetData.add(paramData);
paramData = new ArrayList<Map<String,Object>>();
curRow = 0;
title = new ArrayList();
}
}public void process(InputStream inputStream,List<List<Map<String, Object>>> sheetData) throws Exception {
OPCPackage pkg = OPCPackage.open(inputStream);
XSSFReader r = new XSSFReader( pkg );
this.sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
Iterator sheets = r.getSheetsData();
while(sheets.hasNext()) {
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
sheetIndex++;
sheetData.add(paramData);
paramData = new ArrayList<Map<String,Object>>();
curRow = 0;
title = new ArrayList();
}
}/**
- 在此添加类型注释
- @param inputStream Excel文件流
- @param sheetData 返回的数据,多个sheet页
- @param sheetNumber 解析几个sheet页的数据
- @throws Exception
*/
public void process(InputStream inputStream,List<List<Map<String, Object>>> sheetData,int sheetNumber) throws Exception {
OPCPackage pkg = OPCPackage.open(inputStream);
XSSFReader r = new XSSFReader( pkg );
this.sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
for (int i = 1; i <= sheetNumber; i++) {
InputStream sheet = r.getSheet(“rId”+i);
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
sheetIndex++;
sheetData.add(paramData);
paramData = new ArrayList<Map<String,Object>>();
curRow = 0;
title = new ArrayList();
}
}
public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
XMLReader parser = XMLReaderFactory.createXMLReader();
ContentHandler handler = this;
parser.setContentHandler(handler);
return parser;
}@Override
public void characters (char ch[], int start, int length) throws SAXException{
lastContents += new String(ch, start, length);
}
@Override
public void startElement(String uri, String localName, String name,Attributes attributes) throws SAXException {
if(name.equals(“c”)) {
String cellType = attributes.getValue(“t”);
curCol = this.getCellCoordinate(attributes.getValue(“r”));
if(cellType != null && cellType.equals(“s”)) {
nextIsString = true;
} else {
nextIsString = false;
}
}
lastContents = “”;
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(this.sst.getEntryAt(idx)).toString();
nextIsString = false;
}if (name.equals("v")) { String value = lastContents.trim(); //读取第一行数据,存储标题名称 if(curRow == 0) { //如果标题有空格不做补空处理,在读取到行尾的逻辑中做下判断如果有空的标题存在直接抛出异常 title.add(lastContents); } //从0开始,第三行数据开始保存业务数据 if(curRow > 1) { //补全规格,规格属性单元格之间的空单元格 if(preRef < curCol) { int leng = curCol - preRef; if(leng > 1) { for (int i = preRef; i < curCol; i++) { String titleName = title.get(i); obj.put(titleName, ""); } } } String titleName = title.get(curCol-1); obj.put(titleName, value); } preRef = curCol; }else { //如果标签名称为 row,这说明已到行尾,调用 optRows() 方法 if (name.equals("row")) { //从0开始,第三行数据开始保存业务数据 if(curRow > 1) { //如果规则属性内容数量不等于规则标题数量,证明尾部有空格,需补齐。 if(obj.size() > 0 && obj.size() < title.size()) { for (int i = obj.size(); i < title.size(); i++) { String titleName = title.get(i); obj.put(titleName, ""); } } } if(obj.size() > 0) { paramData.add(obj); } obj = new HashMap<String, Object>(); curRow++; curCol = 0; preRef = 0; } }
}
/**
- Excel列号转换成数字
- @author tanle
- @since 2019年1月23日
- @param column
- @return
*/
public Integer getCellCoordinate(String column) {
column = column.replaceAll("\d", “”);
int num = 0;
int result = 0;
int length =column.length();
for(int i = 0; i < length; i++) {
char ch = column.charAt(length - i - 1);
num = (int)(ch - ‘A’ + 1) ;
num *= Math.pow(26, i);
result += num;
}
return result;
}
}