poi解析Excel2007海量数据

  处理excel,开源的javaApI提供了两种,一种是jxl,一种是poi。poi提供的功能较多,所以我用的是poi。

  poi有两种模式,一个是用户模式(HSSFworkbook:支持Excel2003,XSSFworkbook:支持Excel2007),这个操作数量上万的时候会造成out of memory 的情况。另一个是事件驱动模,解析的Excel数据上万的时候用这个,这里拿Excel2007来说明,Excel2007的底层其实就是xml形式的,其实也就是解析xml。

  底层xml格式:

<sheetData>//代表一个shet
- <row r="1" spans="1:33">//代表一个行
- <c r="A1" t="s">//代表一个单元格  r是坐标
  <v>0</v> //代表相应的值,这里的0不是真正的值
  </c>
- <c r="B1" t="s">
  <v>1</v>
  </c>
- <c r="C1" t="s">
  <v>2</v>
  </c>
</row>
</sheetData>

  所需jar包:poi.jar,poi-excelant,poi-ooxml.jar,poi-ooxml-schemas.jar,poi-    scratchpad.jar,dom4j.jar,xmlbeans.jar,xerces.jar

  代码:空值问题待解决

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
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.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;

//Default是sax解析xml的处理类
public class TestExcel2007Util{
     public static void main(String[] args) throws IOException, OpenXML4JException, SAXException {
         Excel2007Util excel2007Util=new Excel2007Util();
            excel2007Util.process("C:/Users/sime/Desktop/XXX.xlsx");

    }
 }
     class Excel2007Util extends DefaultHandler{
            //共享字符串表
            private ReadOnlySharedStringsTable sst;
            //单元格
            private StylesTable stylesTable;

            private String lastContents;

            private boolean nextIsString; 

            private List<String> rowlist=new ArrayList<String>();
            //当前页
            private int sheetIndex;
            //当前行
            private int curRow =0;
            //当前单元格
            private int curCol =0;
            private boolean cellNull;

            /**
             * excel记录行操作方法,rowlist是一行记录,这里可以进行你的逻辑处理
             */
            public void optRows(int sheetIndex,int curRow,List<String> rowlist){
                System.out.println(rowlist.toString());
            }

            /**
             * 遍历工作簿中所有的电子表格
             * @throws OpenXML4JException
             * @throws IOException
             * @throws SAXException
             */
            public void process    (String filename) throws IOException, OpenXML4JException, SAXException{
                     OPCPackage pkg = OPCPackage.open(filename);
                    XSSFReader xssfReader = new XSSFReader(pkg);
                    sst = new ReadOnlySharedStringsTable(pkg);
                    XMLReader parser=this.fetchSheetParser(sst);
                    Iterator<InputStream> sheets = xssfReader.getSheetsData();
                    while (sheets.hasNext()) {
                        curRow = 0;
                        sheetIndex++;
                        InputStream sheet = sheets.next();
                        InputSource sheetSource = new InputSource(sheet);
                        parser.parse(sheetSource);
                        sheet.close();
                    }
                    pkg.close();
            }
            public XMLReader fetchSheetParser(ReadOnlySharedStringsTable sst) throws SAXException {
                XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); 

         parser.setContentHandler(this); 
return parser;
            } 

            /**
             * 解析器在 XML 文档中的每个元素的开始调用此方法
             * uri:名称空间 URI
             * localName:本地名称
             * name:限定名
             * attributes:连接到元素上的属性
             */
            public void startElement(String uri, String localName, String name, Attributes attributes){
                if (name.equals("c")) {
                    // 如果下一个元素是 SST 的索引,则将nextIsString标记为true
                    String cellType = attributes.getValue("t");
//                    System.out.println("cellType : " + cellType);
                    if (cellType != null && cellType.equals("s")) {
                        nextIsString = true;
                        cellNull = false;
                    } else {
                        nextIsString = false;
                        cellNull = true;
                    }
                }
                lastContents = "";
            }
            // 根据SST的索引值的到单元格的真正要存储的字符串
            // 这时characters()方法可能会被调用多次
            public void characters(char[] ch, int start, int length) throws SAXException {
                //得到单元格内容的值
                lastContents += new String(ch, start, length); 

            } 

            public void endElement (String uri, String localName, String name){
                if (nextIsString) {
                    try {
                        int idx = Integer.parseInt(lastContents);
                        lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
                    } catch (Exception e) { 

                    }
                } 

            // v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
            // 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
            if (name.equals("v") || "t".equals(name)) {
                String value = lastContents.trim();
                rowlist.add(curCol, value);
                curCol++;
                cellNull = false;
            }else if("c".equals(name)){
                rowlist.add(curCol, "");
                curCol++;
                cellNull = false;
            }else {
                //如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
                if (name.equals("row")) {
                    optRows(sheetIndex,curRow,rowlist);
                    rowlist.clear();
                    curRow++;
                    curCol = 0;
                }
            }
            }

        }

这是个人网上百度后总结的方法,比较简洁,可以直接拿去用,但是空值的问题尚未解决,如有不对的地方请指出。

  

org.apache.xerces.parsers.SAXParser
时间: 2024-12-16 14:01:23

poi解析Excel2007海量数据的相关文章

POI以SAX方式解析Excel2007大文件(包含空单元格的处理) Java生成CSV文件实例详解

http://blog.csdn.net/l081307114/article/details/46009015 http://www.cnblogs.com/dreammyle/p/5458280.html . Office2007与Office Open XML 在Office 2007之前,Office一直都是以二进制位的方式存储,但这种格式不易被其它软件拿来使用,在各界的压力下,MicroSoft于2005年发布了基于XML的ooxml开放文档标准.ooxml的xml schema强调减

java 使用 poi 解析excel

背景: web应用经常需要上传文件,有时候需要解析出excel中的数据,如果excel的格式没有问题,那就可以直接解析数据入库. 工具选择: 目前jxl和poi可以解析excel,jxl很早就停止维护了,只支持excel-2003也就是xls格式的文件: poi可支持xls和xlsx格式的文件,经过考察,poi的功能强大很多,所以选择这个工具解析excel.文件上传在之前的一个专题有所提及. 需要如下jar包,jar包见附件,也可在官网下载. 注意: 1. 不支持单元格合并的情况,默认表格格式规

poi解析Excel文件版本问题

poi解析Excel文件时有两种格式: HSSFWorkbook格式用来解析Excel2003(xls)的文件 XSSFWorkbook格式用来解析Excel2007(xlsx)的文件 如果用HSSFWorkbook解析Excel2007(xlsx)时就会报异常:“The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office

Poi解析Excel

Poi解析Excel Poi包里有4个主要的类,包括: Workbook------工作表,通过WorkbookFactory的create(FileInputStream fis)方法获取, Sheet------------表格,Workbook实例的getSheetAt(int num)方法获取, Row--------------行,Sheet实例的getRow(int num)方法获取, Cell--------------单元格,Row实例的getCell(int num)方法获取,

使用POI解析Excel时,出现org.xml.sax.SAXParseException: duplicate attribute &#39;o:relid&#39;的解决办法

1.使用org.apache.poi解析excle,.xlsx类型文件InputStream is = new FileInputStream(strFileName);XSSFWorkbook wb = new XSSFWorkbook(is);出现异常如下: org.apache.poi.POIXMLException: java.lang.reflect.InvocationTargetExceptionat org.apache.poi.xssf.usermodel.XSSFFactor

Apache POI解析Excel文件

1.导入POI的jar包到BOS项目中 2. 使用POI解析Excel文件

框架 day50 BOS项目 4 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)

知识点: 批量导入(ocupload插件,pinyin4J /POI解析Excel(apache POI) /区域分页查询 /Combobox下拉框 /分区组合条件分页查询(ajax) /分区数据导出(Excel下载) BOS项目笔记第4天 1.    区域批量导入功能 *Ajax不支持文件上传. *上传并且不刷新上传页面原理: Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象 <form target="myIframe" action="ab

结合项目(Spring+(基于注解的)SpringMVC和Mybatis+uploadify文件上传)--poi解析Excel文件

poi解析Excel文件 1.上传文件至服务器 2.解析Excel文件并返回数据集合 3.将数据保存到服务器 框架======Spring+(基于注解的)SpringMVC和Mybatis===== 第一步: 前台: jsp文件采用的是uploadify <div id="fileQueue"></div> <input type="file" id="brandFile"> js: <script ty

springmvc 使用poi解析excel并通过hibernate连续插入多条数据 实际数据库只能保存最后一条

有一个原始数据的excel表 用poi解析之后通过hibernate插数据库 结果 后来发现,有人说 果断尝试 问题解决 但是这好像并不是真正解决问题,只是解决了一个现象 因为有人说 https://blog.csdn.net/u010739551/article/details/49362403 实际上我刚才那种操作是正确的,并且做了测试,但是我实测是不行的,那只能解释为版本问题了 原文地址:https://www.cnblogs.com/jnhs/p/10060717.html