jxls(poi) 工具 定制模板生产Excel报表

 
 
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pingan.qhcs.map.loan.pg.util.adapter.IQuery;
import net.sf.jxls.transformer.XLSTransformer;


/***
 * 
 * @author 
 * @desc 通过jxls 工具 定制模板生产Excel报表
 * @date 2017-09-12 13:53
 */
public class JxlsExcelUtils {

private static final Logger logger = LoggerFactory.getLogger(JxlsExcelUtils.class);


public static void loadFileToHttpServletResponse(String saveFile,HttpServletResponse response) {
File file = new File(saveFile);
ServletOutputStream ops = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
response.setContentLength((int) file.length());
byte[] buffer = new byte[64 * 1024];
int count;
ops = response.getOutputStream();
while ((count = fis.read(buffer)) > 0)
ops.write(buffer, 0, count);
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
fis.close();
ops.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 将文件名中的汉字转为UTF8编码的串,以便下载时能正确显示另存的文件名

* @param s
*            原文件名
* @return 重新编码后的文件名
*/
public static String toUtf8String(String s) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 0 && c <= 255) {
sb.append(c);
} else {
byte[] b;
try {
b = Character.toString(c).getBytes("utf-8");
} catch (Exception ex) {
ex.printStackTrace();
b = new byte[0];
}
for (int j = 0; j < b.length; j++) {
int k = b[j];
if (k < 0)
k += 256;
sb.append("%" + Integer.toHexString(k).toUpperCase());
}
}
}
return sb.toString();
}




/**
* @Description: 下载excel
* @author: 
* @date: 2017/09/12 15:31:08
* @param path
*            模板路径
* @param destFileName
*            保存文件名称
* @param map
*            数据
* @param response
* @throws UnsupportedEncodingException 
*/
public static void doDownload(String path, String destFileName,Map<String, Object> map, HttpServletResponse response) {
XLSTransformer transformer = new XLSTransformer();
InputStream in = null;
OutputStream out = null;
try {
//String fileName = URLEncoder.encode(destFileName, "utf-8");  
//String fileName = new String((destFileName).getBytes("UTF-8"), "ISO-8859-1");


String fileName = destFileName ;
logger.info("destFileName:" + fileName);
response.reset();
response.setCharacterEncoding("UTF-8");
//这里对文件名进行编码,保证下载时汉字显示正常
//response.setContentType("application/vnd.ms-excel;charset=utf-8"); 
//Content-disposition属性设置成以附件方式进行下载  
//response.setHeader("Content-Disposition", "attachment;filename="+ fileName);

response.setContentType("application/vnd.ms-excel");
   response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));


in = new BufferedInputStream(new FileInputStream(path));
Workbook workbook = transformer.transformXLS(in, map);
out = response.getOutputStream();
workbook.write(out);
out.flush();
} catch (InvalidFormatException e) {
logger.error("doDownload-->InvalidFormatException:" + e);

} catch (IOException e) {
//e.printStackTrace();
logger.error("doDownload-->IOException:" + e);
}catch (Exception e) {
logger.error("doDownload-->Exception:" + e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
logger.error("doDownload-->in.close:" + e);
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
logger.error("doDownload-->out.close:" + e);
}
}
}
}



/**
* @Description: 下载excel
* @author: 
* @date: 2017/09/12 15:31:08
* @param path
*            模板路径
* @param destFileName
*            保存文件名称
* @param map
*            数据
* @param response
* @throws UnsupportedEncodingException 
*/
public static void doDownload(InputStream in, String destFileName,Map<String, Object> map, HttpServletResponse response) {
XLSTransformer transformer = new XLSTransformer();
//InputStream in = null;
OutputStream out = null;
try {
//String fileName = URLEncoder.encode(destFileName, "utf-8");  
//String fileName = new String((destFileName).getBytes("UTF-8"), "ISO-8859-1");


String fileName = destFileName ;
logger.info("destFileName:" + fileName);
response.reset();
response.setCharacterEncoding("UTF-8");
//这里对文件名进行编码,保证下载时汉字显示正常
//response.setContentType("application/vnd.ms-excel;charset=utf-8"); 
//Content-disposition属性设置成以附件方式进行下载  
//response.setHeader("Content-Disposition", "attachment;filename="+ fileName);

response.setContentType("application/vnd.ms-excel");
   response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));


in = new BufferedInputStream(in);
Workbook workbook = transformer.transformXLS(in, map);
out = response.getOutputStream();
workbook.write(out);
out.flush();
} catch (InvalidFormatException e) {
logger.error("doDownload-->InvalidFormatException:" + e);
} catch (IOException e) {
logger.error("doDownload-->IOException:" + e);
}catch (Exception e) {
logger.error("doDownload-->Exception:" + e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
logger.error("doDownload-->in.close:" + e);
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
logger.error("doDownload-->out.close:" + e);
}
}
}
}

//-----------------------------------------------------------------------------------------
/****

数据库中存在大量的数据,我们要查询,怎么办?我们在没有经过设计的时候是这样来处理的,先写一个集合,然后执行jdbc,将返回的结果赋值给list,然后再返回到页面上,但是当数据量大的时候,就会出现数据无法返回,内存溢出的情况,于是我们在有限的时间和空间下,通过分页将数据一页一页的显示出来,这样可以避免了[大数据
量数据对内存的占用,也提高了用户的体验,在我们要导出的百万数据也是一个道理,内存突发性占用,我们可以限制导出数据所占用的内存,
这里我先建立一个list容器,list中开辟10000行的存储空间,每次存储10000行,用完了将内容清空,然后重复利用
,这样就可以有效控制内存,所以我们的设计思路就基本形成了,所以分页数据导出共有以下3个步骤:

1、求数据库中待导出数据的行数
2、根据行数求数据提取次数
3、按次数将数据写入文件
*/
/**
* @author LIUZILIANG856
* @desc 添加 2017-11-15 15:05
* @param response
* @param fileName
* @param sheetName
* @param listData
* @param columns
* @throws Exception
*/
public static void exportBigDataExcelByPageSize(HttpServletResponse response, String fileName, String sheetName,List<Map<String, Object>> listData, List<String> columns,IQuery<?,?> query) throws Exception {
        exportBigDataExcelByPageSize(response, fileName, listData, sheetName, columns,query);
    }

/**
     * 下载excel
     * @desc 添加 2017-11-15 15:05
     * @param response
     * @param filename 文件名 ,如:20150808.xls
     * @param listData 数据源
     * @param sheetName 表头名称
     * @param columns 列名称集合,如:{姓名,性别,地址}
     * @throws Exception 
     */
    private static void exportBigDataExcelByPageSize(HttpServletResponse response, String filename, List<Map<String, Object>> listData,
            String sheetName, List<String> columns,IQuery<?,?> query) throws Exception {
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        exportBigDataExcelByPageSiz(response, listData, sheetName, columns,query);
    }
    
    /**
     * @author 
     * @date 2017-11-09 20:49
     * @desc 采用poi导出百万级别大数据
     * @param objData 导出内容数组
     * @param sheetName 导出工作表的名称
     * @param columns 导出Excel的表头数组
     * @return
     */
    private static final int page_size = 100 ;// 数据库中存储的数据行数
    @SuppressWarnings({ "rawtypes", "static-access" })
private static void exportBigDataExcelByPageSiz(HttpServletResponse response, List<Map<String, Object>> objData, String sheetName,
            List<String> columns,IQuery<?,?> query) {
    OutputStream os = null ;
    SXSSFWorkbook wb = new SXSSFWorkbook(100); //最重要的就是使用SXSSFWorkbook,表示流的方式进行操作 
    wb.setCompressTempFiles(false);//临时文件进行压缩,建议不要true,否则会影响导出时间
    Sheet sheet = wb.createSheet(sheetName);     //工作表对象 
    Row nRow = sheet.createRow(0);   // 创建第一行对象
    Cell nCell = null ;
    CellStyle cellStyle=wb.createCellStyle(); // 创建单元格样式
         Font font = wb.createFont();
         font.setFontHeightInPoints((short) 10);
         font.setFontName("微软雅黑");
         font.setItalic(true);
         cellStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
         cellStyle.setFillForegroundColor((short)43);
         cellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); 
         cellStyle.setFont(font);
         if (columns != null && columns.size() > 0) {
      for (int j = 0; j < columns.size(); j++) {
      nCell = nRow.createCell(j);
      nCell.setCellStyle(cellStyle);
      nCell.setCellValue(columns.get(j).split("_")[1]);//创建表头
             }
      }
    long  startTime = System.currentTimeMillis();   //开始时间              
    logger.info("strat execute time: " + startTime);  
        try {
        os = response.getOutputStream();    
        //int page_size = 10000;// 数据库中存储的数据行数
        PageHelper.startPage(1, 1);
        List<Map> resultList = query.queryForList();
        Page<Map> page =  new Page<Map>() ;
        int list_count = 0 ;
        if (resultList != null) {
        if(!resultList.isEmpty()) {
      page = (Page<Map>) resultList ;
      list_count = (int) page.getTotal();
      }
        }
        int export_times = list_count % page_size > 0 ? list_count / page_size  + 1 : list_count / page_size;
        for (int j = 0; j < export_times; j++) {
        PageHelper.startPage(j + 1,page_size);
        resultList = query.queryForList();
        if (resultList != null) {
            if(!resultList.isEmpty()) {
          page = (Page<Map>) resultList ;
          }
            }
        int len = page.getResult().size() < page_size ? page.getResult().size() : page_size;
        for (int i = 0; i < len; i++) {
        nRow = sheet.createRow(j * page_size + i + 1);//新建行对象   
        Map map = page.getResult().get(i);
                    for (int k = 0; k < columns.size(); k++) {
                    nRow.createCell(k).setCellValue("null".equals(String.valueOf(map.get(columns.get(k).split("_")[0]))) ? null 
                        :String.valueOf(map.get(columns.get(k).split("_")[0])));
                    } 
        }
        resultList.clear();
        }


        wb.write(os);
os.close();
os.flush();//刷新缓冲区  
       wb.dispose();
       
            long stopTime = System.currentTimeMillis();     //写文件时间  
            logger.info("write xlsx file time: " + (stopTime - startTime)/1000 + "m");  
            
            logger.info("exportToExcel successful!");
        } catch (Exception e) {
            logger.error("exportToExcel error: " + e.getMessage());
        }
    }
//-----------------------------------------------------------------------------------------


    //-----------------------------------------------------------------------------------------
/**
* @author
* @desc 修改
* @param response
* @param fileName
* @param sheetName
* @param listData
* @param columns
* @throws Exception
*/
public static void exportBigDataExcel(HttpServletResponse response, String fileName, String sheetName,List<Map<String, Object>> listData, List<String> columns) throws Exception {
        exportBigDataExcel(response, fileName, listData, sheetName, columns);
    }

/**
     * 下载excel
     * @param response
     * @param filename 文件名 ,如:20150808.xls
     * @param listData 数据源
     * @param sheetName 表头名称
     * @param columns 列名称集合,如:{姓名,性别,地址}
     * @throws Exception 
     */
    private static void exportBigDataExcel(HttpServletResponse response, String filename, List<Map<String, Object>> listData,
            String sheetName, List<String> columns) throws Exception {
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        exportBigDataExcel(response, listData, sheetName, columns);
    }
    
    
    
    /**
     * @author
     * @date 2017-11-09 20:49
     * @desc 采用poi导出百万级别大数据
     * @param objData 导出内容数组
     * @param sheetName 导出工作表的名称
     * @param columns 导出Excel的表头数组
     * @return
     */
    private static final int sheetCount = 50000 ;
    private static void exportBigDataExcel(HttpServletResponse response, List<Map<String, Object>> objData, String sheetName,
            List<String> columns) {
    OutputStream os = null ;
    SXSSFWorkbook wb = null ;      
        try {
        os = response.getOutputStream();
        //在内存中保持100行,超过100行将被刷新到磁盘   
        wb = new SXSSFWorkbook(100); //最重要的就是使用SXSSFWorkbook,表示流的方式进行操作          
            wb.setCompressTempFiles(false);//临时文件进行压缩,建议不要true,否则会影响导出时间   
            Sheet sheet = null;     //工作表对象 
            Row nRow = null;        //行对象  
            Cell nCell = null ;
            CellStyle cellStyle=wb.createCellStyle(); // 创建单元格样式
            Font font = wb.createFont();
            font.setFontHeightInPoints((short) 10);
            font.setFontName("微软雅黑");
            font.setItalic(true);
            long  startTime = System.currentTimeMillis();   //开始时间  
            
            logger.info("strat execute time: " + startTime);  
            
            int rowNo = 0;      //总行号  
            int pageRowNo = 0;  //页行号  
            if (CollectionUtils.isNotEmpty(objData)) {
            for ( int i = 0 ;i < objData.size() ; i++ ) {
            //打印300000条后切换到下个工作表,可根据需要自行拓展,2百万,3百万...数据一样操作,只要不超过1048576就可以  
                    if( rowNo % sheetCount == 0 ){  
                    logger.info("Current Sheet:" + rowNo / sheetCount);  
                        sheet = wb.createSheet(sheetName + (rowNo / sheetCount));//建立新的sheet对象  
                        sheet = wb.getSheetAt(rowNo / sheetCount);        //动态指定当前的工作表  
                        sheet.autoSizeColumn(1, true);//自适应列宽度
                        pageRowNo = 0;      //每当新建了工作表就将当前工作表的行号重置为0  
                        
                        nRow = sheet.createRow(pageRowNo);   // 创建第一行对象


                        cellStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
                        cellStyle.setFillForegroundColor((short)43);
                        cellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); 
                        cellStyle.setFont(font);
                        if (columns != null && columns.size() > 0) {
                    for (int j = 0; j < columns.size(); j++) {
                    nCell = nRow.createCell(j);
                    nCell.setCellStyle(cellStyle);
                    nCell.setCellValue(columns.get(j));//创建表头
                            }
                    }
                    }     


                    rowNo++;  
                    nRow = sheet.createRow(++pageRowNo);//新建行对象  
                
                    Map<String, Object> map = objData.get(i);
                    for (int j = 0; j < columns.size(); j++) {
                    nRow.createCell(j).setCellValue("null".equals(String.valueOf(map.get(columns.get(j)))) ? null 
                        :String.valueOf(map.get(columns.get(j))));
                    }  
                    
                    if (rowNo % 10000 == 0) {  
                    logger.info("row no: " + rowNo);  
                    }  
                    Thread.sleep(1);//休息一下,防止对CPU占用,其实影响不大 
                 }              
            }
            
            long finishedTime = System.currentTimeMillis(); //处理完成时间  
            logger.info("finished execute  time: " + (finishedTime - startTime)/1000 + "m");  
            
            
            wb.write(os);
os.close();
os.flush();//刷新缓冲区  
       wb.dispose();
            


            long stopTime = System.currentTimeMillis();     //写文件时间  
            logger.info("write xlsx file time: " + (stopTime - startTime)/1000 + "m");  
            
            logger.info("exportToExcel successful!");
        } catch (Exception e) {
            logger.error("exportToExcel error: " + e.getMessage());
        }
    }
    
  //-----------------------------------------------------------------------------------------
    
    
  //-----------------------------------------------------------------------------------------
    /**
* @author
* @desc 添加
* 多sheet、按pageSize进行分页 多sheet写入
* @date 2017-11-17 13:37
* @param response
* @param fileName
* @param sheetName
* @param listData
* @param columns
* @throws Exception
*/
public static void exportBgDataExcelForSheetByPageSize(HttpServletResponse response, String fileName, String sheetName,
Map<String, Object> paramMaps, List<String> columns,IQuery<?,?> query) throws Exception {
exportBgDataExcelForSheetByPageSize(response, fileName, paramMaps, sheetName, columns,query);
    }

/**
     * 下载excel
     * @param response
     * @param filename 文件名 ,如:20150808.xls
     * @param listData 数据源
     * @param sheetName 表头名称
     * @param columns 列名称集合,如:{姓名,性别,地址}
     * @throws Exception 
     */
    private static void exportBgDataExcelForSheetByPageSize(HttpServletResponse response, String filename, Map<String, Object> paramMaps,
            String sheetName, List<String> columns,IQuery<?,?> query) throws Exception {
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        exportBgDataExcelForSheetByPageSize(response, paramMaps, sheetName, columns,query);
    }
    
    
    /**
     * @author 
     * @date 2017-11-17 14:41
     * @desc 采用poi导出百万级别大数据(大数据量按pageSize分页查询然后在多sheet写入【因为单个sheet只能承受100万级别的数据量】)
     * @param objData 导出内容数组
     * @param sheetName 导出工作表的名称
     * @param columns 导出Excel的表头数组
     * @return
     */
    private static final int sheetTotalCount = 500000;//单个sheet的数量
    private static final int pageSize = 50000 ;// 数据库中存储的数据行数
    @SuppressWarnings("unchecked")
    private static void exportBgDataExcelForSheetByPageSize(HttpServletResponse response, Map<String, Object> paramMaps, String sheetName,
            List<String> columns,IQuery<?,?> query) {
    OutputStream os = null ;
    SXSSFWorkbook wb = null ;
        try {
        os = response.getOutputStream();
        wb = new SXSSFWorkbook(5000); //最重要的就是使用SXSSFWorkbook,表示流的方式进行操作 
        wb.setCompressTempFiles(false);//临时文件进行压缩,建议不要true,否则会影响导出时间
        Sheet sheet = null;     //工作表对象 
        Row nRow = null;   // 创建第一行对象
            Cell nCell = null ;
      CellStyle cellStyle=wb.createCellStyle(); // 创建单元格样式
        Font font = wb.createFont();
        font.setFontHeightInPoints((short) 10);
        font.setFontName("微软雅黑");
        font.setItalic(true);
        cellStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
        cellStyle.setFillForegroundColor((short)43);
        cellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); 
        cellStyle.setFont(font);
        long  startTime = System.currentTimeMillis();   //开始时间              
    logger.info("strat execute time: " + startTime);
     
    PageHelper.startPage(1, 1);
List<Map> resultList = (List<Map>) query.queryForList();
        Page<Map> page =  new Page<Map>() ;
        int list_count = 0 ;
        if (resultList != null) {
        if(!resultList.isEmpty()) {
      page = (Page<Map>) resultList ;
      list_count = (int) page.getTotal();//获取总记录数
      }
        }
        int export_times = list_count % pageSize > 0 ? list_count / pageSize  + 1 : list_count / pageSize;
        int rowNo = 0;      //总行号  
            int pageRowNo = 0;  //页行号  
        for (int j = 0; j < export_times; j++) {
        PageHelper.startPage( j + 1 , pageSize);
        resultList = (List<Map>) query.queryForList();
        if (resultList != null) {
            if(!resultList.isEmpty()) {
          page = (Page<Map>) resultList ;
          }
            }
        List<Map> objData = page.getResult();
        if (CollectionUtils.isNotEmpty(objData) && list_count > 0) {
        for ( int i = 0 ;i < objData.size() ; i++ ) {
        //打印100000条后切换到下个工作表,可根据需要自行拓展,2百万,3百万...数据一样操作,只要不超过1048576就可以  
                        if( rowNo % sheetTotalCount == 0 ){  
                        logger.info("Current Sheet:" + rowNo / sheetTotalCount);  
                            sheet = wb.createSheet(sheetName + (rowNo / sheetTotalCount));//建立新的sheet对象  
                            sheet = wb.getSheetAt(rowNo / sheetTotalCount);        //动态指定当前的工作表  
                            sheet.autoSizeColumn(1, true);//自适应列宽度
                            pageRowNo = 0;      //每当新建了工作表就将当前工作表的行号重置为0                             
                            nRow = sheet.createRow(pageRowNo);   // 创建第一行对象
                            cellStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
                            cellStyle.setFillForegroundColor((short)43);
                            cellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); 
                            cellStyle.setFont(font);
                            if (columns != null && columns.size() > 0) {
                        for (int k = 0; k < columns.size(); k++) {
                        nCell = nRow.createCell(k);
                        nCell.setCellStyle(cellStyle);
                        nCell.setCellValue(columns.get(k).split("_")[1]);//创建表头
                                }
                        }               
                        }
                        
                        rowNo++;  
                        nRow = sheet.createRow(++pageRowNo);//新建行对象
                        
                        Map<String, Object> map = objData.get(i);
                        for (int e = 0; e < columns.size(); e++) {
                        nRow.createCell(e).setCellValue("null".equals(String.valueOf(map.get(columns.get(e).split("_")[0]))) ? null 
                            :String.valueOf(map.get(columns.get(e).split("_")[0])));
                        }  
                        
                        if (rowNo % 10000 == 0) {  
                        logger.info("row no: " + rowNo);  
                        }  
                        Thread.sleep(1);//休息一下,防止对CPU占用,其实影响不大 
        }//rowNo end
       
        }
        resultList.clear();
        }
       
        wb.write(os);
os.close();
os.flush();//刷新缓冲区  
       wb.dispose();
       
            long stopTime = System.currentTimeMillis();     //写文件时间  
            logger.info("write xlsx file time: " + (stopTime - startTime)/1000 + "m");  
            
            logger.info("exportToExcel successful!");        
        } catch (Exception e) {
logger.error("exportBgDataExcelForSheetByPageSize error: " + e);
}
    }
  //-----------------------------------------------------------------------------------------  
}

猜你喜欢

转载自blog.csdn.net/lzljava/article/details/78579455