Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 1075|回复: 0

关于poi导出大数据量EXCEL导出缓慢的解决方案--生成xml格式的表格文件(注意xls格式为03 07下格式会不一样)

[复制链接]
  • TA的每日心情
    奋斗
    5 天前
  • 签到天数: 803 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726482
    发表于 2021-4-27 12:27:19 | 显示全部楼层 |阅读模式

    今天遇到了一个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 }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-11-22 03:26 , Processed in 3.140592 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表