码迷,mamicode.com
首页 > 其他好文 > 详细

关于poi导出大数据量EXCEL导出缓慢的解决方案--生成xml格式的表格文件

时间:2015-03-04 16:28:58      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

今天遇到了一个POI导出EXCEL文件结果文件大小太大导致系统运行缓慢的问题。想到了使用输出XML格式的表格来完成。

首先,我们需要理解一下为什么POI导出EXCEL文件会导致文件大小变大。最主要的原因应该是POI变成中经常会对无关的单元格设置属性。例如:一个EXCEL工作表的最大列数为256,我们只使用10列。而编程时经常会将256列全部渲染格式,造成很大的资源浪费。当然应该还有其他很多原因也会造成表格变大。

使用这个方案的前提是对于表格的格式要求不高,因为使用的是自己的工具,没有POI优化了那么多格式。

接下来我们看一下这个方法的理论依据:

我们新建一个aa.xls。内容就少一点,方便观察。内容如下:

技术分享

使用文件--》另存为--》.xml 得到一个 aa.xml。

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">
 <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
  <Created>1996-12-17T01:32:42Z</Created>
  <LastSaved>2015-03-04T02:45:33Z</LastSaved>
  <Version>11.9999</Version>
 </DocumentProperties>
 <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
  <RemovePersonalInformation/>
 </OfficeDocumentSettings>
 <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
  <WindowHeight>4530</WindowHeight>
  <WindowWidth>8505</WindowWidth>
  <WindowTopX>480</WindowTopX>
  <WindowTopY>120</WindowTopY>
  <AcceptLabelsInFormulas/>
  <ProtectStructure>False</ProtectStructure>
  <ProtectWindows>False</ProtectWindows>
 </ExcelWorkbook>
 <Styles>
  <Style ss:ID="Default" ss:Name="Normal">
   <Alignment ss:Vertical="Bottom"/>
   <Borders/>
   <Font ss:FontName="宋体" x:CharSet="134" ss:Size="12"/>
   <Interior/>
   <NumberFormat/>
   <Protection/>
  </Style>
  <Style ss:ID="s21">
   <Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
  </Style>
 </Styles>
 <Worksheet ss:Name="Sheet1">
  <Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="12" x:FullColumns="1"
   x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">
   <Row>
    <Cell ss:StyleID="s21"><Data ss:Type="String">A</Data></Cell>
    <Cell ss:StyleID="s21"><Data ss:Type="String">B</Data></Cell>
    <Cell ss:StyleID="s21"><Data ss:Type="String">C</Data></Cell>
    <Cell ss:StyleID="s21"><Data ss:Type="String">D</Data></Cell>
    <Cell ss:StyleID="s21"><Data ss:Type="String">E</Data></Cell>
   </Row>
   <Row ss:Index="4">
    <Cell ss:Index="2"><Data ss:Type="String">aaa</Data></Cell>
   </Row>
   <Row ss:Index="8">
    <Cell ss:Index="4"><Data ss:Type="String">ddd</Data></Cell>
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="String">sss</Data></Cell>
   </Row>
   <Row ss:Index="11">
    <Cell><Data ss:Type="String">fddd</Data></Cell>
   </Row>
   <Row>
    <Cell ss:Index="4"><Data ss:Type="String">fff</Data></Cell>
   </Row>
  </Table>
  <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
   <Print>
    <ValidPrinterInfo/>
    <PaperSizeIndex>9</PaperSizeIndex>
    <HorizontalResolution>200</HorizontalResolution>
    <VerticalResolution>200</VerticalResolution>
   </Print>
   <Selected/>
   <Panes>
    <Pane>
     <Number>3</Number>
     <RangeSelection>R1C1:R12C5</RangeSelection>
    </Pane>
   </Panes>
   <ProtectObjects>False</ProtectObjects>
   <ProtectScenarios>False</ProtectScenarios>
  </WorksheetOptions>
 </Worksheet>
 <Worksheet ss:Name="Sheet2">
  <Table ss:ExpandedColumnCount="0" ss:ExpandedRowCount="0" x:FullColumns="1"
   x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25"/>
  <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
   <ProtectObjects>False</ProtectObjects>
   <ProtectScenarios>False</ProtectScenarios>
  </WorksheetOptions>
 </Worksheet>
 <Worksheet ss:Name="Sheet3">
  <Table ss:ExpandedColumnCount="0" ss:ExpandedRowCount="0" x:FullColumns="1"
   x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25"/>
  <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
   <ProtectObjects>False</ProtectObjects>
   <ProtectScenarios>False</ProtectScenarios>
  </WorksheetOptions>
 </Worksheet>
</Workbook>

 

可以看到 其实输出文件就是一个标准的xml文档。而且该文档还有一个很特殊的地方就是:文档的后缀名一旦修改为.XLS那么直接就可以生成一个表格文件。所以,如果我们找到XML的对应关系就可以通过输出XML文件,重命名为.XLS文件。完成减小EXCEL大小的目的。

最后贴上一个测试的类 TEST.java 完成了基本对应关系。但是还有很多需要摸索的地方:例如格式,函数。希望对大家有所帮助。

  

  1 package com.sun;
  2 import java.io.BufferedWriter;
  3 import java.io.File;
  4 import java.io.FileNotFoundException;
  5 import java.io.FileOutputStream;
  6 import java.io.IOException;
  7 import java.io.OutputStreamWriter;
  8 
  9 
 10 public class Test {
 11      public static void main(String[] args) {  
 12             StringBuffer sb = new StringBuffer();  
 13             try {  
 14                 OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(new File("d://aa.xls")),"UTF-8");
 15                   BufferedWriter output = new BufferedWriter(write); 
 16                 sb.append("<?xml version=\"1.0\"?>");  
 17                 sb.append("\n");  
 18                 sb.append("<?mso-application progid=\"Excel.Sheet\"?>");  
 19                 sb.append("\n");  
 20                 sb.append("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"");  
 21                 sb.append("\n");  
 22                 sb.append("  xmlns:o=\"urn:schemas-microsoft-com:office:office\"");  
 23                 sb.append("\n");  
 24                 sb.append(" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");  
 25                 sb.append("\n");  
 26                 sb.append(" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"");  
 27                 sb.append("\n");  
 28                 sb.append(" xmlns:html=\"http://www.w3.org/TR/REC-html40\">");  
 29                 sb.append("\n");  
 30                 sb.append(" <Styles>\n");  
 31                 sb.append("  <Style ss:ID=\"Default\" ss:Name=\"Normal\">\n");  
 32                 sb.append("   <Alignment ss:Vertical=\"Center\"/>\n");  
 33                 sb.append("   <Borders/>\n");  
 34                 sb.append("   <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"12\"/>\n");  
 35                 sb.append("   <Interior/>\n");  
 36                 sb.append("   <NumberFormat/>\n");  
 37                 sb.append("   <Protection/>\n");  
 38                 sb.append("  </Style>\n");  
 39                 sb.append(" </Styles>\n");  
 40                 //行数
 41                 int rowNum = 20;  
 42                 
 43                 int currentRecord = 0;  
 44                 //总数据量
 45                 int total = 2000;  
 46                 //列数
 47                 int columnNum = 10;  
 48                 //第一个工作表 
 49                 sb.append("<Worksheet ss:Name=\"Sheet0\">");  
 50                 sb.append("\n");  
 51                 sb.append("<Table ss:ExpandedColumnCount=\"" + columnNum  
 52                         + "\" ss:ExpandedRowCount=\"" + rowNum  
 53                         + "\" x:FullColumns=\"1\" x:FullRows=\"1\">");  
 54                 sb.append("\n");  
 55                 for (int i = 0; i < total; i++) {  
 56                     if ((currentRecord == rowNum  
 57                             || currentRecord > rowNum || currentRecord == 0)  
 58                             && i != 0) {// 一个sheet写满  
 59                         currentRecord = 0;  
 60                         output.write(sb.toString());  
 61                         sb.setLength(0);  
 62                         sb.append("</Table>");  
 63                         sb.append("<WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">");  
 64                         sb.append("\n");  
 65                         sb.append("<ProtectObjects>False</ProtectObjects>");  
 66                         sb.append("\n");  
 67                         sb.append("<ProtectScenarios>False</ProtectScenarios>");  
 68                         sb.append("\n");  
 69                         sb.append("</WorksheetOptions>");  
 70                         sb.append("\n");  
 71                         sb.append("</Worksheet>");  
 72                         sb.append("<Worksheet ss:Name=\"Sheet" + i / rowNum  
 73                                 + "\">");  
 74                         sb.append("\n");  
 75                         sb.append("<Table ss:ExpandedColumnCount=\"" + columnNum  
 76                                 + "\" ss:ExpandedRowCount=\"" + rowNum  
 77                                 + "\" x:FullColumns=\"1\" x:FullRows=\"1\">");  
 78                         sb.append("\n");  
 79                     }  
 80                     sb.append("<Row>");  
 81                     for (int j = 0; j < columnNum; j++) {  
 82                         sb.append("<Cell><Data ss:Type=\"String\">第"+(i+1)+"列第"+(j+1)+"行</Data></Cell>");  
 83                         sb.append("\n");  
 84                     }  
 85                     sb.append("</Row>");  
 86                     //每三百行数据批量提交一次
 87                     if (i % 300 == 0) {  
 88                         System.out.println("提交了");  
 89                         output.write(sb.toString());  
 90                         output.flush();  
 91                         sb.setLength(0);  
 92                     }  
 93                     sb.append("\n");  
 94                     currentRecord++;  
 95                 }  
 96                 output.write(sb.toString());  
 97                 sb.setLength(0);  
 98                 sb.append("</Table>");  
 99                 sb.append("<WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">");  
100                 sb.append("\n");  
101                 sb.append("<ProtectObjects>False</ProtectObjects>");  
102                 sb.append("\n");  
103                 sb.append("<ProtectScenarios>False</ProtectScenarios>");  
104                 sb.append("\n");  
105                 sb.append("</WorksheetOptions>");  
106                 sb.append("\n");  
107                 sb.append("</Worksheet>");  
108                 sb.append("</Workbook>");  
109                 sb.append("\n");  
110                 output.write(sb.toString());  
111                 output.flush();  
112                 output.close();  
113             } catch (FileNotFoundException e) {  
114                 e.printStackTrace();  
115             } catch (IOException e) {  
116                 e.printStackTrace();  
117             }  
118         }  
119 }

 

关于poi导出大数据量EXCEL导出缓慢的解决方案--生成xml格式的表格文件

标签:

原文地址:http://www.cnblogs.com/reload-sun/p/4313461.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!