Poi使用sax解析xlsx

本文參考了
https://blog.csdn.net/sai739295732/article/details/68489403

https://blog.csdn.net/rainyspring4540/article/details/50747122
兩篇文章,感謝這兩篇文章的作者

maven

<!--poi -excel表格驅(qū)動(dòng)-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.10-FINAL</version>
 </dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.10-FINAL</version>
</dependency>
<!--SAX解析excel-->
<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>2.9.1</version>
</dependency>

解析工具代碼

package com.cignacmb.sms.common.util;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
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.Attributes;
import org.xml.sax.ContentHandler;
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;

public class SaxExcelUtils {
    private static List<Map<String,String>> dataListT;
    private final int startRow;
    private final int endRow;
    private int currentRow = 0;
    private final String filename;
    private static Map<String,String> map;
    static char[] strChar ;
    /**
     * 構(gòu)造方法
     */
    public SaxExcelUtils(String filename,int startRow,int endRow) throws Exception{
        dataListT = new ArrayList<>();
        if(StringUtils.isEmpty(filename)) throw new Exception("文件名不能空");
        this.filename = filename;
        this.startRow = startRow;
        this.endRow = endRow+1;
        processSheet();
    }
    /**
     * 指定獲取第一個(gè)sheet
     * @param filename
     * @throws Exception
     */
    private void processSheet() throws Exception {
        OPCPackage pkg = OPCPackage.open(filename);
        XSSFReader r = new XSSFReader( pkg );
        SharedStringsTable sst = r.getSharedStringsTable();
        XMLReader parser = fetchSheetParser(sst);
        Iterator<InputStream> it = r.getSheetsData();
        while(it.hasNext()){
            map = null;
            InputStream sheet1 = it.next();
            InputSource sheetSource = new InputSource(sheet1);
            parser.parse(sheetSource);
            sheet1.close();
        }
    }
    /**
     * 加載sax 解析器
     * @param sst
     * @return
     * @throws SAXException
     */
    private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
        XMLReader parser =
                XMLReaderFactory.createXMLReader(
                        "org.apache.xerces.parsers.SAXParser"
                );
        ContentHandler handler = new PagingHandler(sst);
        parser.setContentHandler(handler);
        return parser;
    }

    /**
     * See org.xml.sax.helpers.DefaultHandler javadocs
     */
    private  class PagingHandler extends DefaultHandler {
        private SharedStringsTable sst;
        private String lastContents;
        private boolean nextIsString;
        private String index = null;
        private PagingHandler(SharedStringsTable sst) {
            this.sst = sst;
        }
        /**
         * 開始元素 (獲取key 值)
         */
        @Override
        public void startElement(String uri, String localName, String name,
                                 Attributes attributes) throws SAXException {
            if(name.equals("c")) {
                index = attributes.getValue("r");
                //判斷是否是新的一行
                if(Pattern.compile("^A[0-9]+$").matcher(index).find()){
                    if(map!=null&&isAccess()&&!map.isEmpty()){
                        dataListT.add(map);
                    }
                    map = new LinkedHashMap<>();
                    currentRow++;
                }
                if(isAccess()){
                    String cellType = attributes.getValue("t");
                    if(cellType != null && cellType.equals("s")) {
                        nextIsString = true;
                    } else {
                        nextIsString = false;
                    }
                }
            }
            lastContents = "";
        }
        /**
         * 獲取value
         */
        @Override
        public void endElement(String uri, String localName, String name)
                throws SAXException {
            if(isAccess()){
                if(nextIsString) {
                    int idx = Integer.parseInt(lastContents);
                    lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
                    nextIsString = false;
                }
                if(name.equals("v")) {
                    map.put(index, lastContents);
                }
            }

        }
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            if(isAccess()){
                lastContents += new String(ch, start, length);
            }
        }
        @Override
        public void endDocument ()throws SAXException{
            if(map!=null&&isAccess()&&!map.isEmpty()){
                dataListT.add(map);
            }
        }

    }
    private boolean isAccess(){
        if(currentRow>=startRow&&startRow<=endRow){
            return true;
        }
        return false;
    }
    /**
     * 獲取數(shù)據(jù) 并且填補(bǔ)字段值為空的數(shù)據(jù)
     * @return
     * @throws Exception
     */
    public List<Map<String,String>> getMyDataList() throws Exception{
        List<Map<String,String>> list = dataListT.subList(startRow, dataListT.size());
        if(!list.isEmpty()){
            Map<String,String> map = dataListT.get(0);
            List<String> com = data("A",map.size()-1);
            for(int i=0;i<list.size();i++){
                Map<String,String> returnMap = list.get(i);
                for(String str:com){
                    boolean flag = true;
                    for(Entry<String,String> entry:returnMap.entrySet()){
                        if(entry.getKey().contains(str)){
                            //有
                            flag = false;
                            break;
                        }
                    }
                    if(flag){
                        //沒有
                        returnMap.put(str+(i+2), null);
                    }
                }
            }
        }
        return list;
    }


    /**
     * 封裝數(shù)據(jù)
     * @param str
     * @param counts
     * @return
     */
    public static List<String> data(String str,int counts){
        List<String> list = new ArrayList<>();
        list.add(str);
        for(int i=0;i<counts;i++){
            strChar = str.toCharArray();
            jinwei(0);
            str = new String(strChar);
            list.add(str);
        }
        return list;
    }
    //數(shù)字進(jìn)位
    public static void jinwei(int index){
        char a = 'A';
        int aint =(int)('A');
        if((strChar.length-1)-index>=0){
            int sc = (int)strChar[(strChar.length-1)-index];
            if(sc- 25 >= aint){
                jinwei(index+1);
                strChar[(strChar.length-1)-index] = a;
            }else{
                strChar[strChar.length-1-index] = (char)(sc+1);
            }
        }else{
            strChar[(strChar.length-1)-index+1] = a;
            StringBuilder str = new StringBuilder();
            str.append('A');
            str.append(strChar);
            strChar = str.toString().toCharArray();
        }
    }
}

快速獲取總行數(shù)

package com.cignacmb.sms.common.util;


import java.io.InputStream;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
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;


/**
 * XSSF and SAX (Event API) basic example.
 * See {@link XLSX2CSV} for a fuller example of doing
 *  XSLX processing with the XSSF Event code.
 */
public class MaxRowExcelUtil {
    //new add
    public long maxRow = 0;//記錄總行數(shù)

    private String filename = null;
    public MaxRowExcelUtil(String filename) throws Exception{
        if(StringUtils.isBlank(filename)) throw new Exception("文件名不能空");
        this.filename = filename;
        processFirstSheet();
    }
    /**
     * 指定獲取第一個(gè)sheet
     * @param filename
     * @throws Exception
     */
    private void processFirstSheet() throws Exception {
        OPCPackage pkg = OPCPackage.open(filename);
        XSSFReader r = new XSSFReader( pkg );
        SharedStringsTable sst = r.getSharedStringsTable();

        XMLReader parser = fetchSheetParser(sst);

        // To look up the Sheet Name / Sheet Order / rID,
        //  you need to process the core Workbook stream.
        // Normally it's of the form rId# or rSheet#
        InputStream sheet2 = r.getSheet("rId1");
        InputSource sheetSource = new InputSource(sheet2);
        parser.parse(sheetSource);
        sheet2.close();
    }

    private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
        XMLReader parser =
                XMLReaderFactory.createXMLReader(
                        "org.apache.xerces.parsers.SAXParser"
                );
        ContentHandler handler = new MaxRowHandler();
        parser.setContentHandler(handler);
        return parser;
    }

    /**
     * See org.xml.sax.helpers.DefaultHandler javadocs
     */
    private  class MaxRowHandler extends DefaultHandler {

        @Override
        public void startElement(String uri, String localName, String name,
                                 Attributes attributes) throws SAXException {
            // c => cell
            if(name.equals("c")) {
                String index = attributes.getValue("r");
                if(Pattern.compile("A[0-9]+$").matcher(index).find()){
                    maxRow++;
                }
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 自定義控件學(xué)習(xí) https://github.com/GcsSloop/AndroidNote/tree/mast...
    楷桐閱讀 637評(píng)論 0 5
  • 機(jī)緣巧合發(fā)現(xiàn)的一份資源,在此感謝原作者(不知道是哪位大神)的分享 自定義控件學(xué)習(xí)https://github.co...
    Smart_Arvin閱讀 1,373評(píng)論 0 20
  • 原創(chuàng)鏈接 一、Java面試題java有多重要,對(duì)于做android的我們,不需要多說了,let’s go (1)J...
    李福來閱讀 2,443評(píng)論 0 5
  • https://github.com/XinYiWorld/CZSuperAdapters 歡迎使用 https:...
    奈何心善閱讀 647評(píng)論 0 4
  • 釘釘(DingTalk)是阿里巴巴集團(tuán)于2014年1月籌劃啟動(dòng),由阿里巴巴團(tuán)隊(duì)打造,專注于提升中國企業(yè)的辦公與協(xié)同...
    _Sweet閱讀 1,276評(píng)論 1 1

友情鏈接更多精彩內(nèi)容