POI驱动SAX事件解析Excel功能

我编写的这个解析工具类有做单元格为空补全的功能,指定解析几个sheet页(有些Excel有隐藏的sheet页是不需要解析的)

调用代码:
XxsAnalysisImportExcel xxs = new XxsAnalysisImportExcel();
List>> sheetData = new ArrayList>>();
xxs.process(inputStream, sheetData,3);
//获取到解析的每个sheet页数据
List> sheet0 = sheetData.get(0);
ObjectMapper map = new ObjectMapper();
//转换成业务VO
List baseInfo = map.convertValue(sheet0, new TypeReference() {});

工具类: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 obj = new HashMap();

    //业务数据
    List> paramData = new ArrayList>();

    public void process(String filename,List>> 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>();
    curRow = 0;
    title = new ArrayList();
    }
    }

    public void process(InputStream inputStream,List>> 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>();
    curRow = 0;
    title = new ArrayList();
    }
    }

    /**

    • 在此添加类型注释
    • @param inputStream Excel文件流
    • @param sheetData 返回的数据,多个sheet页
    • @param sheetNumber 解析几个sheet页的数据
    • @throws Exception
      */
      public void process(InputStream inputStream,List>> 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>();
      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();
     		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;
      }

}

你可能感兴趣的:(POI驱动SAX事件解析Excel功能)