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
    }
}
时间: 2024-12-13 22:13:07

JAVA中用POI组件访问EXCEL文档的相关文章

Java使用poi包读取Excel文档

项目需要解析Excel文档获取数据,就在网上找了一些资料,结合自己这次使用,写下心得: 1.maven项目需加入如下依赖: <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.10-FINAL</version> </dependency> <dependency> <gr

Java使用Aspose组件进行多文档间的转换操作

什么是Aspose? Aspose.Total是Aspose公司旗下的最全的一套office文档管理方案,主要提供.net跟java两个开发语言的控件套包,通过它,我们可以有计划地操纵一些商业中最流行的文件格式:Word, Excel, PowerPoint, Project,等office文档以及PDF文档. 除了强大的文件操纵组件之外,Aspose.Total 还提供了用于制图.写电子邮件.拼写检查.创建条形码.生成ad hoc 查询.重现格式以及工作流等组件,运用它我们可以整理一个完整的文

Asp.net的对Excel文档的导入导出操作

刚刚初入职场,在休闲的时间写下了项目中用到的对Excel文档操作的方法以及总结,多的不说,直接上代码 public static void CreateExcel(DataSet ds, string FileName) { //resp = Page.Response; HttpContext.Current.Response.Clear(); HttpContext.Current.Response.Buffer = true; HttpContext.Current.Response.Ch

Apache POI -- Java 导出Excel文档(笔记)

一.Action类 import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Met

POI操纵EXCEL文档之导入文档(一)

             当前主流的后台管理系统,相信都会有文档导入导出的功能.而这其中用到的技术又是多种多样,有用POI框架,也有用JXLS技术的.技术只是手段,项目中实现功能最重要.今天主要说下如何利用POI技术操作EXCEL文档. POI 导入EXCEL文档: 1,首先,要导入EXCEL 文档,就必须要先有导入的模板文件,在这里,我提供好了制作好的EXCEL 模板文件提供下载:( EXCEL文档模板示例下载 ) 2,有了EXCEL 模板文件,就开始编写页面,并编写后台逻辑代码了: <%--

struts2中利用POI导出Excel文档并下载

1.项目组负责人让我实现这个接口,因为以前做过类似的,中间并没有遇到什么太困难的事情.其他不说,先上代码: 1 package com.tydic.eshop.action.feedback; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.FileInputStream; 6 import java.io.IOException; 7 import

Apache POI处理excel文档

目前比较流行处理excel文档的方式一般有两种,分别是POI和JXL.重量级POI优缺点:适合对excel文档细节有比较专业的要求,如使用公式.宏等高级功能:缺点是操作相对繁琐,非纯java编写的架包,跨平台性有待加强.轻量级JXL优缺点:Jxl是纯javaAPI,跨平台性优越,操作相对简便:缺点是对excel文档的一些高级功能不支持,但可以满足日常需求.这里我们介绍POI的基本使用. 1.首先导入相关架包,如图: 这里还要注意你开发项目的JDK版本是什么,要根据相应JDK版本下载不同POI的版

POI导出EXCEL文档

package com.wiseweb.util.excel; import java.io.*; import java.util.*; import javax.swing.JOptionPane; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.hssf.util.HSSFColor; import com.wiseweb.pom.entity.BaiinfoPriceTime; public class Expo

java读取WORD/EXCEL模板转换生成新WORD/EXCEL文档

原文:java读取WORD/EXCEL模板转换生成新WORD/EXCEL文档 代码下载地址:http://www.zuidaima.com/share/1550463239670784.htm 可以通过预先设置指定的excel和word模板,通过替换文档里面指定的标志来生成新的excel和word文档.excel的部分只是实现了简单的方法.word部分可以支持word2003和word2007格式.建议word使用07及其以上. 其实excel部分标签和jstl很像,而且支持循环等.word就支