您的当前位置:首页java导出Excel大数据量,自己经验总结!

java导出Excel大数据量,自己经验总结!

来源:小侦探旅游网
java导出Excel⼤数据量,⾃⼰经验总结!

出处:

分析导出实现代码,XLSX⽀持:

/**

* ⽣成XLSX,2007版本的excel,每个sheet⽆6.5W的⾏数限制,但是到了⼀定数量,可能内存溢出, * 次⽅法适合在预计10W以下的数据导出时使⽤,本机测试,14W可以导出。列数量在8列左右 *

* @param fileOut * 输出流

* @param sheetMap

* 要设置的数据信息 * @throws SQLException */

public static void createXSLXByResultSet(OutputStream fileOut, WriteXLSBean... beans) throws SQLException { try {

//重点 Workbook

Workbook wb = new XSSFWorkbook();

for (int i = 0, len = beans.length; i < len; i++) { WriteXLSBean xlsBean = beans[i];

Sheet sheet = wb.createSheet(xlsBean.getSheetName()); ResultSet rs = xlsBean.getRs();

ResultSetMetaData rsmd = rs.getMetaData(); TypeHandlerRegistry tr = BeanContext.tr; Map th = xlsBean.getTh(); int index = 0; while (rs.next()) {

long t1 = System.currentTimeMillis();

org.apache.poi.ss.usermodel.Row row = sheet .createRow(index);

for (int j = 0, numberOfColumns = rsmd.getColumnCount(); j < numberOfColumns; j++) { String key = rsmd.getColumnLabel(j + 1).toLowerCase(); if (th.containsKey(key)) {

TypeHandler type = tr.getTypeHandler(JdbcType .forCode(rsmd.getColumnType(j + 1))); Object obj = type.getResult(rs, key);

row.createCell(j).setCellValue(obj == null ? \"\" : obj.toString()); } }

System.out.println(index + \" :\"

+ (System.currentTimeMillis() - t1)); index++; } }

//重点 Workbook wb.write(fileOut);

} catch (IOException e) { e.printStackTrace();

throw new ServiceRunTimeException(\"⽣产xls⽂档错误\ } finally { } }

在上⾯ 标注了重点的两处,分别是:1.构建⼀个Excel对象

2.将该对象写⼊⼀个OutPutStream

⽽在构建过程中,没有地⽅写⼊OutPutSteam ,也就是说必须在内存中构建整个 Excel,才能进⾏写出操作,在⼤数据量情况下,这样将导致所有数据加载到内存中,⽽不能输出,导致最后 内存溢出。根据运⾏环境不⽤,可能内存溢出的 情况不同根据情况,如果数据量达到10W以上,建议使⽤

1、多个Excel,每个Excel⼀个Sheet,因为所有Sheet都是Workbook的组成部分。如果不分多个Excel,即使分Sheet也没⽤,

2、每个Excel中列数适中,⽐如: 5W⾏每个Excel档,实现分多次导出和分页查询原理⼀样

3、对多个Excel导出到⼀个临时⽬录,并通过程序压缩,然后提供给客户下载

2003版通过数据库结果存到List中,然后进⾏⽣产:Table 就是List Row 是Map

/**

* ⽣产xls,2003版本的excel,每个sheet有6.5W的⾏数限制 *

* @param fileOut

* 输出流,未关闭 * @param sheetMap

* 要导出的数据信息 */

public static void createXSLByMap(OutputStream fileOut, Map>> sheetMap) { try {

HSSFWorkbook wb = new HSSFWorkbook(); Set keys = sheetMap.keySet();

for (Iterator iterator = keys.iterator(); iterator .hasNext();) {

String SheetKey = iterator.next();

Sheet sheet = wb.createSheet(SheetKey);

List> sheetRows = sheetMap.get(SheetKey); for (int i = 0, len = sheetRows.size(); i < len; i++) { Map cellMap = sheetRows.get(i); Set cellSet = cellMap.keySet();

org.apache.poi.ss.usermodel.Row row = sheet.createRow(i); int j = 0;

for (Iterator iterCell = cellSet.iterator(); iterCell .hasNext(); j++) {

String cellKey = iterCell.next(); Object obj = cellMap.get(cellKey);

row.createCell(j).setCellValue(obj == null ? \"\"

: obj.toString()); } } }

wb.write(fileOut);

} catch (IOException e) { e.printStackTrace();

throw new ServiceRunTimeException(\"⽣产xls⽂档错误\ } finally { } }

新版本 POI+office 2007版本excel可以导出⼏⼗万条⽽不内存溢出,详细见:

导出⼤量数据到 excel 的 xlsx⽂件

static String src=\"abcdefafslfelgtryjukjhgfdadertjDSFGHJKJGHFERTUIOabcdefafslfelgtryjukjhgfdadertjDSFGHJKdertjDSFGHJKJGHFERTUIOabcdefafslfelgtryjukjhgfdadertjDSFGHJKJGHFERTUIO\"; public static void main(String[] args) throws Throwable {

SXSSFWorkbook wb = new SXSSFWorkbook(100); // 这⾥100是在内存中的数量,如果⼤于此数量时,会写到硬盘,以避免在内存导致内存溢出 Sheet sh = wb.createSheet();

for (int rownum = 0; rownum < 1000000; rownum++) { Row row = sh.createRow(rownum);

for (int cellnum = 0; cellnum < 10; cellnum++) { Cell cell = row.createCell(cellnum);

String address = new CellReference(cell).formatAsString();

cell.setCellValue(address+src.substring(rownum%10*10+1, (rownum%10+1)*10)); } }

File file = new File(\"F:/aa.xlsx\"); file.createNewFile();

FileOutputStream out = new FileOutputStream(file); wb.write(out); out.close(); }

内存使⽤情况:

根据以上前辈经验,⾃⼰在结果⾃⾝需求考虑,整合出⼀个⼯具。解决了excle表.xls格式⾏数65535⾏的限制。我实现的形式是导出⼀张表,⾥⾯有多页(我是已65000为⼀页)

这⾥是⽤反射来使⽤所有传⼊进⾏的实体的属性的值。这⾥只针对String和基本数据类型。如有⾃⼰定义的类型需要⾃⼰加上。

package com.tommy.fundation.util;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Date;import java.util.List;

public class RelectUtil {

public static List reflectEntity(T model,Class cals) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchFieldException{ List list = new ArrayList();

Field[] field = model.getClass().getDeclaredFields(); //获取实体类的所有属性,返回Field数组 for(int j=0 ; jString nam = field[j].getName(); //获取属性的名字 String name = nam;

name = name.substring(0,1).toUpperCase()+name.substring(1); String type = field[j].getGenericType().toString(); //获取属性的类型

if(type.equals(\"class java.lang.String\")){ //如果type是类类型,则前⾯包含\"class \",后⾯跟类名 Method m = model.getClass().getMethod(\"get\"+name);

String value = (String) m.invoke(model); //调⽤getter⽅法获取属性值 if(value != null){ list.add(value); }else{

list.add(\"\"); } }

if(type.equals(\"class java.lang.Integer\")){

Method m = model.getClass().getMethod(\"get\"+name); Integer value = (Integer) m.invoke(model); if(value != null){ list.add(value); }else{

list.add(\"\"); } }

if(type.equals(\"class java.lang.Short\")){

Method m = model.getClass().getMethod(\"get\"+name); Short value = (Short) m.invoke(model); if(value != null){

list.add(value); }else{

list.add(\"\"); }

}

if(type.equals(\"class java.lang.Double\")){

Method m = model.getClass().getMethod(\"get\"+name); Double value = (Double) m.invoke(model); if(value != null){ list.add(value); }else{

list.add(\"\"); }

}

if(type.equals(\"class java.lang.Boolean\")){

Method m = model.getClass().getMethod(\"get\"+name); Boolean value = (Boolean) m.invoke(model); if(value != null){ list.add(value); }else{

list.add(\"\"); } }

if(type.equals(\"class java.util.Date\")){

Method m = model.getClass().getMethod(\"get\"+name); Date value = (Date) m.invoke(model); if(value != null){ list.add(value); }else{

list.add(\"\"); }

} }

return list; }}

下⾯将是重点实现导出excel表

package com.tommy.fundation.util;import java.io.OutputStream;import java.util.ArrayList;import java.util.Date;

import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;

import javax.servlet.http.HttpServletResponse;import org.apache.poi.hssf.record.formula.functions.T;import org.apache.poi.hssf.usermodel.HSSFRow;import org.apache.poi.hssf.usermodel.HSSFSheet;import org.apache.poi.hssf.usermodel.HSSFWorkbook;

@SuppressWarnings(\"hiding\")public class ExportExcel { /**

* 导出多张excel表,解决xls格式⾏数65535的限制 * @author OnlyOne * @param response

* @param list 需要处理的list数据集合 * @throws Exception */

@SuppressWarnings(\"deprecation\")

public void doExcel(HttpServletResponse response,List list,String fileName) throws Exception { OutputStream os = response.getOutputStream();//获取输出流 response.reset();

// 设置下载头部信息。Content-disposition为属性名。attachment表⽰以附件⽅式下载,如果要在页⾯中打开,则改为inline。filename为⽂件名 response.setHeader(\"Content-disposition\ response.setContentType(\"application/msexcel\");

Map> sheetMap = daData(list); HSSFWorkbook wb = new HSSFWorkbook(); Set keys = sheetMap.keySet();

for (Iterator iterator = keys.iterator(); iterator.hasNext();) { Integer SheetKey = iterator.next();

HSSFSheet sheet = wb.createSheet((fileName+SheetKey).toString()); List sheetRows = sheetMap.get(SheetKey); for (int i = 0, len = sheetRows.size(); i < len; i++) { T en = (T) sheetRows.get(i);

List dataList = RelectUtil.reflectEntity(en, en.getClass()); HSSFRow row = sheet.createRow(i);

row.createCell(0).setCellValue(String.valueOf(i)); for(int m=0; mrow.createCell(m+1).setCellValue(dataList.get(m).toString()); } } }

wb.write(os); } /**

* 此⽅法将数据集合按65000个进⾏分割成多个⼦集合 * @author OnlyOne

* @param list 需要处理的list数据集合 * @return */

public Map> daData(List list){ int count = list.size()/65000; int yu = list.size() % 65000;

Map> map = new HashMap>(); for (int i = 0; i <= count; i++) {

List subList = new ArrayList(); if (i == count) {

subList = list.subList(i * 65000, 65000 * i + yu); } else {

subList = list.subList(i * 65000, 65000 * (i + 1)-1); }

map.put(i, subList); }

return map; }

}

在Java中调⽤的⽅式

@RequestMapping(value = \"/doExcel\

public void doExcel(HttpServletResponse response,HttpServletRequest request) throws Exception { List list = enrolltgService.findAll();

new ExportExcel().doExcel(response, list, \"⿊⽩淡奶\"); }

⼤功搞成,以后再也不会为了数据量太⼤⽽导不出来烦恼了!!!

需要的包 poi-3.2-FINAL-20081019.jar

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 版权所有