Java 使用stringTemplate导出大批量数据excel(百万级)

Posted 有梦就能实现

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 使用stringTemplate导出大批量数据excel(百万级)相关的知识,希望对你有一定的参考价值。

目前java框架中能够生成excel文件的的确不少,但是,能够生成大数据量的excel框架,我倒是没发现,一般数据量大了都会出现内存溢出,所以,生成大数据量的excel文件要返璞归真,用java的基础技术,IO流来实现。    如果想用IO流来生成excel文件,必须要知道excel的文件格式内容,相当于生成html文件一样,用字符串拼接html标签保存到文本文件就可以生成一个html文件了。同理,excel文件也是可以的。怎么知道excel的文件格式呢?其实很简单,随便新建一个excel文件,双击打开,然后点击“文件”-》“另存为”,保存的类型为“xml表格”,保存之后用文本格式打开,就可以看到excel的字符串格式一览无遗了。
把下面的xml字符串复制到文本文件,然后保存为xls格式,就是一个excel文件。

  1. <?xml version="1.0"?>  
  2. <?mso-application progid="Excel.Sheet"?>  
  3. <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"  
  4. xmlns:o="urn:schemas-microsoft-com:office:office"  
  5. xmlns:x="urn:schemas-microsoft-com:office:excel"  
  6. xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"  
  7. xmlns:html="http://www.w3.org/TR/REC-html40">  
  8. <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">  
  9.   <Created>1996-12-17T01:32:42Z</Created>  
  10.   <LastSaved>2000-11-18T06:53:49Z</LastSaved>  
  11.   <Version>11.9999</Version>  
  12. </DocumentProperties>  
  13. <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">  
  14.   <RemovePersonalInformation/>  
  15. </OfficeDocumentSettings>  
  16. <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">  
  17.   <WindowHeight>4530</WindowHeight>  
  18.   <WindowWidth>8505</WindowWidth>  
  19.   <WindowTopX>480</WindowTopX>  
  20.   <WindowTopY>120</WindowTopY>  
  21.   <AcceptLabelsInFormulas/>  
  22.   <ProtectStructure>False</ProtectStructure>  
  23.   <ProtectWindows>False</ProtectWindows>  
  24. </ExcelWorkbook>  
  25. <Styles>  
  26.   <Style ss:ID="Default" ss:Name="Normal">  
  27.    <Alignment ss:Vertical="Bottom"/>  
  28.    <Borders/>  
  29.    <Font ss:FontName="宋体" x:CharSet="134" ss:Size="12"/>  
  30.    <Interior/>  
  31.    <NumberFormat/>  
  32.    <Protection/>  
  33.   </Style>  
  34. </Styles>  
  35. <Worksheet ss:Name="Sheet1">  
  36.   <Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="2" x:FullColumns="1"  
  37.    x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">  
  38.    <Column ss:AutoFitWidth="0" ss:Width="73.5"/>  
  39.    <Row>  
  40.     <Cell><Data ss:Type="String">zhangzehao</Data></Cell>  
  41.     <Cell><Data ss:Type="String">zhangzehao</Data></Cell>  
  42.    </Row>  
  43.    <Row>  
  44.     <Cell><Data ss:Type="String">zhangzehao</Data></Cell>  
  45.    </Row>  
  46.   </Table>  
  47.   <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">  
  48.    <Selected/>  
  49.    <Panes>  
  50.     <Pane>  
  51.      <Number>3</Number>  
  52.      <ActiveRow>5</ActiveRow>  
  53.      <ActiveCol>3</ActiveCol>  
  54.     </Pane>  
  55.    </Panes>  
  56.    <ProtectObjects>False</ProtectObjects>  
  57.    <ProtectScenarios>False</ProtectScenarios>  
  58.   </WorksheetOptions>  
  59. </Worksheet>  
  60. <Worksheet ss:Name="Sheet2">  
  61.   <Table ss:ExpandedColumnCount="0" ss:ExpandedRowCount="0" x:FullColumns="1"  
  62.    x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25"/>  
  63.   <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">  
  64.    <ProtectObjects>False</ProtectObjects>  
  65.    <ProtectScenarios>False</ProtectScenarios>  
  66.   </WorksheetOptions>  
  67. </Worksheet>  
  68. <Worksheet ss:Name="Sheet3">  
  69.   <Table ss:ExpandedColumnCount="0" ss:ExpandedRowCount="0" x:FullColumns="1"  
  70.    x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25"/>  
  71.   <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">  
  72.    <ProtectObjects>False</ProtectObjects>  
  73.    <ProtectScenarios>False</ProtectScenarios>  
  74.   </WorksheetOptions>  
  75. </Worksheet>  
  76. </Workbook>  
<?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>2000-11-18T06:53:49Z</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>
</Styles>
<Worksheet ss:Name="Sheet1">
  <Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="2" x:FullColumns="1"
   x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">
   <Column ss:AutoFitWidth="0" ss:Width="73.5"/>
   <Row>
    <Cell><Data ss:Type="String">zhangzehao</Data></Cell>
    <Cell><Data ss:Type="String">zhangzehao</Data></Cell>
   </Row>
   <Row>
    <Cell><Data ss:Type="String">zhangzehao</Data></Cell>
   </Row>
  </Table>
  <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
   <Selected/>
   <Panes>
    <Pane>
     <Number>3</Number>
     <ActiveRow>5</ActiveRow>
     <ActiveCol>3</ActiveCol>
    </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>

如果要生成千万级别以上的excel,除了这个关键点之外,还要控制IO流,如果有1000万记录,要迭代1000万次组装xml字符串,这样肯定占用相当大的内存,肯定内存溢出,所以,必须把组装的xml字符串分批用IO流刷新到硬盘里,如果是在web应用中,可以刷新到response中,web应用会自动把临时流保存到客户端的临时文件中,然后再一次性复制到你保存的路径。言归正传,分批刷新的话,可以迭代一批数据就flush进硬盘,同时把list,大对象赋值为空,显式调用垃圾回收器,表明要回收内存。这样的话,不管生成多大的数据量都不会出现内存溢出的,我曾经试过导出1亿的excel文件,都不会出现内存溢出,只是用了35分钟。   当然,如果要把实现做的优雅一些,在组装xml字符串的时候,可以结合模板技术来实现,我个人喜好stringtemplate这个轻量级的框架,我给出的DEMO也是采用了模板技术生成的,当然velocity和freemarker都是可以,stringbuilder也行,呵呵。    我为人比较懒,本意不是为了写个帖子的,只是想多赚点下载豆:lol1 ,这和赚钱一样谁不想?谁知道就写了那么多。同时鄙人知识寡陋,希望可以抛砖引玉。

 

 

综上:使用技术为 stringTemplate 

pom.xml:

 

  1. <dependency>  
  2.             <groupId>antlr</groupId>  
  3.             <artifactId>antlr</artifactId>  
  4.             <version>2.7.7</version>  
  5.         </dependency>  
  6.   
  7.         <dependency>  
  8.             <groupId>org.antlr</groupId>  
  9.             <artifactId>stringtemplate</artifactId>  
  10.             <version>3.2.1</version>  
  11.         </dependency>  
<dependency>
            <groupId>antlr</groupId>
            <artifactId>antlr</artifactId>
            <version>2.7.7</version>
        </dependency>

        <dependency>
            <groupId>org.antlr</groupId>
            <artifactId>stringtemplate</artifactId>
            <version>3.2.1</version>
        </dependency>

 

 

template对象:

 

  1. class Row{  
  2.     private List<String> result;  
  3.   
  4.     public List<String> getResult() {  
  5.         return result;  
  6.     }  
  7.   
  8.     public void setResult(List<String> result) {  
  9.         this.result = result;  
  10.     }  
  11. }  
  12.   
  13. class Worksheet{  
  14.     private String sheet;  
  15.       
  16.     private int columnNum;  
  17.       
  18.     private int rowNum;  
  19.   
  20.     private List<String> title;  
  21.       
  22.     private List<Row> rows;  
  23.   
  24.     public String getSheet() {  
  25.         return sheet;  
  26.     }  
  27.   
  28.     public void setSheet(String sheet) {  
  29.         this.sheet = sheet;  
  30.     }  
  31.   
  32.     public List<Row> getRows() {  
  33.         return rows;  
  34.     }  
  35.   
  36.     public void setRows(List<Row> rows) {  
  37.         this.rows = rows;  
  38.     }  
  39.   
  40.     public int getColumnNum() {  
  41.         return columnNum;  
  42.     }  
  43.   
  44.     public void setColumnNum(int columnNum) {  
  45.         this.columnNum = columnNum;  
  46.     }  
  47.   
  48.     public int getRowNum() {  
  49.         return rowNum;  
  50.     }  
  51.   
  52.     public void setRowNum(int rowNum) {  
  53.         this.rowNum = rowNum;  
  54.     }  
  55.   
  56.     public List<String> getTitle() {  
  57.         return title;  
  58.     }  
  59.   
  60.     public void setTitle(List<String> title) {  
  61.         this.title = title;  
  62.     }  
  63. }  
class Row{
    private List<String> result;

    public List<String> getResult() {
        return result;
    }

    public void setResult(List<String> result) {
        this.result = result;
    }
}

class Worksheet{
	private String sheet;
	
	private int columnNum;
	
	private int rowNum;

    private List<String> title;
	
	private List<Row> rows;

	public String getSheet() {
		return sheet;
	}

	public void setSheet(String sheet) {
		this.sheet = sheet;
	}

	public List<Row> getRows() {
		return rows;
	}

	public void setRows(List<Row> rows) {
		this.rows = rows;
	}

	public int getColumnNum() {
		return columnNum;
	}

	public void setColumnNum(int columnNum) {
		this.columnNum = columnNum;
	}

	public int getRowNum() {
		return rowNum;
	}

	public void setRowNum(int rowNum) {
		this.rowNum = rowNum;
	}

    public List<String> getTitle() {
        return title;
    }

    public void setTitle(List<String> title) {
        this.title = title;
    }
}

 

模版文件(通用):

excel 头模板

 

  1. <?xml version="1.0"?>  
  2. <?mso-application progid="Excel.Sheet"?>  
  3. <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"  
  4.  xmlns:o="urn:schemas-microsoft-com:office:office"  
  5.  xmlns:x="urn:schemas-microsoft-com:office:excel"  
  6.  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"  
  7.  xmlns:html="http://www.w3.org/TR/REC-html40">  
  8.  <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">  
  9.   <Created>1996-12-17T01:32:42Z</Created>  
  10.   <LastSaved>2013-08-02T09:21:24Z</LastSaved>  
  11.   <Version>11.9999</Version>  
  12.  </DocumentProperties>  
  13.  <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">  
  14.   <RemovePersonalInformation/>  
  15.  </OfficeDocumentSettings>  
  16.  <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">  
  17.   <WindowHeight>4530</WindowHeight>  
  18.   <WindowWidth>8505</WindowWidth>  
  19.   <WindowTopX>480</WindowTopX>  
  20.   <WindowTopY>120</WindowTopY>  
  21.   <AcceptLabelsInFormulas/>  
  22.   <ProtectStructure>False</ProtectStructure>  
  23.   <ProtectWindows>False</ProtectWindows>  
  24.  </ExcelWorkbook>  
  25.  <Styles>  
  26.   <Style ss:ID="Default" ss:Name="Normal">  
  27.    <Alignment ss:Vertical="Bottom"/>  
  28.    <Borders/>  
  29.    <Font ss:FontName="宋体" x:CharSet="134" ss:Size="12"/>  
  30.    <Interior/>  
  31.    <NumberFormat/>  
  32.    <Protection/>  
  33.   </Style>  
  34.  </Styles>  
<?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>2013-08-02T09:21:24Z</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>
 </Styles>

 

 

body模板:

 

  1.  $worksheet:{  
  2.  <Worksheet ss:Name="$it.sheet$">  
  3.   <Table ss:ExpandedColumnCount="$it.columnNum$" ss:ExpandedRowCount="$it.rowNum$" x:FullColumns="1"  
  4.    x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">  
  5.    <Row>  
  6.    $it.title:{  
  7.    <Cell><Data ss:Type="String">$it$</Data></Cell>  
  8.    }$  
  9.    </Row>  
  10.  $it.rows:{  
  11.  <Row>  
  12.  $it.result:{  
  13.  <Cell><Data ss:Type="String">$it$</Data></Cell>  
  14.  }$  
  15.    </Row>  
  16.  }$  
  17.   </Table>  
  18.  </Worksheet>  
  19. }$  
 $worksheet:{
 <Worksheet ss:Name="$it.sheet$">
  <Table ss:ExpandedColumnCount="$it.columnNum$" ss:ExpandedRowCount="$it.rowNum$" x:FullColumns="1"
   x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">
   <Row>
   $it.title:{
   <Cell><Data ss:Type="String">$it$</Data></Cell>
   }$
   </Row>
 $it.rows:{
 <Row>
 $it.result:{
 <Cell><Data ss:Type="String">$it$</Data></Cell>
 }$
   </Row>
 }$
  </Table>
 </Worksheet>
}$

 

实际处理类:传入list对象,利用反射获取对象属性名及属性值

  1.  long startTimne = System.currentTimeMillis();  
  2.   
  3.         StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");  
  4.   
  5.         //写入excel文件头部信息  
  6.         StringTemplate head =  stGroup.getInstanceOf("head");  
  7.         File file = new File("D:/output2.xls");  
  8.         PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));  
  9.         writer.print(head.toString());  
  10.         writer.flush();  
  11.   
  12.         int totalRowNum = listWinningRecordDTOList.size();  
  13.         int maxRowNum = 60000;  
  14.         int sheets = totalRowNum % 60000 == 0 ? (totalRowNum/maxRowNum) : (totalRowNum/maxRowNum +1);  
  15.         //excel单表最大行数是65535  
  16.   
  17.         List record = listWinningRecordDTOList;  
  18.         List<String> title = new ArrayList<String>();  
  19.         List<Method> getMethods = new ArrayList<Method>();  
  20.         Class<?> clazz = record.get(0).getClass();  
  21.   
  22.         Field[] fields = clazz.getDeclaredFields();  
  23.         if(fields != null && fields.length > 0){  
  24.             for(Field field : fields){  
  25.                 if(!"serialVersionUID".equals(field.getName())) {  
  26.                     title.add(field.getName());  
  27.                     getMethods.add(clazz.getDeclaredMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)));  
  28.                 }  
  29.             }  
  30.         }  
  31. //        BeanInfo beanInfo=Introspector.getBeanInfo(clazz,Object.class);  
  32. //        PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();  
  33. //        for(PropertyDescriptor propertyDescriptor : proDescrtptors){  
  34. //            title.add(propertyDescriptor.getName());  
  35. //            getMethods.add(propertyDescriptor.getReadMethod());  
  36. //        }  
  37.         int columnLength = title.size();  
  38.   
  39.         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  40.   
  41.         //写入excel文件数据信息  
  42.         for(int i=0;i<sheets;i++){  
  43.             StringTemplate body =  stGroup.getInstanceOf("body");  
  44.             Worksheet worksheet = new Worksheet();  
  45.             worksheet.setTitle(title);  
  46.             worksheet.setSheet(" "+(i+1)+" ");  
  47.             worksheet.setColumnNum(columnLength);  
  48.             worksheet.setRowNum(maxRowNum+1);  
  49.             List<Row> rows = new ArrayList<Row>();  
  50.             int startIndex = i*maxRowNum;  
  51.             int endIndex = Math.min((i+1)*maxRowNum -1,totalRowNum-1);  
  52.             for(int j=startIndex;j<=endIndex;j++){  
  53.                 Row row = new Row();  
  54.                 List<String> result = new ArrayList<String>(columnLength);  
  55.                 for(int n=0;n<columnLength;n++){  
  56.                     Object value = getMethods.get(n).invoke(record.get(j));  
  57.                     if(value == null){  
  58.                         result.add("");  
  59.                     }else{  
  60.                         if(value instanceof Date){  
  61.                             result.add(sdf.format((Date)value));  
  62.                         }else{  
  63.                             result.add(value.toString());  
  64.                         }  
  65.                     }  
  66.   
  67.                 }  
  68.                 row.setResult(result);  
  69.                 rows.add(row);  
  70.             }  
  71.             worksheet.setRows(rows);  
  72.             body.setAttribute("worksheet", worksheet);  
  73.             writer.print(body.toString());  
  74.             writer.flush();  
  75.             rows.clear();  
  76.             rows = null;  
  77.             worksheet = null;  
  78.             body = null;  
  79.             Runtime.getRuntime().gc();  
  80.             System.out.println("正在生成excel文件的 sheet"+(i+1));  
  81.         }  
  82.   
  83.         //写入excel文件尾部  
  84.         writer.print("</Workbook>");  
  85.         writer.flush();  
  86.         writer.close();  
  87.         System.out.println("生成excel文件完成");  
  88.         long endTime = System.currentTimeMillis();  
  89.         System.out.println("用时="+((endTime-startTimne)/1000)+"秒");  
 long startTimne = System.currentTimeMillis();

        StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");

        //写入excel文件头部信息
        StringTemplate head =  stGroup.getInstanceOf("head");
        File file = new File("D:/output2.xls");
        PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));
        writer.print(head.toString());
        writer.flush();

        int totalRowNum = listWinningRecordDTOList.size();
        int maxRowNum = 60000;
        int sheets = totalRowNum % 60000 == 0 ? (totalRowNum/maxRowNum) : (totalRowNum/maxRowNum +1);
        //excel单表最大行数是65535

        List record = listWinningRecordDTOList;
        List<String> title = new ArrayList<String>();
        List<Method> getMethods = new ArrayList<Method>();
        Class<?> clazz = record.get(0).getClass();

        Field[] fields = clazz.getDeclaredFields();
        if(fields != null && fields.length > 0){
            for(Field field : fields){
                if(!"serialVersionUID".equals(field.getName())) {
                    title.add(field.getName());
                    getMethods.add(clazz.getDeclaredMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)));
                }
            }
        }
//        BeanInfo beanInfo=Introspector.getBeanInfo(clazz,Object.class);
//        PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();
//        for(PropertyDescriptor propertyDescriptor : proDescrtptors){
//            title.add(propertyDescriptor.getName());
//            getMethods.add(propertyDescriptor.getReadMethod());
//        }
        int columnLength = title.size();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //写入excel文件数据信息
        for(int i=0;i<sheets;i++){
            StringTemplate body =  stGroup.getInstanceOf("body");
            Worksheet worksheet = new Worksheet();
            worksheet.setTitle(title);
            worksheet.setSheet(" "+(i+1)+" ");
            worksheet.setColumnNum(columnLength);
            worksheet.setRowNum(maxRowNum+1);
            List<Row> rows = new ArrayList<Row>();
            int startIndex = i*maxRowNum;
            int endIndex = Math.min((i+1)*maxRowNum -1,totalRowNum-1);
            for(int j=startIndex;j<=endIndex;j++){
                Row row = new Row();
                List<String> result = new ArrayList<String>(columnLength);
                for(int n=0;n<columnLength;n++){
                    Object value = getMethods.get(n).invoke(record.get(j));
                    if(value == null){
                        result.add("");
                    }else{
                        if(value instanceof Date){
                            result.add(sdf.format((Date)value));
                        }else{
                            result.add(value.toString());
                        }
                    }

                }
                row.setResult(result);
                rows.add(row);
            }
            worksheet.setRows(rows);
            body.setAttribute("worksheet", worksheet);
            writer.print(body.toString());
            writer.flush();
            rows.clear();
            rows = null;
            worksheet = null;
            body = null;
            Runtime.getRuntime().gc();
            System.out.println("正在生成excel文件的 sheet"+(i+1));
        }

        //写入excel文件尾部
        writer.print("</Workbook>");
        writer.flush();
        writer.close();
        System.out.println("生成excel文件完成");
        long endTime = System.currentTimeMillis();
        System.out.println("用时="+((endTime-startTimne)/1000)+"秒");

 

整理后的公用类:

 

  1. import org.antlr.stringtemplate.StringTemplate;  
  2. import org.antlr.stringtemplate.StringTemplateGroup;  
  3.   
  4. import java.io.*;  
  5. import java.lang.reflect.Field;  
  6. import java.lang.reflect.InvocationTargetException;  
  7. import java.lang.reflect.Method;  
  8. import java.text.SimpleDateFormat;  
  9. import java.util.ArrayList;  
  10. import java.util.Date;  
  11. import java.util.List;  
  12.   
  13. /** 
  14.  * Created by Administrator on 2016/2/25. 
  15.  */  
  16. public class ExcelStUtil {  
  17.   
  18.     public static void export(OutputStream outputStream,List target) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {  
  19.         long startTime = System.currentTimeMillis();  
  20.   
  21.         StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");  
  22.         //解决可能发生的中文乱码  
  23.         stGroup.setFileCharEncoding("UTF-8");  
  24.         //写入excel文件头部信息  
  25.         StringTemplate head =  stGroup.getInstanceOf("st/head");  
  26.         PrintWriter writer = new PrintWriter(new BufferedOutputStream(outputStream));  
  27.         writer.print(head.toString());  
  28.         writer.flush();  
  29.   
  30.         int totalRowNum = target.size();  
  31.         int maxRowNum = 60000;  
  32.         int sheets = totalRowNum % 60000 == 0 ? (totalRowNum/maxRowNum) : (totalRowNum/maxRowNum +1);  
  33.         //excel单表最大行数是65535  
  34.   
  35.         List record = target;  
  36.         List<String> title = new ArrayList<String>();  
  37.         List<Method> getMethods = new ArrayList<Method>();  
  38.         Class<?> clazz = record.get(0).getClass();  
  39.   
  40.         Field[] fields = clazz.getDeclaredFields();  
  41.         if(fields != null && fields.length > 0){  
  42.             for(Field field : fields){  
  43.                 if(!"serialVersionUID".equals(field.getName())) {  
  44.                     title.add(field.getName());  
  45.                     getMethods.add(clazz.getDeclaredMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)));  
  46.                 }  
  47.             }  
  48.         }  
  49. //        BeanInfo beanInfo=Introspector.getBeanInfo(clazz,Object.class);  
  50. //        PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();  
  51. //        for(PropertyDescriptor propertyDescriptor : proDescrtptors){  
  52. //            title.add(propertyDescriptor.getName());  
  53. //            getMethods.add(propertyDescriptor.getReadMethod());  
  54. //        }  
  55.         int columnLength = title.size();  
  56.   
  57.         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  58.   
  59.         //写入excel文件数据信息  
  60.         for(int i=0;i<sheets;i++){  
  61.             StringTemplate body =  stGroup.getInstanceOf("st/body");  
  62.             Worksheet worksheet = new Worksheet();  
  63.             worksheet.setTitle(title);  
  64.             worksheet.setSheet(" "+(i+1)+" ");  
  65.             worksheet.setColumnNum(columnLength);  
  66.             worksheet.setRowNum(maxRowNum+1);  
  67.             List<Row> rows = new ArrayList<Row>();  
  68.             int startIndex = i*maxRowNum;  
  69.             int endIndex = Math.min((i+1)*maxRowNum -1,totalRowNum-1);  
  70.             for(int j=startIndex;j<=endIndex;j++){  
  71.                 Row row = new Row();  
  72.                 List<String> result = new ArrayList<String>(columnLength);  
  73.                 for(int n=0;n<columnLength;n++){  
  74.                     Object value = getMethods.get(n).invoke(record.get(j));  
  75.                     if(value == null){  
  76.                         result.add("");  
  77.                     }else{  
  78.                         if(value instanceof Date){  
  79.                             result.add(sdf.format((Date)value));  
  80.                         }else{  
  81.                             result.add(value.toString());  
  82.                         }  
  83.                     }  
  84.   
  85.                 }  
  86.                 row.setResult(result);  
  87.                 rows.add(row);  
  88.             }  
  89.             worksheet.setRows(rows);  
  90.             body.setAttribute("worksheet", worksheet);  
  91.             writer.print(body.toString());  
  92.             writer.flush();  
  93.             rows.clear();  
  94.             rows = null;  
  95.             worksheet = null;  
  96.             body = null;  
  97.             Runtime.getRuntime().gc();  
  98.             System.out.println("正在生成excel文件的 sheet"+(i+1));  
  99.         }  
  100.   
  101.         //写入excel文件尾部  
  102.         writer.print("</Workbook>");  
  103.         writer.flush();  
  104.         writer.close();  
  105.         System.out.println("生成excel文件完成");  
  106.         long endTime = System.currentTimeMillis();  
  107.         System.out.println("用时="+((endTime-startTime)/1000)+"秒");  
  108.     }  
  109.   
  110.     public static void main(String[] args) throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {  
  111.         System.out.println(Thread.currentThread().getContextClassLoader().getResource("").getPath());  
  112.         System.out.println(ExcelStUtil.class.getResource("").getPath());  
  113.         System.out.println(ExcelStUtil.class.getClassLoader().getResource("").getPath());  
  114.         List<Sample> result = new ArrayList<Sample>();  
  115.         for(int i=0;i<100;i++){  
  116.             result.add(new Sample("放大双方的"+String.valueOf(i),String.valueOf(i)));  
  117.         }  
  118.         //OutputStream outputStream = new FileOutputStream("D:/output2.xls");  
  119.         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
  120.         ExcelStUtil.export(byteArrayOutputStream,result);  
  121.         //ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());  
  122.         //解决可能发生的中文乱码  
  123.         ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toString().getBytes("UTF-8"));  
  124.   
  125.         File file = new File("D:/output2.xls");  
  126.         OutputStream output = new FileOutputStream(file);  
  127.         BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);  
  128.         //bufferedOutput.write(byteArrayOutputStream.toByteArray());  
  129.         bufferedOutput.write(byteArrayOutputStream.toString().getBytes("UTF-8"));  
  130.         bufferedOutput.flush();  
  131.         bufferedOutput.close();  
  132.   
  133.     }  
  134. }  
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2016/2/25.
 */
public class ExcelStUtil {

    public static void export(OutputStream outputStream,List target) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        long startTime = System.currentTimeMillis();

        StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");
        //解决可能发生的中文乱码
        stGroup.setFileCharEncoding("UTF-8");
        //写入excel文件头部信息
        StringTemplate head =  stGroup.getInstanceOf("st/head");
        PrintWriter writer = new PrintWriter(new BufferedOutputStream(outputStream));
        writer.print(head.toString());
        writer.flush();

        int totalRowNum = target.size();
        int maxRowNum = 60000;
        int sheets = totalRowNum % 60000 == 0 ? (totalRowNum/maxRowNum) : (totalRowNum/maxRowNum +1);
        //excel单表最大行数是65535

        List record = target;
        List<String> title = new ArrayList<String>();
        List<Method> getMethods = new ArrayList<Method>();
        Class<?> clazz = record.get(0).getClass();

        Field[] fields = clazz.getDeclaredFields();
        if(fields != null && fields.length > 0){
            for(Field field : fields){
                if(!"serialVersionUID".equals(field.getName())) {
                    title.add(field.getName());
                    getMethods.add(clazz.getDeclaredMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)));
                }
            }
        }
//        BeanInfo beanInfo=Introspector.getBeanInfo(clazz,Object.class);
//        PropertyDescriptor[] proDescrtptors=beanInfo.getPropertyDescriptors();
//        for(PropertyDescriptor propertyDescriptor : proDescrtptors){
//            title.add(propertyDescriptor.getName());
//            getMethods.add(propertyDescriptor.getReadMethod());
//        }
        int columnLength = title.size();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //写入excel文件数据信息
        for(int i=0;i<sheets;i++){
            StringTemplate body =  stGroup.getInstanceOf("st/body");
            Worksheet worksheet = new Worksheet();
            worksheet.setTitle(title);
            worksheet.setSheet(" "+(i+1)+" ");
            worksheet.setColumnNum(columnLength);
            worksheet.setRowNum(maxRowNum+1);
            List<Row> rows = new ArrayList<Row>();
            int startIndex = i*maxRowNum;
            int endIndex = Math.min((i+1)*maxRowNum -1,totalRowNum-1);
            for(int j=startIndex;j<=endIndex;j++){
                Row row = new Row();
                List<String> result = new ArrayList<String>(columnLength);
                for(int n=0;n<columnLength;n++){
                    Object value = getMethods.get(n).invoke(record.get(j));
                    if(value == null){
                        result.add("");
                    }else{
                        if(value instanceof Date){
                            result.add(sdf.format((Date)value));
                        }else{
                            result.add(value.toString());
                        }
                    }

                }
                row.setResult(result);
                rows.add(row);
            }
            worksheet.setRows(rows);
            body.setAttribute("worksheet", worksheet);
            writer.print(body.toString());
            writer.flush();
            rows.clear();
            rows = null;
            worksheet = null;
            body = null;
            Runtime.getRuntime().gc();
            System.out.println("正在生成excel文件的 sheet"+(i+1));
        }

        //写入excel文件尾部
        writer.print("</Workbook>");
        writer.flush();
        writer.close();
        System.out.println("生成excel文件完成");
        long endTime = System.currentTimeMillis();
        System.out.println("用时="+((endTime-startTime)/1000)+"秒");
    }

    public static void main(String[] args) throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        System.out.println(Thread.currentThread().getContextClassLoader().getResource("").getPath());
        System.out.println(ExcelStUtil.class.getResource("").getPath());
        System.out.println(ExcelStUtil.class.getClassLoader().getResource("").getPath());
        List<Sample> result = new ArrayList<Sample>();
        for(int i=0;i<100;i++){
            result.add(new Sample("放大双方的"+String.valueOf(i),String.valueOf(i)));
        }
        //OutputStream outputStream = new FileOutputStream("D:/output2.xls");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ExcelStUtil.export(byteArrayOutputStream,result);
        //ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        //解决可能发生的中文乱码
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toString().getBytes("UTF-8"));

        File file = new File("D:/output2.xls");
        OutputStream output = new FileOutputStream(file);
        BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
        //bufferedOutput.write(byteArrayOutputStream.toByteArray());
        bufferedOutput.write(byteArrayOutputStream.toString().getBytes("UTF-8"));
        bufferedOutput.flush();
        bufferedOutput.close();

    }
}

以上是关于Java 使用stringTemplate导出大批量数据excel(百万级)的主要内容,如果未能解决你的问题,请参考以下文章

java导出大批量(百万以上)数据的excel文件

excel导入导出

php Excel 导出大批量数据解决方案

POI 导出大批量数据的Excel

SQL Server通过BCP进行大批量数据导入导出

StringTemplate 和 FreeMarker 之间的主要区别是啥?