JAVA中用POI组件访问EXCEL文档

        对于用JAVA访问EXCEL文件,常用的组件有jxl和POI, jxl因为目前已无版本更新,并且仅能访问EXCEL2007以前的文件格式,对xlsx文件格式目前不支持, 故而推荐使用POI, 
       POI的官方下载地址为: http://poi.apache.org/
      本质上来说, EXCEL2007文档是一个XML文档, 所以POI对EXCEL文件读操作有两种方式,一种是DOM, 一种是SAX, DOM对EXCEL操作简单,易上手, 但是占用较多的内存,尤其是表格超过10000行, 经常会出现内存溢出问题,虽然可以改变JVM启动参数, 加大内存,但不能从根本上解决问题,所以当需要读取较大的EXCEL文件时, 我们采用第二种方式更为合理.
       对于EXCEL文档写操作也面临同样问题, 如果写入的行数过多, 也会遇到内存溢出, 但是写操作解决大文件的办法比较简单, 设置写缓存就可以了, 不过因为EXCEL的SHEET有最大行数的限制(65534), 所以如果行数超过这个限制, 需要创建新的SHEET, 以下是对EXCEL大文件读写操作的示例.

import java.io.InputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DateUtil;
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;

public class TestExcelReader {
    public static void main(String[] args) throws Exception {
    String path = "c://cache//test.xlsx";
    ExcelHandler handler = new ExcelHandler();
        handler.process(path);
    }
    public static class ExcelHandler extends DefaultHandler {
        public ExcelHandler() {}
        private StylesTable stylesTable;
        private CellDataType dataType;
        private SharedStringsTable sst;
        private Map<String, String> datas;
        private short dataFormat;
        private String dataFormatString;
        private boolean tagString;
        private boolean tElement = false;
        private String content;
        private Coordinate coordinate;
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            if ("c".equals(qName)) {
                this.setDataType(attributes);
                coordinate = getCoordinate(attributes.getValue("r"));
            }
            else if ("t".equals(qName)) {
                tElement = true;
            } 
            else {
                tElement = false;
            }
            content = "";
        }
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            if (tagString) {
                int idx = Integer.parseInt(content);
                content = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
            }
            if (tElement) {
                String value = content.trim();
                setDataValue(datas, value, true);
                tElement = false;
            }
            if ("v".equals(qName)) {
                setDataValue(datas, content.trim(), false);
            }
            if ("row".equals(qName)) {
                // process the row datas;
                System.out.println(datas);
                datas.clear();
            }
        }
        public void process(String path) {
            InputStream is = null;
            OPCPackage pkg = null;
            try {
                pkg = OPCPackage.open(path);
                XSSFReader reader = new XSSFReader(pkg);
                stylesTable = reader.getStylesTable();
                SharedStringsTable sst = reader.getSharedStringsTable();
                this.sst = sst;
                Iterator<InputStream> it = reader.getSheetsData();
                if (it.hasNext()) {
                    is = it.next();
                    InputSource source = new InputSource(is);
                    XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
                    parser.setContentHandler(this);
                    parser.parse(source);
                }
            }
            catch(Throwable ex) {
                ex.printStackTrace();
            }
            finally {
                try {
                    if (is != null) is.close();
                    if (pkg != null) pkg.close();
                }
                catch(Throwable e) {}
            }
        }
        public void setDataValue(Map<String, String> datas, String value, boolean t) {
            String column = coordinate.getColumnName();
            if (t) {
                datas.put(column, value);
            }
            else {
                switch (dataType) {
                    case BOOL:
                        char first = value.charAt(0);
                        datas.put(column, first == '0' ? "否":"是");
                        break;
                    case ERROR:
                        String err = "\"ERROR:" + value.toString() + '"';
                        datas.put(column, err);
                        break;
                    case FORMULA:
                        datas.put(column, value);
                        break;
                    case INLINESTR:
                        XSSFRichTextString rts = new XSSFRichTextString(value.toString());
                        String inline = rts.toString();
                        datas.put(column, inline);
                        break;
                    case SSTINDEX:
                        String sidx = value.toString();
                        try {
                            int idx = Integer.parseInt(sidx);
                            XSSFRichTextString rtss = new XSSFRichTextString(sst.getEntryAt(idx));
                            String sstindex = rtss.toString();
                            datas.put(column, sstindex);
                            rtss = null;
                        }
                        catch (NumberFormatException ex) {
                            ex.printStackTrace();
                            datas.put(column, value);
                        }
                        break;
                    case NUMBER:
                        Double db = Double.parseDouble(value);
                        datas.put(column, String.valueOf(db));
                        break;
                    case DATE:
                        double number = Double.parseDouble(value);
                        Date date = DateUtil.getJavaDate(number);
                        datas.put(column, date.toString());
                        break;
                    default:
                        datas.put(column, "");
                        break;
                }
            }
        }
        public void setDataType(Attributes attributes) {
            String cellType = attributes.getValue("t");
            String cellStyleStr = attributes.getValue("s");
            dataType = CellDataType.NUMBER;
            if ("b".equals(cellType)) {
                dataType = CellDataType.BOOL;
            }
            else if ("e".equals(cellType)) {
                dataType = CellDataType.ERROR;
            }
            else if ("inlineStr".equals(cellType)) {
                dataType = CellDataType.INLINESTR;
            }
            else if ("s".equals(cellType)) {
                dataType = CellDataType.SSTINDEX;
            }
            else if ("str".equals(cellType)) {
                dataType = CellDataType.FORMULA;
            }
            if (cellStyleStr != null) {
                int styleIndex = Integer.parseInt(cellStyleStr);
                XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
                dataFormat = style.getDataFormat();
                dataFormatString = style.getDataFormatString();
                if (dataFormatString == null) {
                    dataType = CellDataType.NULL;
                    dataFormatString = BuiltinFormats.getBuiltinFormat(dataFormat);
                }
                if (dataFormat > 0) {
                    if (!isScientificReg(dataFormatString)) {
                        dataType = CellDataType.DATE;
                    }
                }
            }
        }
    }
    public static interface Coordinate {
        String getColumnName();
        int getLine();
    }
    public static Coordinate getCoordinate(String row) {
        Coordinate coordinate = null;
        if (row != null && !"".equals(row)) {
            int last = -1;
            for(int i = 0; i < row.length(); i++) {
                if (Character.isDigit(row.charAt(i))) {
                    last = i;
                    break;
                }
            }
            String sline = last != -1 ? row.substring(last):"0";
            final String column = last != -1 ? row.substring(0, last):row;
            final int line = Integer.parseInt(sline);
            coordinate = new Coordinate() {
                @Override
                public String getColumnName() {
                    return column;
                }
                @Override
                public int getLine() {
                    return line;
                }
            };
        }
        if (coordinate == null) {
            coordinate = new Coordinate() {
                @Override
                public String getColumnName() {
                    return "";
                }
                @Override
                public int getLine() {
                    return 0;
                }
            };
        }
        return coordinate;
    }

    public static boolean isScientificReg(String str) {
        boolean result = false;
        if (str != null) {
            String reg = "0.[0]+[Ee][+-]00";
            Pattern pattern = Pattern.compile(reg);
            result = pattern.matcher(str).matches();
        }
        return result;
    }

    public static enum CellDataType {
        BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
    }
}

你可能感兴趣的:(java,poi,Excel)