3、2007及以上版本
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import com.base.infrastructure.log.LoggerManager;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
/**
 * 2007版本
 */
public class ExcelXlsxReader extends DefaultHandler {
    /**
     * 单元格中的数据可能的数据类型
     */
    enum CellDataType {
        BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
    }
    /**
     * 共享字符串表
     */
    private SharedStringsTable sst;
    /**
     * 上一次的索引值
     */
    private String lastIndex;
    /**
     * 文件的绝对路径
     */
    private String filePath = "";
    /**
     * 工作表索引
     */
    private int sheetIndex = 0;
    /**
     * sheet名
     */
    private String sheetName = "";
    /**
     * 总行数
     */
    private int totalRows = 0;
    /**
     * 一行内cell集合
     */
    private List cellList = new ArrayList();
    /**
     * 判断整行是否为空行的标记
     */
    private boolean flag = false;
    /**
     * 当前行
     */
    private int curRow = 1;
    /**
     * 前一个列
     */
    private int lastCurCol = -1;
    /**
     * 当前列
     */
    private int curCol = 0;
    //定义该文档一行最大的单元格数,用来补全一行最后可能缺失的单元格
    private int maxcurCol = 0;
    // 定义当前读到的列与上一次读到的列中是否有空值(即该单元格什么也没有输入,连空格都不存在)默认为false
    private boolean curflag = false;
    /**
     * T元素标识
     */
    private boolean isTElement;
    /**
     * 异常信息,如果为空则表示没有异常
     */
    private String exceptionMessage;
    /**
     * 单元格数据类型,默认为字符串类型
     */
    private CellDataType nextDataType = CellDataType.SSTINDEX;
    private final DataFormatter formatter = new DataFormatter();
    /**
     * 单元格日期格式的索引
     */
    private short formatIndex;
    /**
     * 日期格式字符串
     */
    private String formatString;
    //定义列名的行索引
    private int headerIncex = 1;
    //定义数据的行索引
    private int dataIndex = 2;
    /**
     * 单元格
     */
    private StylesTable stylesTable;
    /**
     * 根据文件路径解析
     *
     * @param path
     * @param headerIncex
     * @param dataIndex
     * @return
     * @throws Exception
     */
    public int process(String path, int headerIncex, int dataIndex)
            throws Exception {
        OPCPackage pkg = OPCPackage.open(path);
        return init(pkg, headerIncex, dataIndex);
    }
    /**
     * 根据文件流解析(占用内存消耗比文件路径解析大)
     *
     * @param inputStream
     * @param headerIncex
     * @param dataIndex
     * @return
     * @throws Exception
     */
    public int process(InputStream inputStream, int headerIncex, int dataIndex)
            throws Exception {
        OPCPackage pkg = OPCPackage.open(inputStream);
        return init(pkg, headerIncex, dataIndex);
    }
    /**
     * 遍历工作簿中所有的电子表格
     * 并缓存在mySheetList中
     *
     * @param pkg
     * @param headerIncex
     * @param dataIndex
     * @return
     * @throws Exception
     */
    private int init(OPCPackage pkg, int headerIncex, int dataIndex)
            throws Exception {
        XSSFReader xssfReader = new XSSFReader(pkg);
        stylesTable = xssfReader.getStylesTable();
        SharedStringsTable sst = xssfReader.getSharedStringsTable();
        XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
        this.sst = sst;
        parser.setContentHandler(this);
        XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
        while (sheets.hasNext()) { //遍历sheet
            curRow = 1; //标记初始行为第一行
            if (headerIncex > 0)
                this.headerIncex = headerIncex; //设置表头行
            if (dataIndex > 0)
                this.dataIndex = dataIndex; //设置数据行
            sheetIndex++;
            InputStream sheet = sheets.next(); //sheets.next()和sheets.getSheetName()不能换位置,否则sheetName报错
            sheetName = sheets.getSheetName();
            InputSource sheetSource = new InputSource(sheet);
            parser.parse(sheetSource); //解析excel的每条记录,在这个过程中startElement()、characters()、endElement()这三个函数会依次执行
            sheet.close();
        }
        pkg.close();
        return totalRows; //返回该excel文件的总行数,不包括首列和空行
    }
    /**
     * 第一个执行
     *
     * @param uri
     * @param localName
     * @param name
     * @param attributes
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes)
            throws SAXException {
        //c => 单元格
        if ("c".equals(name)) {
            //当前单元格的位置
            String r = attributes.getValue("r");
            int firstDigit = -1;
            for (int c = 0; c     
     
  
