Poi excel

来源:互联网 发布:linux java 打包war 编辑:程序博客网 时间:2024/05/22 09:50
        // 构造 XSSFWorkbook 对象,strPath 传入文件路径
        XSSFWorkbook xwb = new XSSFWorkbook(strPath);
        // 读取第一章表格内容
        XSSFSheet sheet = xwb.getSheetAt(0);
        // 定义 row、cell
        XSSFRow row;
        String cell;
        // 循环输出表格中的内容
        for (int i = sheet.getFirstRowNum(); i < sheet.getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            for (int j = row.getFirstCellNum(); j < row.getPhysicalNumberOfCells(); j++) {
                // 通过 row.getCell(j).toString() 获取单元格内容,
                cell = row.getCell(j).toString();
                System.out.print(cell + "\t");
            }
            System.out.println("");

        }


FileOutputStream out = new FileOutputStream(new File("D://result.xlsx"));


Workbook writeWB = new SXSSFWorkbook(500);
Sheet writeSheet = writeWB.createSheet();


for (int rr = 0; rr < 400000; rr++) {
Row writeRow = writeSheet.createRow(rr);
for (int cc = 0; cc < 10; cc++) {
writeRow.createCell(cc).setCellValue("测试" + rr + "," + cc);
}
}
writeWB.write(out);



        // 构造 XSSFWorkbook 对象,strPath 传入文件路径
        XSSFWorkbook xwb = new XSSFWorkbook(strPath);
        // 读取第一章表格内容
        XSSFSheet sheet = xwb.getSheetAt(0);
        // 定义 row、cell
        XSSFRow row;
        String cell;
        // 循环输出表格中的内容
        for (int i = sheet.getFirstRowNum(); i < sheet.getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            for (int j = row.getFirstCellNum(); j < row.getPhysicalNumberOfCells(); j++) {
                // 通过 row.getCell(j).toString() 获取单元格内容,
                cell = row.getCell(j).toString();
                System.out.print(cell + "\t");
            }
            System.out.println("");
        }




    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SS");
        TimeZone t = sdf.getTimeZone();
        t.setRawOffset(0);
        sdf.setTimeZone(t);
        Long startTime = System.currentTimeMillis();
        String fileName = "F:\\我的文档\\学生缴费代码.xlsx";
        // 检测代码
        try {
            PoiReadExcel er = new PoiReadExcel();
            // 读取excel2007
            er.testPoiExcel2007(fileName);
        } catch (Exception ex) {
            Logger.getLogger(FastexcelReadExcel.class.getName()).log(Level.SEVERE, null, ex);
        }
        Long endTime = System.currentTimeMillis();
        System.out.println("用时:" + sdf.format(new Date(endTime - startTime)));
    }



POI3.8的SXSSF包是XSSF的一个扩展版本,支持流处理,在生成大数据量的电子表格且堆空间有限时使用。SXSSF通过限制内存中可访问的记录行数来实现其低内存利用,当达到限定值时,新一行数据的加入会引起老一行的数据刷新到硬盘。

       比如内存中限制行数为100,当行号到达101时,行号为0的记录刷新到硬盘并从内存中删除,当行号到达102时,行号为1的记录刷新到硬盘,并从内存中删除,以此类推。

       rowAccessWindowSize代表指定的内存中缓存记录数,默认为100,此值可以通过

new SXSSFWorkbook(int rowAccessWindowSize)或SXSSFSheet.setRandomAccessWindowSize(intwindowSize)来设置。

       SXSSF在把内存数据刷新到硬盘时,是把每个SHEET生成一个临时文件,这个临时文件可能会很大,有可以会达到G级别,如果文件的过大对你来说是一个问题,你可以使用下面的方法让SXSSF来进行压缩,当然性能也会有一定的影响。

               SXSSFWorkbook wb = new SXSSFWorkbook();               wb.setCompressTempFiles(true); // temp files will be gzipped

 

例子:

生成三个SHEET,每个SHEET有6000行记录,共18万行记录

 

importjava.io.FileOutputStream;

 

importorg.apache.poi.ss.usermodel.Cell;

importorg.apache.poi.ss.usermodel.Row;

importorg.apache.poi.ss.usermodel.Sheet;

importorg.apache.poi.ss.util.CellReference;

importorg.apache.poi.xssf.streaming.SXSSFSheet;

importorg.apache.poi.xssf.streaming.SXSSFWorkbook;

 

public classSXSSFWorkBookUtil {

    public voidtestWorkBook() {

       try{

           longcurr_time=System.currentTimeMillis();

 

           introwaccess=100;//内存中缓存记录行数

           /*keep 100 rowsin memory,exceeding rows will be flushed to disk*/

           SXSSFWorkbook wb = newSXSSFWorkbook(rowaccess); 

 

           intsheet_num=3;//生成3个SHEET

           for(inti=0;i<sheet_num;i++){

              Sheet sh = wb.createSheet();

              //每个SHEET有60000ROW

              for(intrownum = 0; rownum < 60000; rownum++) {

                  Row row = sh.createRow(rownum);

                  //每行有10个CELL

                  for(intcellnum = 0; cellnum < 10; cellnum++) {

                     Cell cell = row.createCell(cellnum);

                     String address = newCellReference(cell).formatAsString();

                     cell.setCellValue(address);

                  }

 

                  //每当行数达到设置的值就刷新数据到硬盘,以清理内存

                  if(rownum%rowaccess==0){

                     ((SXSSFSheet)sh).flushRows();

                  }

              }

           }

 

           /*写数据到文件中*/

           FileOutputStream os = newFileOutputStream("d:/data/poi/biggrid.xlsx");    

           wb.write(os);

           os.close();

 

           /*计算耗时*/

           System.out.println("耗时:"+(System.currentTimeMillis()-curr_time)/1000);

       } catch(Exception e) {

           e.printStackTrace();

       }

    }

}

 

对于不同的rowAccessWindowSize值,用上面的例子进行耗时测试,结果如下:

 

rowAccessWindowSize    Time(s)

5000    293

1000    69

500    43

100    20

50    18

10    16

1    15

 

以上测试结果是在个人笔记本电脑上进行的,配置为:

Dual-Core CPU T4400 2.2GHz 2.19GHz

Memory 1.86GB

以上测试过程只是进行了一次,并没有多次测试求平均值,数据也只想表达当设置不同的rowAccessWindowSize值,耗时的一种趋势。

可见一般情况下,使用默认值100即可。



import java.io.InputStream;import java.util.ArrayList;import java.util.Iterator;import java.util.List;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.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 ExcelUtil extends DefaultHandler {private SharedStringsTable sst;private String lastContents;private boolean nextIsString;private int sheetIndex = -1;private List<String> rowlist = new ArrayList<String>();private int curRow = 0;private int curCol = 0;/** * 读取第一个工作簿的入口方法 * @param path */public void readOneSheet(String path) throws Exception {OPCPackage pkg = OPCPackage.open(path);XSSFReader r = new XSSFReader(pkg);SharedStringsTable sst = r.getSharedStringsTable();XMLReader parser = fetchSheetParser(sst);InputStream sheet = r.getSheet("rId1");InputSource sheetSource = new InputSource(sheet);parser.parse(sheetSource);sheet.close();}/** * 读取所有工作簿的入口方法 * @param path * @throws Exception */public void process(String path) throws Exception {OPCPackage pkg = OPCPackage.open(path);XSSFReader r = new XSSFReader(pkg);SharedStringsTable sst = r.getSharedStringsTable();XMLReader parser = fetchSheetParser(sst);Iterator<InputStream> sheets = r.getSheetsData();while (sheets.hasNext()) {curRow = 0;sheetIndex++;InputStream sheet = sheets.next();InputSource sheetSource = new InputSource(sheet);parser.parse(sheetSource);sheet.close();}}/** * 该方法自动被调用,每读一行调用一次,在方法中写自己的业务逻辑即可 * @param sheetIndex 工作簿序号 * @param curRow 处理到第几行 * @param rowList 当前数据行的数据集合 */public void optRow(int sheetIndex, int curRow, List<String> rowList) {String temp = "";for(String str : rowList) {temp += str + "_";}System.out.println(temp);}public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");this.sst = sst;parser.setContentHandler(this);return parser;}public void startElement(String uri, String localName, String name,Attributes attributes) throws SAXException {// c => 单元格if (name.equals("c")) {// 如果下一个元素是 SST 的索引,则将nextIsString标记为trueString cellType = attributes.getValue("t");if (cellType != null && cellType.equals("s")) {nextIsString = true;} else {nextIsString = false;}}// 置空lastContents = "";}public void endElement(String uri, String localName, String name)throws SAXException {// 根据SST的索引值的到单元格的真正要存储的字符串// 这时characters()方法可能会被调用多次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")) {String value = lastContents.trim();value = value.equals("") ? " " : value;rowlist.add(curCol, value);curCol++;} else {// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法if (name.equals("row")) {optRow(sheetIndex, curRow, rowlist);rowlist.clear();curRow++;curCol = 0;}}}public void characters(char[] ch, int start, int length)throws SAXException {// 得到单元格内容的值lastContents += new String(ch, start, length);}}

 

1 楼 hqingjin 2012-05-18  
读取excel的程序的入口方法和获取结果的方法是哪一个?方法之间好像关联性不太强啊。。。。

0 0
原创粉丝点击