您的位置:首页 > 其它

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

2017-11-20 09:57 260 查看


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) {
<
4000
/span>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);
}

    }

  //-----------------------------------------------------------------------------------------  

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: