poi技术

其实生活中不乏很多需要从数据库向excel导入数据的情况,但是如果数据库的东西很多且字段很长,会造成卡死机的状态。
那么如何解决这个一问题呢,其实网络上有一门技术叫做poi,官方介绍是:
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
其实可以把它理解为Java和Microsoft之间互相沟通的一门技术
Microsoft其实除了excel 还有ppt,word, 相互对应的列举如下:
结构:

HSSF - 提供读写Microsoft Excel格式档案的功能。

XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。

HWPF - 提供读写Microsoft Word格式档案的功能。

HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

HDGF - 提供读写Microsoft Visio格式档案的功能。

那我今天为大家简单的介绍一下如何优化poi导出问题
1.常用类说明

类名 说明
HSSFWorkbook Excel的文档对象
HSSFSheet sheet页
HSSFRow Excel的行
HSSFCell Excel的格子单元
HSSFFont Excel字体

HSSFDataFormat 格子单元的日期格式
HSSFHeader Excel文档Sheet的页眉
HSSFFooter Excel文档Sheet的页脚
HSSFCellStyle 格子单元样式
HSSFDateUtil 日期
HSSFPrintSetup 打印
HSSFErrorConstants 错误信息表

1.2 .1新建一个表格
首先要将下载好的jar包,解压将根目录下的所有包,以及将lib目录下的commons-logging-1.2.jar 和 junit-4.12.jar 以及 log4j1.2.17.jar 这三个通用包导入到项目的lib的目录下,poi-4.0.0.jar包是最重要的。
主要介绍HSSFWorkbook
/**
* 多态实现
* HSSFWorkbook 是对于xls进行操作
/
Workbook wb=new HSSFWorkbook();//新建一个工作簿
/
*
* 导出所以用到输出流
*参数为输出的地址
*/
FileOutputStream fout=new FileOutputStream(“E:\Demo\poi.xls”);
wb.write(fout);//Workbook提供了write的方法
fout.close();//将输出流关闭

1.1.2新建sheet页
在新建工作簿的基础上新建sheet页,wb.createSheet() 返回一个Sheet()如果不进行操作不用接收
/**
* 多态实现
* HSSFWorkbook 是对于xls进行操作
/
Workbook wb=new HSSFWorkbook();//新建一个工作簿
/
*
* 导出所以用到输出流
/
FileOutputStream fout=new FileOutputStream(“E:\Demo\poi.xls”);
/
*
* 有有参和无参数两种
* 参数为sheet页的名字
* 不写参数默认名字为sheet0到n
*/
Sheet sheet1 = wb.createSheet();//创建一个sheet页
Sheet sheet2 = wb.createSheet(“第二个sheet页”);//创建第二个sheet页
wb.write(fout);
fout.close();//将输出流关闭
一些工作表的方法
workbook.setActiveSheet(工作表下标);//设置默认工作表
workbook.setSheetName(2(工作表下标), “1234”(新名字));//重命名工作表
sheet1.setZoom(1,2);//50%显示比例
sheet2.setZoom(2,1);//200%显示比例
sheet3.setZoom(1,10);//10%显示比例

扫描二维码关注公众号,回复: 4252014 查看本文章

优化之后的方法

package com.ywj.excel;

import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class Excel {

	/**
	 * 
	* @Title: export
	* @Description: (通用导出excel)
	* @param excelName  导出文件名
	* @param list   数据集合 
	* @param fieldMap   表头字段   数据库字段为键  表头字段为值
	* @param response   浏览器下载
	* @return void
	 */
	   public static  void export(String excelName,List<Map<String, Object>> list,LinkedHashMap<String, String> fieldMap,HttpServletResponse response){
		   // 设置默认文件名为当前时间:年月日时分秒
	        if (excelName==null || excelName=="") {
	            excelName = new SimpleDateFormat("yyyyMMddhhmmss").format(
	                    new Date()).toString();
	        }
	        int total=list.size();  //总记录数
	        int  excelBig=10000;    //excel划分的大小

	        //判断需要分成多少个excel
	        int excelCount=(total%excelBig==0)?(total/excelBig):(total/excelBig+1);
           
	        //定义一个excel集合
	        List<HSSFWorkbook>  excelList=new ArrayList<HSSFWorkbook>();
	        
	        HSSFWorkbook wb=null;  //excel工作表
	        int begin = 0;   //数据源的开始位置
	        int end = 0;      //数据源的结束位置
		   
		   
	        //循环得到excel集合
	        for(int i=0;i<excelCount;i++){
	            //第一次begin从零开始,否则从结束位置加1开始
	            if(end!=0){
	                begin=end;
	            }
	            end=begin+excelBig;
	            //判断如果最后的位置大于总记录数,则修改为总记录数
	            if(end>list.size()){
	                end=list.size();
	            }
	            //生成excel
	            wb=createExcel(excelName+(i+1), list,begin,end, fieldMap);
	            //将生成的excel添加到集合
	            excelList.add(wb);
	        } 
		   
	        //生成压缩文件,并导出
	        toZipOut(excelName, excelList, response);   
	        
	   }
	   /**
	    * 
	   * @Title: toZipOut
	   * @Description: (压缩文件)
	   * @param excelName  文件命
	   * @param excelList    wb工作簿集合
	   * @param response  将数据发送到页面上
	   * @return void
	    */
	    private static void toZipOut(String excelName, List<HSSFWorkbook> excelList, HttpServletResponse response) {
	
	    	 try {
	             //将压缩包的名字默认为日期时间串
	             String fieldName=new SimpleDateFormat("yyyyMMddhhmmss").format(
	                     new Date()).toString();
	             /**设置response头信息**/
	             response.reset();  
	             //自己写状态码
	             response.setStatus(HttpServletResponse.SC_OK);  
	             //使客户端浏览器,区分不同种类的数据,并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。
	             //ZIP与EXE文件的MIME类型同为application/octet-stream
	             response.setContentType( "application/octet-stream "); 
	             //Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。
	             //Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,文件直接在浏览器上显示或者在访问时弹出文件下载对话框。 
	             //此处设置下载文件的格式为.zip
	             response.setHeader("Content-Disposition","attachment;filename=\""+fieldName+".zip"+"\"");  

	             //生成输出流
	             OutputStream ouputStream = response.getOutputStream();
	             //生成压缩包
	             ZipOutputStream zip = new ZipOutputStream(ouputStream);
//	             zip.setEncoding("GBK");//指定编码为gbk,否则部署到linux下会出现乱码
	             int i = 1;
	             String eName;
	             //循环文件列表,添加到压缩包中
	             for(HSSFWorkbook workbook:excelList){
	                 //给每个文件名加序号
	                 eName=excelName+String.valueOf(i);
	                 //实例化一个压缩实体
	                 ZipEntry entry = new ZipEntry(eName+".xls");
	                 //将压缩实体放入压缩包
	                 zip.putNextEntry(entry);
	                 //将excel内容写进压缩实体
	                 workbook.write(zip);
	                 i++;
	             }
	             //将文件输出
	             zip.flush();
	             zip.close();
	             response.flushBuffer();  
	         } catch (Exception e) {
	        	 e.printStackTrace();
	         }
	    	
	    	
	    	
	    	
		
	}
		/**
	     * 生成Excel
	     * @param excelName   要导出的excel名称
	     * @param list       要导出的数据集合
	     * @param begin   数据集合的开始位置
	     * @param end      数据集合的结束位置
	     * @param fieldMap 中英文字段对应Map,即要导出的excel表头
	  
	     * @return
	     */ 
	    private static  HSSFWorkbook createExcel(String excelName,List<Map<String, Object>> list,Integer begin,Integer end,LinkedHashMap<String, String> fieldMap){

	        int sheetContent=2000;     //每个excel中sheet的容量

	        //计算sheet的数量
	        int sheetCount=0;
	        //如果总记录数  正好整除 以每个sheet的容量
	        if ((end-begin)%sheetContent==0){
	            //sheet的数量=总记录数 除以 每个sheet的容量
	            sheetCount=(end-begin)/sheetContent;
	        }else{
	            //sheet的数量=总记录数 除以 每个sheet的容量 加1
	            sheetCount=(end-begin)/sheetContent+1;
	        }

	        //创建一个WorkBook,对应一个Excel文件
	        HSSFWorkbook wb=new HSSFWorkbook();
	        //创建单元格,并设置值表头 设置表头居中
	        HSSFCellStyle style=wb.createCellStyle();
	        //创建一个居中格式
	        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);

	        //定义sheet
	        HSSFSheet sheet=null;
	        //定义sheet的名称
	        String sheetName=excelName+"-";
	        //sheet中的数据开始位置
	        int beginSheet=0;
	        //sheet中的数据结束位置
	        int endSheet=0;

	        //循环创建sheet
	        for (int i=0;i<sheetCount;i++){
	            //在Workbook中,创建一个sheet,对应Excel中的工作薄(sheet)
	            sheet=wb.createSheet(sheetName+(i+1));

	            //第一次beginSheet从begin开始,否则从结束位置加1开始
	            if(endSheet==0){
	                beginSheet=begin;
	            }else{
	                beginSheet=endSheet;
	            }
	            //sheet结束位置=sheet开始位置+每个sheet的容量
	            endSheet=beginSheet+sheetContent;
	            //判断如果最后的位置大于总记录数,则修改为总记录数
	            if(endSheet>end){
	                endSheet=end;
	            }

	            // 填充工作表
	            try {
	            	  fillSheet(sheet,list,beginSheet,endSheet,fieldMap,style);
	            } catch (Exception e) {
                 e.printStackTrace();
	            }
	        }
	        //返回excel
	        return wb;
	    }
/**
 * 
* @Title: fillSheet
* @Description: (向每一个sheet页中填充row)
* @param sheet 页对象
* @param list  数据集合
* @param beginSheet   这一页开始的数据
* @param endSheet  这一夜结束的数据
* @param fieldMap   表头中文字段和数据库字段  键为数据库字段 值为中文字段
* @param style   表头样式
* @return void
 */
	    private static void fillSheet(HSSFSheet sheet, List<Map<String, Object>> list, int beginSheet, int endSheet,
				LinkedHashMap<String, String> fieldMap, HSSFCellStyle style) {
	    	   // 定义存放英文字段名和中文字段名的数组
	    	    //英文为键中文为值
	        String[] enFields = new String[fieldMap.size()];
	        String[] cnFields = new String[fieldMap.size()];

	        // 将值分别填入两个数组
	        int count = 0;
	        for (Entry<String, String> entry : fieldMap.entrySet()) {
	            enFields[count] = entry.getKey();
	            cnFields[count] = entry.getValue();
	            count++;
	        }
	        int   rowIndex=0;//行的数量
	        //在sheet中添加表头第0行
	        HSSFRow row=sheet.createRow(rowIndex++);

	        // 填充表头
	        for (int i = 0; i < cnFields.length; i++) {
	            HSSFCell cell=row.createCell(i);
	            cell.setCellValue(cnFields[i]);
	            cell.setCellStyle(style);
	            sheet.autoSizeColumn(20);
	        }

	        Map<String, Object> map=null;
      for(int i=beginSheet;i<endSheet;i++) {
	  row=sheet.createRow(rowIndex++);
		 map= list.get(i);//map集合可以理解为对象
	  for (int j = 0; j < enFields.length; j++) {
           String fieldValue=map.get(enFields[j]).toString();//用键取值
           row.createCell(j).setCellValue(fieldValue);//将值赋给单元格
      }
       }	    		
		}    
	   
}

猜你喜欢

转载自blog.csdn.net/qq_43238210/article/details/83244762
poi