6、poi eventUserModel快速读取数据

apache官方的链接,看了几遍还是觉得很模糊,如果有相关的资料,请推荐一下。
https://poi.apache.org/spreadsheet/examples.html
https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/eventusermodel/XLSX2CSV.java
https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java
xls和xlsx在usermodel下可以用同一套代码处理,eventUserModel好像不行。不过速度真的很快,2,3 秒就可以处理300多条数据。
处理xlsx如下:

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
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;  
  
/** 
 * 使用CVS模式解决XLSX文件,可以有效解决用户模式内存溢出的问题 
 * 该模式是POI官方推荐的读取大数据的模式,在用户模式下,数据量较大、Sheet较多、或者是有很多无用的空行的情况 
 * ,容易出现内存溢出,用户模式读取Excel的典型代码如下: FileInputStream file=new 
 * FileInputStream("c:\\test.xlsx"); Workbook wb=new XSSFWorkbook(file); 
 *  
 *  
 */  
public class XLSXCovertCSVReader {  
  
    /** 
     * The type of the data value is indicated by an attribute on the cell. The 
     * value is usually in a "v" element within the cell. 
     */  
    enum xssfDataType {  
        BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER,  
    }  
  
    /** 
     * 使用xssf_sax_API处理Excel,请参考: http://poi.apache.org/spreadsheet/how-to.html#xssf_sax_api 
     * <p/> 
     * Also see Standard ECMA-376, 1st edition, part 4, pages 1928ff, at 
     * http://www.ecma-international.org/publications/standards/Ecma-376.htm 
     * <p/> 
     * A web-friendly version is http://openiso.org/Ecma/376/Part4 
     */  
    class MyXSSFSheetHandler extends DefaultHandler {  
//      private XSSFFormulaEvaluator evaluator;

        
        /** 
         * Table with styles 
         */  
        private StylesTable stylesTable;  
  
        /** 
         * Table with unique strings 
         */  
        private ReadOnlySharedStringsTable sharedStringsTable;  
  
        /** 
         * Destination for data 
         */  
        private final PrintStream output;  
  
        /** 
         * Number of columns to read starting with leftmost 
         */  
        private final int minColumnCount;  
  
        // Set when V start element is seen  
        private boolean vIsOpen;  
  
        // Set when cell start element is seen;  
        // used when cell close element is seen.  
        private xssfDataType nextDataType;  
  
        // Used to format numeric cell values.  
        private short formatIndex;  
        private String formatString;  
        private final DataFormatter formatter;  
  
        private int thisColumn = -1;   // 当前列
        private int requireHeadColumn = 99;  // 需求标题所在列
        private int exTaskHead = 99;  //任务标题所在列
        private List<String> nullRowList;   // 包含"需求标题", "任务标题"
        
        // The last column printed to the output stream  
        private int lastColumnNumber = -1;  
  
        // Gathers characters as they are seen.  
        private StringBuffer value;  
        private String[] record;  
        private List<String[]> rows = new ArrayList<String[]>();  
        private boolean isCellNull = false;  
  
        /** 
         * Accepts objects needed while parsing. 
         *  
         * @param styles 
         *            Table of styles 
         * @param strings 
         *            Table of shared strings 
         * @param cols 
         *            Minimum number of columns to show 
         * @param target 
         *            Sink for output 
         */  
        public MyXSSFSheetHandler(StylesTable styles,  
                ReadOnlySharedStringsTable strings, int cols, PrintStream target, List<String> nullRowList) {  
            this.stylesTable = styles;  
            this.sharedStringsTable = strings;  
            this.minColumnCount = cols;  
            this.output = target;  
            this.value = new StringBuffer();  
            this.nextDataType = xssfDataType.NUMBER;  
            this.formatter = new DataFormatter();  
//            record = new String[100];  
            record = new String[this.minColumnCount];  
            rows.clear();// 每次读取都清空行集合  
            this.nullRowList = nullRowList;
        }  
  
        /* 
         * (non-Javadoc) 
         *  
         * @see 
         * org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, 
         * java.lang.String, java.lang.String, org.xml.sax.Attributes) 
         */  
        public void startElement(String uri, String localName, String name,  
                Attributes attributes) throws SAXException {  
  
            if ("inlineStr".equals(name) || "v".equals(name)) {  
                vIsOpen = true;  
                // Clear contents cache  
                value.setLength(0);  
            }  
//            else if("f".equals(name)) {
//              nextDataType = xssfDataType.FORMULA;  
//            }
            // c => cell  
            else if ("c".equals(name)) {  
                // Get the cell reference  
                String r = attributes.getValue("r");  
                int firstDigit = -1;  
                for (int c = 0; c < r.length(); ++c) {  
                    if (Character.isDigit(r.charAt(c))) {  
                        firstDigit = c;  
                        break;  
                    }  
                }  
                thisColumn = nameToColumn(r.substring(0, firstDigit));  
  
                // Set up defaults.  
                this.nextDataType = xssfDataType.NUMBER;  
                this.formatIndex = -1;  
                this.formatString = null;  
                String cellType = attributes.getValue("t");  
                String cellStyleStr = attributes.getValue("s");  
                
//                int styleIndex2 = Integer.parseInt(cellStyleStr);  
//                XSSFCellStyle style2 = stylesTable.getStyleAt(styleIndex2);  
//                System.out.println("styleDataFormat:" + style2.getDataFormat());
                
                if ("b".equals(cellType))  
                    nextDataType = xssfDataType.BOOL;  
                else if ("e".equals(cellType))  
                    nextDataType = xssfDataType.ERROR;  
                else if ("inlineStr".equals(cellType))  
                    nextDataType = xssfDataType.INLINESTR;  
                else if ("s".equals(cellType))  
                    nextDataType = xssfDataType.SSTINDEX;  
                else if ("str".equals(cellType))  
                    nextDataType = xssfDataType.FORMULA;  
                else if (cellStyleStr != null) {  
                    // It's a number, but almost certainly one  
                    // with a special style or format  
                    int styleIndex = Integer.parseInt(cellStyleStr);  
                    XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);  
                    this.formatIndex = style.getDataFormat();  
                    this.formatString = style.getDataFormatString(); 
                    if (this.formatString == null)  
                        this.formatString = BuiltinFormats  
                                .getBuiltinFormat(this.formatIndex);  
                }  
            }  
  
        }  
  
        /* 
         * (non-Javadoc) 
         *  
         * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, 
         * java.lang.String, java.lang.String) 
         */  
        public void endElement(String uri, String localName, String name)  
                throws SAXException {  
  
            String thisStr = null;  
  
            // v => contents of a cell  
            if ("v".equals(name)) {  
                // Process the value contents as required.  
                // Do now, as characters() may be called more than once  
                switch (nextDataType) {  
  
                case BOOL:  
                    char first = value.charAt(0);  
                    thisStr = first == '0' ? "FALSE" : "TRUE";  
                    break;  
  
                case ERROR:  
                    thisStr = "ERROR:" + value.toString();  
                    break;  
  
                case FORMULA:  
                    // A formula could result in a string value,  
                    // so always add double-quote characters.  
                    thisStr = value.toString();  
                    break;  
  
                case INLINESTR:  
                    // TODO: have seen an example of this, so it's untested.  
                    XSSFRichTextString rtsi = new XSSFRichTextString(  
                            value.toString());  
                    thisStr = rtsi.toString();  
                    break;  
  
                case SSTINDEX:  
                    String sstIndex = value.toString();  
                    try {  
                        int idx = Integer.parseInt(sstIndex);  
                        XSSFRichTextString rtss = new XSSFRichTextString(  
                                sharedStringsTable.getEntryAt(idx));  
                        thisStr = rtss.toString();  
                    } catch (NumberFormatException ex) {  
                        output.println("Failed to parse SST index '" + sstIndex  
                                + "': " + ex.toString());  
                    }  
                    break;  
  
                case NUMBER:  
                    String n = value.toString();  
                    // 判断是否是日期格式  
                    if (HSSFDateUtil.isADateFormat(this.formatIndex, n)) {  
                        Double d = Double.parseDouble(n);  
                        Date date=HSSFDateUtil.getJavaDate(d);  
                        thisStr=formateDateToString(date);  
                    } else if (this.formatString != null)  
                        thisStr = formatter.formatRawCellContents(  
                                Double.parseDouble(n), this.formatIndex,  
                                this.formatString);  
                    else  
                        thisStr = n;  
                    break;  
  
                default:  
                    thisStr = "(TODO: Unexpected type: " + nextDataType + ")";  
                    break;  
                }  
  
                // Output after we've seen the string contents  
                // Emit commas for any fields that were missing on this row  
                if (lastColumnNumber == -1) {  
                    lastColumnNumber = 0;  
                }  
                //判断单元格的值是否为空  
                if (thisStr == null || "".equals(isCellNull)) {  
                    isCellNull = true;// 设置单元格是否为空值  
                }  
                // 判断 单元格内容是否为 "需求标题"
                if(nullRowList.get(0).equals(thisStr)) {
                    // 记录需求标题所在列
                    requireHeadColumn = thisColumn;
                    System.out.println("requireTitleColumn:" + requireHeadColumn);
                }
                // 判断 单元格内容是否为 "任务标题"
                if(nullRowList.get(1).equals(thisStr)) {
                    // 记录任务标题所在列
                    exTaskHead = thisColumn;
                    System.out.println("exTaskHead:" + exTaskHead);
                }
                record[thisColumn] = thisStr;  
                // Update column  
                if (thisColumn > -1)  {
                    lastColumnNumber = thisColumn;
                }
//                System.out.println("thisStr:" + thisStr);
            } else if ("row".equals(name)) {  
  
                // Print out any missing commas if needed  
                if (minColumns > 0) {  
                    // Columns are 0 based  
                    if (lastColumnNumber == -1) {  
                        lastColumnNumber = 0;  
                    }  
                    
                    if (isCellNull == false && 
                            (record[requireHeadColumn] != null && !"".equals(record[requireHeadColumn].trim())) || 
                            (record[exTaskHead] != null && !"".equals(record[exTaskHead].trim())))// 判断是否空行  
                    {  
                        rows.add(record.clone());  
                        isCellNull = false;  
                        for (int i = 0; i < record.length; i++) {  
                            record[i] = null;  
                        }  
                    }  
                }  
                lastColumnNumber = -1;  
            }  
  
        }  
  
        public List<String[]> getRows() {  
            return rows;  
        }  
  
        public void setRows(List<String[]> rows) {  
            this.rows = rows;  
        }  
  
        /** 
         * Captures characters only if a suitable element is open. Originally 
         * was just "v"; extended for inlineStr also. 
         */  
        public void characters(char[] ch, int start, int length)  
                throws SAXException {  
            if (vIsOpen)  
                value.append(ch, start, length);  
        }  
  
        /** 
         * Converts an Excel column name like "C" to a zero-based index. 
         *  
         * @param name 
         * @return Index corresponding to the specified name 
         */  
        private int nameToColumn(String name) {  
            int column = -1;  
            for (int i = 0; i < name.length(); ++i) {  
                int c = name.charAt(i);  
                column = (column + 1) * 26 + c - 'A';  
            }  
            return column;  
        }  
  
        private String formateDateToString(Date date) {  
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");//格式化日期  
            return sdf.format(date);  
        }  
  
    }  
  
    // /////////////////////////////////////  
  
    private OPCPackage xlsxPackage;  
    private int minColumns;  
    private PrintStream output;  
    private String sheetName;  
  
    /** 
     * Creates a new XLSX -> CSV converter 
     *  
     * @param pkg 
     *            The XLSX package to process 
     * @param output 
     *            The PrintStream to output the CSV to 
     * @param minColumns 
     *            The minimum number of columns to output, or -1 for no minimum 
     */  
    public XLSXCovertCSVReader(OPCPackage pkg, PrintStream output,  
            String sheetName, int minColumns) {  
        this.xlsxPackage = pkg;  
        this.output = output;  
        this.minColumns = minColumns;  
        this.sheetName = sheetName;  
    }  
  
    /** 
     * Parses and shows the content of one sheet using the specified styles and 
     * shared-strings tables. 
     *  
     * @param styles 
     * @param strings 
     * @param sheetInputStream 
     */  
    public List<String[]> processSheet(StylesTable styles,  
            ReadOnlySharedStringsTable strings, InputStream sheetInputStream, List<String> nullRowList)  
            throws IOException, ParserConfigurationException, SAXException {  
  
        InputSource sheetSource = new InputSource(sheetInputStream);  
        SAXParserFactory saxFactory = SAXParserFactory.newInstance();  
        SAXParser saxParser = saxFactory.newSAXParser();  
        XMLReader sheetParser = saxParser.getXMLReader();  
        MyXSSFSheetHandler handler = new MyXSSFSheetHandler(styles, strings,  
                this.minColumns, this.output, nullRowList);  
        sheetParser.setContentHandler(handler);  
        sheetParser.parse(sheetSource);  
        return handler.getRows();  
    }  
  
    /** 
     * 初始化这个处理程序 将 
     *  
     * @throws IOException 
     * @throws OpenXML4JException 
     * @throws ParserConfigurationException 
     * @throws SAXException 
     */  
    public List<String[]> process(List<String> nullRowList) throws IOException, OpenXML4JException,  
            ParserConfigurationException, SAXException {  
  
        ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(  
                this.xlsxPackage);  
        XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);  
        List<String[]> list = null;  
        StylesTable styles = xssfReader.getStylesTable();  
        XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();  
        int index = 0;  
        while (iter.hasNext()) {  
            InputStream stream = iter.next();  
            String sheetNameTemp = iter.getSheetName();  
            if (this.sheetName.equals(sheetNameTemp)) {  
                list = processSheet(styles, strings, stream, nullRowList);  
                stream.close();  
                ++index;  
            }  
        }  
        return list;  
    }  
  
    /** 
     * 读取Excel 
     *  
     * @param path 
     *            文件路径 
     * @param sheetName 
     *            sheet名称 
     * @param minColumns 
     *            列总数 
     * @return 
     * @throws SAXException 
     * @throws ParserConfigurationException 
     * @throws OpenXML4JException 
     * @throws IOException 
     */  
    public static List<String[]> readerExcel(String path, String sheetName, List<String> nullRowList) throws IOException, OpenXML4JException,  
            ParserConfigurationException, SAXException {  
        OPCPackage p = OPCPackage.open(path, PackageAccess.READ);  
        XLSXCovertCSVReader xlsx2csv = new XLSXCovertCSVReader(p, System.out,  
                sheetName, 100);  
        List<String[]> list = xlsx2csv.process(nullRowList);  
        p.close();  
        return list;  
    }  
  
    public static void main(String[] args) throws Exception {  
        long a=System.currentTimeMillis();  
        List<String> nullRowList = new ArrayList<>();
        nullRowList.add("需求标题");
        nullRowList.add("任务标题");
        
        List<String[]> list = XLSXCovertCSVReader  
                .readerExcel(  
                        "C:/Users/Administrator/Desktop/说明文档2/文档标准/2017ttt.xlsx",  
                        "未安排", nullRowList);  
//        List<String[]> list = XLSXCovertCSVReader  
//                .readerExcel(  
//                        "C:/Users/Administrator/Desktop/说明文档2/2017需求列表.xlsx",  
//                        "需求矩阵");  
//        List<String[]> list = XLSXCovertCSVReader  
//              .readerExcel(  
//                      "D:/profiles/sts-bundle/workspace20170628/ermss/target/classes/bbb.xlsx",  
//                      "月版本和周版本");  
        List<Map<String, String>> resultList = new LinkedList<Map<String, String>>();
        for (int i=0; i<list.size(); i++) {  
            Map<String, String> valueMap = new HashMap<String, String>();
            for (int j=0; j<list.get(i).length; j++) {  
                if(list.get(0)[j] != null && !"".equals(list.get(0)[j])) {
                    valueMap.put(list.get(0)[j], list.get(i)[j]);  
                }
            }  
            // 只获取数据,不要标题
            if(i > 0) {
                resultList.add(valueMap);
            }
        }  
        System.out.println("resultList.size():" + resultList);  
        System.out.println("执行耗时 :"+(System.currentTimeMillis()-a)/1000f+" 秒 "); 
        
    }  
}  

处理xlx如下:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;
import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.BoolErrRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.ExtendedFormatRecord;
import org.apache.poi.hssf.record.FormatRecord;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.LabelRecord;
import org.apache.poi.hssf.record.LabelSSTRecord;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.RKRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.util.POILogger;

/**
 * A XLS -> CSV processor, that uses the MissingRecordAware
 *  EventModel code to ensure it outputs all columns and rows.
 * @author Nick Burch
 */
public class XLS2CSVmra implements HSSFListener {
    private int minColumns;
    private POIFSFileSystem fs;
    private PrintStream output;

    private int lastRowNumber;
    private int lastColumnNumber;

    /** Should we output the formula, or the value it has? */
    private boolean outputFormulaValues = true;

    /** For parsing Formulas */
    private SheetRecordCollectingListener workbookBuildingListener;
    private HSSFWorkbook stubWorkbook;

    // Records we pick up as we process
    private SSTRecord sstRecord;
    private FormatTrackingHSSFListener formatListener;
    
    /** So we known which sheet we're on */
    private int sheetIndex = -1;
    private BoundSheetRecord[] orderedBSRs;
    private List<BoundSheetRecord> boundSheetRecords = new ArrayList<BoundSheetRecord>();

    // For handling formulas with string results
    private int nextRow;
    private int nextColumn;
    private boolean outputNextStringRecord;
    
    String[] recordArray = new String[100];  ;   // 每行为一个数组  
    List<String[]> rowsList = new ArrayList<String[]>();  //当前sheet页的所有行 
    
    private int requireHeadColumn = 99;  // 需求标题所在列
    private int exTaskHead = 99;  //任务标题所在列
    private List<String> nullRowList;   // 包含"需求标题", "任务标题"
    
    private String sheetName = "";
    private final List<ExtendedFormatRecord> _xfRecords = new ArrayList<ExtendedFormatRecord>();
    private final Map<Integer, FormatRecord> _customFormatRecords = new HashMap<Integer, FormatRecord>();

    /**
     * Creates a new XLS -> CSV converter
     * @param fs The POIFSFileSystem to process
     * @param output The PrintStream to output the CSV to
     * @param minColumns The minimum number of columns to output, or -1 for no minimum
     */
    public XLS2CSVmra(POIFSFileSystem fs, PrintStream output, List<String> nullRowList, String sheetName) {
        this.fs = fs;
        this.output = output;
        this.minColumns = 100;
        this.nullRowList = nullRowList;
        this.sheetName = sheetName;
    }

    /**
     * Creates a new XLS -> CSV converter
     * @param filename The file to process
     * @param minColumns The minimum number of columns to output, or -1 for no minimum
     * @throws IOException
     * @throws FileNotFoundException
     */
    public XLS2CSVmra(String filename, String sheetName, List<String> nullRowList) throws IOException, FileNotFoundException {
        this(new POIFSFileSystem(new FileInputStream(filename)), System.out, nullRowList, sheetName);
    }

    /**
     * Initiates the processing of the XLS file to CSV
     */
    public List<String[]> readerExcel() throws IOException {
        MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
        formatListener = new FormatTrackingHSSFListener(listener);
        HSSFEventFactory factory = new HSSFEventFactory();
        HSSFRequest request = new HSSFRequest();
        if(outputFormulaValues) {
            request.addListenerForAllRecords(formatListener);
        } else {
            workbookBuildingListener = new SheetRecordCollectingListener(formatListener);
            request.addListenerForAllRecords(workbookBuildingListener);
        }
        factory.processWorkbookEvents(request, fs);
        return rowsList;
    }

    /**
     * Main HSSFListener method, processes events, and outputs the
     *  CSV as the file is processed.
     */
    @Override
    public void processRecord(Record record) {
        int thisRow = -1;
        int thisColumn = -1;   // 当前cell所在列
        String thisStr = null;  // 单元格内容
        
        processRecordInternally(record);
        
        switch (record.getSid()) {
        case BoundSheetRecord.sid:
            boundSheetRecords.add((BoundSheetRecord)record);
            break;
        case BOFRecord.sid:
            BOFRecord br = (BOFRecord)record;
            if(br.getType() == BOFRecord.TYPE_WORKSHEET) {
                // Create sub workbook if required
                if(workbookBuildingListener != null && stubWorkbook == null) {
                    stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
                }
                
                // Output the worksheet name
                // Works by ordering the BSRs by the location of
                //  their BOFRecords, and then knowing that we
                //  process BOFRecords in byte offset order
                sheetIndex++;
                if(orderedBSRs == null) {
                    orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
                }
//              output.println();
                //output.println(orderedBSRs[sheetIndex].getSheetname() +" [" + (sheetIndex+1) + "]:");
            }
            break;

        case SSTRecord.sid:
            sstRecord = (SSTRecord) record;
            break;

        case BlankRecord.sid:
            BlankRecord brec = (BlankRecord) record;

            thisRow = brec.getRow();
            thisColumn = brec.getColumn();
            thisStr = "";
            break;
        case BoolErrRecord.sid:
            BoolErrRecord berec = (BoolErrRecord) record;

            thisRow = berec.getRow();
            thisColumn = berec.getColumn();
            thisStr = "";
            break;

        case FormulaRecord.sid:
            FormulaRecord frec = (FormulaRecord) record;

            thisRow = frec.getRow();
            thisColumn = frec.getColumn();

            if(outputFormulaValues) {
                if(Double.isNaN( frec.getValue() )) {
                    // Formula result is a string
                    // This is stored in the next record
                    outputNextStringRecord = true;
                    nextRow = frec.getRow();
                    nextColumn = frec.getColumn();
                } else {
                    thisStr = formatListener.formatNumberDateCell(frec);
                }
            } else {
                thisStr = HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression());
            }
            break;
        case StringRecord.sid:
            if(outputNextStringRecord) {
                // String for formula
                StringRecord srec = (StringRecord)record;
                thisStr = srec.getString();
                thisRow = nextRow;
                thisColumn = nextColumn;
                outputNextStringRecord = false;
            }
            break;

        case LabelRecord.sid:
            LabelRecord lrec = (LabelRecord) record;

            thisRow = lrec.getRow();
            thisColumn = lrec.getColumn();
            thisStr = lrec.getValue();
            break;
        case LabelSSTRecord.sid:
            LabelSSTRecord lsrec = (LabelSSTRecord) record;

            thisRow = lsrec.getRow();
            thisColumn = lsrec.getColumn();
            if(sstRecord == null) {
                thisStr ="(No SST Record, can't identify string)";
            } else {
                thisStr = sstRecord.getString(lsrec.getSSTIndex()).toString();
            }
            break;
        case NoteRecord.sid:
            NoteRecord nrec = (NoteRecord) record;

            thisRow = nrec.getRow();
            thisColumn = nrec.getColumn();
            // TODO: Find object to match nrec.getShapeId()
            thisStr = "(TODO)";
            break;
        case NumberRecord.sid:
            NumberRecord numrec = (NumberRecord) record;
            thisRow = numrec.getRow();
            thisColumn = numrec.getColumn();
            // Format
            thisStr = formatNumberDateCell(numrec);
//          thisStr = formatListener.formatNumberDateCell(numrec);
            break;
        case RKRecord.sid:
            RKRecord rkrec = (RKRecord) record;

            thisRow = rkrec.getRow();
            thisColumn = rkrec.getColumn();
            thisStr = "(TODO)";
            break;
        default:
            break;
        }

        // Handle new row
        if(thisRow != -1 && thisRow != lastRowNumber) {
            lastColumnNumber = -1;
        }

        // Handle missing column
        if(record instanceof MissingCellDummyRecord) {
            MissingCellDummyRecord mc = (MissingCellDummyRecord)record;
            thisRow = mc.getRow();
            thisColumn = mc.getColumn();
            thisStr = "";
        }

        // If we got something to print out, do so
        if(thisStr != null) {
            if(thisColumn > 0) {
                output.print(',');
            }
            
            // 判断 单元格内容是否为 "需求标题"
            if(nullRowList.get(0).equals(thisStr)) {
                // 记录需求标题所在列
                requireHeadColumn = thisColumn;
                System.out.println("requireTitleColumn:" + requireHeadColumn);
            }
            // 判断 单元格内容是否为 "任务标题"
            if(nullRowList.get(1).equals(thisStr)) {
                // 记录任务标题所在列
                exTaskHead = thisColumn;
                System.out.println("exTaskHead:" + exTaskHead);
            }
//            output.print(thisStr);
            recordArray[thisColumn] = thisStr;  
        }

        // Update column and row count
        if(thisRow > -1)
            lastRowNumber = thisRow;
        if(thisColumn > -1)
            lastColumnNumber = thisColumn;

        // Handle end of row
        if(record instanceof LastCellOfRowDummyRecord) {
            // Print out any missing commas if needed
            if(minColumns > 0) {
                // Columns are 0 based
                if(lastColumnNumber == -1) { lastColumnNumber = 0; }
                for(int i=lastColumnNumber; i<(minColumns); i++) {
//                  output.print(',');
                }
                // 判断是不是指定sheet页下的内容
                if(sheetName.equals(orderedBSRs[sheetIndex].getSheetname())) {
                    // 判断是否空行  
                    if ((recordArray[requireHeadColumn] != null && !"".equals(recordArray[requireHeadColumn].trim())) || 
                            (recordArray[exTaskHead] != null && !"".equals(recordArray[exTaskHead].trim()))) {  
                        output.println();
                        rowsList.add(recordArray.clone());  
                        for (int i = 0; i < recordArray.length; i++) {  
                            recordArray[i] = null;  
                        }  
                    } 
                }
            }
            lastColumnNumber = -1;
        }
    }
    public int getFormatIndex(CellValueRecordInterface cell) {
        ExtendedFormatRecord xfr = _xfRecords.get(cell.getXFIndex());
        if (xfr == null) {
            return -1;
        }
        return xfr.getFormatIndex();
    }
    public String formatNumberDateCell(CellValueRecordInterface cell) {
        double value;
        if (cell instanceof NumberRecord) {
            value = ((NumberRecord) cell).getValue();
        } else if (cell instanceof FormulaRecord) {
            value = ((FormulaRecord) cell).getValue();
        } else {
            throw new IllegalArgumentException("Unsupported CellValue Record passed in " + cell);
        }
        // Format, using the nice new
        // HSSFDataFormatter to do the work for us"yyyy/MM/dd"
        DataFormatter _formatter = new DataFormatter();
        return _formatter.formatRawCellContents(value, getFormatIndex(cell), getFormatString(cell));
    }
    public String getFormatString(CellValueRecordInterface cell) {
        int formatIndex = getFormatIndex(cell);
        if (formatIndex == -1) {
            // Not found
            return null;
        }
        return getFormatString(formatIndex);
    }
    public String getFormatString(int formatIndex) {
        String format = null;
        if (formatIndex >= HSSFDataFormat.getNumberOfBuiltinBuiltinFormats()) {
            FormatRecord tfr = _customFormatRecords.get(Integer.valueOf(formatIndex));
            if (tfr == null) {
            } else {
                format = tfr.getFormatString();
            }
        } else if(formatIndex == 14) {
            format = "yyyy/MM/dd";
        } else {
            // "yyyy/MM/dd"
            format = HSSFDataFormat.getBuiltinFormat((short) formatIndex);
        }
        return format;
    }
    public void processRecordInternally(Record record) {
        if (record instanceof FormatRecord) {
            FormatRecord fr = (FormatRecord) record;
            _customFormatRecords.put(Integer.valueOf(fr.getIndexCode()), fr);
        }
        if (record instanceof ExtendedFormatRecord) {
            ExtendedFormatRecord xr = (ExtendedFormatRecord) record;
            _xfRecords.add(xr);
        }
    }

    public static void main(String[] args) throws Exception {
        List<String> nullRowList = new ArrayList<>();
        nullRowList.add("需求内容");
        nullRowList.add("任务标题");
        XLS2CSVmra xls2csv = new XLS2CSVmra(
                "C:/Users/Administrator/Desktop/说明文档2/XXX.xls", 
                "电销系统", nullRowList);
        List<String[]> list = xls2csv.readerExcel();
        
        List<Map<String, String>> resultList = new LinkedList<Map<String, String>>();
        for (int i=0; i<list.size(); i++) {  
            Map<String, String> valueMap = new HashMap<String, String>();
            for (int j=0; j<list.get(i).length; j++) {  
                if(list.get(0)[j] != null && !"".equals(list.get(0)[j])) {
                    valueMap.put(list.get(0)[j], list.get(i)[j]);  
                }
            }  
            // 只获取数据,不要标题
            if(i > 0) {
                resultList.add(valueMap);
            }
        }  
        System.out.println("\nresultList.size():" + resultList.size());  
        System.out.println("\nresultList:" + resultList);  
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容