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

  1. Java 导出大批量数据excel(百万级)(转载)

    参考资料:http://bbs.51cto.com/thread-1074293-1-1.html                 http://bbs.51cto.com/viewthread.ph ...

  2. java使用freemarker导出复杂的excel表格

    正常导出excel表格使用的poi,但是导出复杂的excel有点困难,但是可以使用freemaker模板来导出复杂的excel. 1.都是先生成一个Excel表格的模板,最好是增加一行数据.具体看图里 ...

  3. 利用ADO.NET导出大批量数据

    2015年12月,XX项目中需要做一个数据导出功能,当时所有页面的到处功能均已经实现,但有个页面数据量太大,导出过程中导出页面直接卡死.不得已我准备选用ADO.NET来重新完成这个功能,因为考虑到越偏 ...

  4. sql server导出大批量数据

    使用sqlserver导出数据的时候,如果数据量大于65536那么就要使用xlsx,最大行数为104万 如果导出的时候报错,则需要在本机安装以下程序: https://www.cnblogs.com/ ...

  5. C# 利用ADO.NET导出大批量数据

    2015年12月,XX项目中需要做一个数据导出功能,当时所有页面的到处功能均已经实现,但有个页面数据量太大,导出过程中导出页面直接卡死.不得已我准备选用ADO.NET来重新完成这个功能,因为考虑到越偏 ...

  6. jsp导出table数据excel表

    <html> <head> <meta http-equiv="content-Type" content="text/html;chars ...

  7. Java使用freemarker导出word和excel

    www.linxiaosheng.com/post/2013-12-05/40060346181 https://github.com/upyun/java-sdk

  8. SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...

  9. SQL Server百万级大数据量删除

    删除一个表中的部分数据,数据量百万级. 一般delete from 表 delete from 表名 where 条件: 此操作可能导致,删除操作执行的时间长:日志文件急速增长: 针对此情况处理 de ...

随机推荐

  1. CharacterRangeTable

    转载:https://github.com/jacoco/jacoco/wiki/CharacterRangeTable This page discusses a not yet available ...

  2. 【转】Spark:一个高效的分布式计算系统

    原文地址:http://tech.uc.cn/?p=2116 概述 什么是Spark Spark是UC Berkeley AMP lab所开源的类Hadoop MapReduce的通用的并行计算框架, ...

  3. C/C++ -- Gui编程 -- Qt库的使用 -- 使用图片与动画

    QWidget工程 #include "mywidget.h" #include "ui_mywidget.h" #include <QLabel> ...

  4. mongodb-导出数据到csv文件或json文件

    在mongodb的bin目录下, 有一个mongoexport, 可用于数据的导出 [wenbronk@localhost bin]$ ./mongoexport --help Usage: mong ...

  5. vscode 常用配置

    { "workbench.iconTheme": "vscode-icons", "editor.tabSize": 2, "ed ...

  6. 正则表达式匹配可以更快更简单 (but is slow in Java, Perl, PHP, Python, Ruby, ...)

    source: https://swtch.com/~rsc/regexp/regexp1.html translated by trav, travmymail@gmail.com 引言 下图是两种 ...

  7. Firebird shadow

    火鸟数据库的shadow,即实时镜像. 主库发生变化,shadow也跟随变化,防止任何意外造成主库损坏无法使用,当然shadow可以有多个. 1.创建shadow的准备:修改Firebird.conf ...

  8. java并发编程的艺术(四)---ConcurrentHashMap原理解析

    本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...

  9. Spring Boot统一异常处理方案示例

    一.异常处理的原则 1.调用方法的时候返回布尔值来代替返回null,这样可以 NullPointerException.由于空指针是java异常里最恶心的异常. 2. catch块里别不写代码.空ca ...

  10. 第二十四天- 模块导入 import from xxx import xxx

    # 模块:# 模块就是⼀个包含了python定义和声明的⽂件,⽂件名就是模块的名字加上.py后缀# 换句话说我们⽬前写的所有的py⽂件都可以看成是⼀个模块# 为何用模块:写大项目时,把相关的功能进⾏分 ...