解决JAVA导出大数据的EXCEL文件

 

     在工作中遇到了要导出30多万条数据的excel文件,写了一个工具类,我用的是POI3.13版本的,至少版本也得是3.8,否则不支持导出大数据。如下:

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;

import com.google.common.base.Strings;


public class ExcelUtil {
	
	private  FileOutputStream output;
	private Sheet sheet;
	private SXSSFWorkbook wb;
	private Integer countRow=0;
	private Map<String, PropertyDescriptor>objPropertyMap;
	/**
	 * 初始化
	 * @param xls_write_Address
	 * @param fieldNames
	 * @throws FileNotFoundException
	 */
	public void init_Excel( String path,String fileName,String[] fieldNames) throws FileNotFoundException{
		
		File pathfile=new File(path);
		if(!pathfile.exists()){
			pathfile.mkdirs();
		}
		
		
        output = new FileOutputStream(new File(path+fileName));  //读取的文件路径   
        wb = new SXSSFWorkbook(1000);//内存中保留 10000 条数据,以免内存溢出,其余写入 硬盘      
        sheet = wb.createSheet(String.valueOf("sheet"));  
        wb.setSheetName(0, "sheet");   
        sheet.autoSizeColumn(1);
        Row row = sheet.createRow(countRow++); 
        for(int i=0;i<fieldNames.length;i++){
            Cell cell = row.createCell(i);                     
            cell.setCellType(XSSFCell.CELL_TYPE_STRING);//文本格式                    
            //sheet.setColumnWidth(i, fieldNames[i].length()*384); //设置单元格宽度  
            cell.setCellValue(fieldNames[i]);//写入内容  
        }
        
	}
	
	/**
	 * 
	 * @param datalist
	 * @param dataFields
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 * @throws IOException
	 * @throws IntrospectionException
	 */
	public void write_data_Excel(List<Object> datalist,String[] dataFields) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException, IntrospectionException{
		write_data_Excel(datalist,dataFields,null,null);
	}
	
	public void write_data_Excel(List<Object> datalist,String[] dataFields,Map<String, Map<String, String>> dataDic) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException, IntrospectionException{
		write_data_Excel(datalist,dataFields,dataDic,null);
	}
	
	/**
	 * 写数据
	 * @param datalist
	 * @param dataFields
	 * @throws IOException
	 * @throws IntrospectionException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
    public  void write_data_Excel(List<Object> datalist,String[] dataFields,Map<String, Map<String, String>> dataDic,Map<String,Integer> dataFormat) throws IOException, IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {
    	
		CellStyle cellStyle =  wb.createCellStyle();  
		cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));              		
		ZipSecureFile.setMinInflateRatio(0l);
		
        for(int i=0;i<datalist.size();i++){  
            Row row = sheet.createRow(countRow++);  
            Object obj=datalist.get(i);           
			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			if(objPropertyMap==null){
				objPropertyMap=new HashMap<String, PropertyDescriptor>();
				for(PropertyDescriptor des:propertyDescriptors){
					objPropertyMap.put(des.getName(), des);
				}
			}
            for(int cols=0;cols<dataFields.length;cols++){  
            	String dataField=dataFields[cols];
            	Object value="";
                if (objPropertyMap.get(dataField)!=null) {  
                    // 得到property对应的getter方法  
                    Method gettter = objPropertyMap.get(dataField).getReadMethod();  
                    value=gettter.invoke(obj);
                    if(value instanceof Date){
                    	Date date=(Date)value;
                    	value=DateUtil.dateFormat("yyyy-MM-dd HH:mm:ss", date);
                    	value=value.toString().replaceAll(" 00:00:00", "");
                    	//数据字典的匹配
                    }else {
                    	if(dataDic!=null && dataDic.get(dataField)!=null){
                    		value=dataDic.get(dataField).get(value+"");
                    	}
                    }
                }  
                
                if(value==null){
                	value="";
                }
                Cell cell = row.createCell(cols);     
                
            	if(dataFormat!=null && dataFormat.get(dataField)!=null){
            		int format=dataFormat.get(dataField);

            		switch(format){
	            		case 10:
		            	    cell.setCellStyle(cellStyle);  
		            		cell.setCellType(XSSFCell.CELL_TYPE_NUMERIC);//数字格式
		            		if(!Strings.isNullOrEmpty(value.toString())){
		            			cell.setCellValue(Double.valueOf(value.toString()));//写入内容  
		            		}
		            		break;
	            		case XSSFCell.CELL_TYPE_NUMERIC:
		            		cell.setCellType( XSSFCell.CELL_TYPE_NUMERIC);//数字格式
		            		if(!Strings.isNullOrEmpty(value.toString())){
		            			cell.setCellValue(Double.valueOf(value.toString()));//写入内容  
		            		}
		            		break;
            		}

            	}else{
            		cell.setCellType(XSSFCell.CELL_TYPE_STRING);//文本格式    
            		cell.setCellValue(value.toString());//写入内容  
            	}
            	
               // sheet.setColumnWidth(cols, value.toString().length()*384); //设置单元格宽度  
              
            }   
        }    
          
    }  
    /**
     * 写文件
     * @throws IOException
     */
    public void write_excel_disk() throws IOException{
        wb.write(output);
        output.close(); 
    }
}

测试的调用方法为:

    	
    	ExcelUtil util=new ExcelUtil();
    	Date date=new Date();
    	String strDate=DateUtil.dateFormat("yyyy/MM/dd", date);
    	String path=ParameterConstants.UPLOAD_FILE_PATH+"excel/skcx/"+strDate+"/";
    	String fileName=date.getTime()+".xlsx";
    	
    	util.init_Excel(path,fileName, new String[]{"日期","时间","处理时间","编号","状态","金额"});
    	String[] datefiles=new String[]{"billDueDate","insertedTime","processTime","userNo","results","money"};//对象的属性名字
    	
    	/**
    	 * 定义数据字典
    	 */
    	Map<String, String> resultsMap=new HashMap<String, String>();
    	resultsMap.put("0", "未处理");
    	resultsMap.put("1", "收款成功");
    	resultsMap.put("2", "收款失败");
    	Map<String, Map<String,String>> properyMap=new HashMap<String, Map<String,String>>();
    	properyMap.put("results", resultsMap);//可以多个
    	
    	/**
    	 * 定义数据格式
    	 */
    	Map <String,Integer> dataFormat =new HashMap<String,Integer>();
    	dataFormat.put("money", 10);//带两位小数数字

    	int countPage=1;
    	command.setPageSize(2000);数据量太大,分批读取数据,一次读取2000条
    	command.setCurPageNo(countPage++);
    	BaseEntity entity=viewBillDeductResultsService.getBillDeductResultsByConditionsQuery(command);
    	//从数据库里循环读出所有数据
    	while(entity!=null && entity.getListObject()!=null){
    		util.write_data_Excel(entity.getListObject(), datefiles, properyMap,dataFormat);
    		command.setCurPageNo(countPage++);
    		entity=viewBillDeductResultsService.getBillDeductResultsByConditionsQuery(command);
    	}
    	//将文件写在硬盘上
    	util.write_excel_disk();
        return new ModelAndView("redirect:../../upload/excel/word/"+strDate+"/"+fileName);//防止直接导出造成内存溢出,所以先存放在硬盘上,再去下载


评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值