实际项目中使用poi导出excel(spring+springMVC+Mybatis环境下)

准备poi所依赖的jar包.

       放到工程的lib文件夹下.本文中项目所使用的jar包为:

  1. poi-3.15.jar,
  2. poi-ooxml-3.15.jar,
  3. poi-ooxml-schemas-3.15.jar
jar包下载地址:http://mvnrepository.com/search?q=comment

场景描述:

前台用easyui框架(这里博主用的是easyui框架,其他框架道理一样),选中一条数据,进行方案导出.效果截图如下:

实际项目中使用poi导出excel(spring+springMVC+Mybatis环境下)_第1张图片
首先是先获取选中方案的id(数据库中的),根据此id去数据库中查询方案下包含的具体的自定义媒体类型信息列表.用于封装成excel的基础数据,也就是要导出的内容.

利用poi导出excel大体思路:

1,需要导出的原始数据.即根据实际需求查询得到的结果集作为原始数据.可能是一个list,map...看你封装成什么样了(这里是封装成list了)

2,将原始的数据转换到excel中,具体根据数据形式不同,写法也会不同.不过这些都是大同小异的.

3,将生产好的excel文件写到一个路径下(这里都是放到tomcat服务器目录下的download下).

4,根据上一步的路径找到excel文件进行下载操作(就是文件下载...网上一大片)

下面看各个层的代码,以及excel工具类.具体步骤,代码中注释已经写到很明白了.

Controller层代码:

/**
     * 导出新闻方案
     * @param Integer[] newsScheme方案id数组
     * @throws Exception
     */
    @RequestMapping(value = "newsSchemes/export/{newsSchemesId}",method = RequestMethod.POST)
    public void exportNewsScheme(@PathVariable("newsSchemesId") Integer newsSchemesId) throws Exception{
        System.err.println("导出的方案的id:"+newsSchemesId);
        //切换到rsdb数据库
        DataSourceContextHolder.setDbType(DataSourceType.SOURCE_RSDB);
        //查询的结果集,list为需要在表格中展示的数据
        List list = this.newsMediaCategoryService.listNewsMediaCateBySid(new NewsMediaCategory(newsSchemesId));
        //循环将自定义媒体对应的新闻源集合存入到list中.
        if(list != null && list.size()>0){
            for(int i=0;i siteList = this.siteService.listBySids(new Site(sIds));
                //List site = this.siteMapper.listBySids(null)
                list.get(i).setSiteList(siteList);
                list.get(i).setSids(sIds);
            }
        }
        for(NewsMediaCategory nmc : list){
            System.err.println(nmc.getName()+"--------"+nmc.getSiteList().size());
        }
        //切换到rsdb数据库
        DataSourceContextHolder.setDbType(DataSourceType.SOURCE_RSDB);
        //根据方案id查询方案基本信息,主要是为了获取导出时候的默认名为(当前方案名+时间戳)
        NewsSchemes newsScheme = this.newsSchemesService.selNewsSchemesBySchemesId(newsSchemesId);
        //获取欲下载的文件路径
        String filePath =this.newsSchemesService.createNewSchemesExcel(newsScheme,list,this.request);
        //执行下载操作
        ExcelUtils.download(filePath , this.request , this.response);
    }
service层代码:

这里需要说明下:步骤大体是这么搞,但是样式需要根据不同需求来设定,其中的逻辑也会不一样的.此处导出的样式如下图:

代码如下:

/**
     * 方法描述:生产方案excel文件,并写到指定位置.将该文件的绝对路径返回
* 返回类型:String
* 作者:GQ
* 创建时间:2016年12月30日14:41:52
* @param request request请求
* @param newsSchemeId 新闻方案id
* @param list NewsMediaCategory集合
*/ @Override public String createNewSchemesExcel(NewsSchemes newsScheme,List list,HttpServletRequest request) { // 第一步,创建一个workbook,对应一个Excel文件 HSSFWorkbook wb = new HSSFWorkbook(); // 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet HSSFSheet sheet = wb.createSheet("新闻方案表"); //获取单元格格式的样式,一些基本属性 HSSFCellStyle cellStyle = ExcelUtils.getCellStyle(wb); //获取标题格式 HSSFCellStyle titleStyle = ExcelUtils.getTitleStyle(wb); //创建表头.第一行.第一列的数据 ExcelUtils.createCell(sheet, 0, 0, titleStyle, "方案具体信息表"); //合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列 ExcelUtils.mergedRegion(sheet , 0 , 0 , 0 , 2); //第二行,弟1,2,3列对应的数值,创建行"自定义媒体名称,备注信息,包含站点源个数". ExcelUtils.createMultiCell(sheet , 1 , new Integer[]{0,1,2} , cellStyle , new String[]{"自定义媒体名称","备注信息","包含站点源个数"}); //记录第一个总信息表真实数据行数,真实数据添加的起始行应该是(rCounts-1)为真是数据起始行. int rCounts=3; //将真实数据插入到excel表中去. for (int r = 0; r < list.size(); r++) { //获取真实数据 NewsMediaCategory nmc = list.get(r); //每次填充同一行的,前三个单元格.调用同时填充(同一行的多个单元格的方法). ExcelUtils.createMultiCell(sheet , r+2 , new Integer[]{0,1,2} , cellStyle , new String[]{nmc.getName(),nmc.getRemark(),String.valueOf(nmc.getSiteList().size())}); //每次加1,为了得到下一个表的表头位置. rCounts++; } //设置分割那一行,将他创建出来,但是不赋值任何数据,用于导入时候的区分点. ExcelUtils.createRow(sheet , rCounts-1); //System.err.println("rowNullde的单元格个数:"+rowNull.getPhysicalNumberOfCells()); //设置'自定义媒体类型具体信息表',表头 ExcelUtils.createCell(sheet, rCounts, 0, titleStyle, "自定义媒体类型具体信息表"); //累计,判断合并时候用.确定每一个单元格 int m=0; for (int r = 0; r < list.size(); r++) { //循环控制有几个媒体类型 NewsMediaCategory nmc = list.get(r); //合并自定义媒体名称那一行,m控制合并的起止位置. ExcelUtils.mergedRegion(sheet , rCounts+1 , rCounts+1 , m , m+2); //设置自定义媒体名称那一行,每一个单元格名称. ExcelUtils.createMultiCell(sheet , rCounts+1 , new Integer[]{m,m+1,m+2} , cellStyle , new String[]{nmc.getName(),"",""}); //循环出媒体名称下面的哪一行,"新闻源id,新闻源站点名称,url" ExcelUtils.createMultiCell(sheet , rCounts+2 , new Integer[]{m,m+1,m+2} , cellStyle , new String[]{"新闻源id","新闻源站点名称","url"}); //填充,每一个自定义媒体类型下,所拥有的新闻源具体信息.. for(int i=0;i
excel的工具类:(等读者熟悉了,自己写自己合适的工具类这里多有东西只是起到指引作用).

package com.rs.sys.utils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
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.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.web.multipart.MultipartFile;

/**
 * 处理excel文件的工具类
 * @author GQ
 * @date 2016年12月27日 上午10:39:56
 * @status
 */
public class ExcelUtils {
    /**
     * 方法描述:用于下载文件,根据存在的文件绝对路径下载.
* 返回类型:void
* 作者:GQ
* 创建时间:2016年12月27日上午10:51:17 * @param filePath 欲下载的文件绝对路径.
如:"F:\apache-tomcat-7.0.70\webapps\Rs_sys\WEB-INF\download\xxx.xls" * @param request request请求 * @param response response请求
*/ public static void download(String filePath,HttpServletRequest request,HttpServletResponse response){ HSSFWorkbook workbook=null; ServletOutputStream sos=null; try { File file = new File(filePath); if (!file.exists()) { response.sendError(404, "File not found!"); return; } BufferedInputStream br = new BufferedInputStream(new FileInputStream( filePath)); String downLoadName = null; String agent = request.getHeader("USER-AGENT"); if (null != agent && -1 != agent.indexOf("MSIE")) // IE { downLoadName = java.net.URLEncoder.encode(file.getName(), "UTF-8"); } else if (null != agent && -1 != agent.indexOf("Mozilla")) // Firefox { downLoadName = new String(file.getName().getBytes("UTF-8"), "iso-8859-1"); } else { downLoadName = java.net.URLEncoder.encode(file.getName(), "UTF-8"); } byte[] buf = new byte[1024]; int len = 0; response.reset(); response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment; filename=" + downLoadName); OutputStream out = response.getOutputStream(); while ((len = br.read(buf)) > 0) { out.write(buf, 0, len); } br.close(); out.close(); }catch (Exception e) { e.printStackTrace(); }finally{ try { if (null != workbook) { workbook.close(); } if(null!=sos){ sos.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 方法描述:获取单元格中的数据,根据存储的值的类型不同,调用相应的方法获取数据,最后返回一个字符串类型的数据
* 返回类型:String
* 作者:GQ
* 创建时间:2016年12月28日下午6:24:00 * @param cell 单元格 * @return
*/ public static String getCellValue(Cell cell) { String cellValue = ""; //DecimalFormat df = new DecimalFormat("#"); switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_STRING: cellValue = cell.getRichStringCellValue().getString().trim(); break; case HSSFCell.CELL_TYPE_NUMERIC: cellValue = String.valueOf(new Integer((int)cell.getNumericCellValue())); break; case HSSFCell.CELL_TYPE_BOOLEAN: cellValue = String.valueOf(cell.getBooleanCellValue()).trim(); break; case HSSFCell.CELL_TYPE_FORMULA: cellValue = cell.getCellFormula(); break; default: cellValue = ""; } return cellValue; } /** * 方法描述:文件写入
* 返回类型:void
* 作者:GQ
* 创建时间:2016年12月30日下午1:41:24 * @param file 为获得到的文件(也就是要讲这个文件写到哪里) * @param filePath 文件写入的位置 * @param fileName
文件的名 */ public static void write(MultipartFile file,String filePath,String fileName){ //在指定目录下建立一个空的文件,作用:别的file文件往里写入 File targetFile = new File(filePath, fileName); if(!targetFile.exists()){ targetFile.mkdirs(); } //保存 try { //将前台传过来的file文件写到targetFile中. file.transferTo(targetFile); } catch (Exception e) { e.printStackTrace(); } } /** * 方法描述:创建行,rowNum控制创建第几行.sheet控制在哪个工作簿上创建
* 返回类型:HSSFRow
* 作者:GQ
* 创建时间:2017年1月3日下午4:58:09 * @param sheet 工作簿 * @param rowNum 行数(下标从0开始) * @return
*/ public static HSSFRow createRow(HSSFSheet sheet,int rowNum) { return sheet.getRow(rowNum)!=null?sheet.getRow(rowNum):sheet.createRow(rowNum); } /** * 方法描述:创建一个cell,样式,值.
* 返回类型:void
* 作者:GQ
* 创建时间:2017年1月3日下午4:02:32
* @param cellnum 第几个cell,下标从0开始,即0代表第一个
* @param value 该cell的值
* @param row 行
* @param style 样式(采用哪个样式)
*/ public static HSSFCell createCell(HSSFSheet sheet, int rowNumm, int cellNum, HSSFCellStyle style, String value) { HSSFRow row = createRow(sheet,rowNumm); HSSFCell cell = row.createCell((short) cellNum); cell.setCellValue(new HSSFRichTextString(value)); cell.setCellStyle(style); return cell; } /** * 方法描述:创建多个单元格.必须是同一行的.并赋值上相应数据
* 返回类型:HSSFCell
* 作者:GQ
* 创建时间:2017年1月3日下午5:21:52 * @param sheet 工作簿 * @param rowNumm 行数 * @param cellNums 要创建的单元格下标数组 * @param style 样式 * @param values 单元格下标对应的值,一个对应一个,顺序不能乱 */ public static List createMultiCell(HSSFSheet sheet, int rowNumm, Integer[] cellNums, HSSFCellStyle style, String[] values) { List cellList = new ArrayList(); for(int i=0;i * 返回类型:HSSFCellStyle
* 作者:GQ
* 创建时间:2017年1月3日下午4:04:02 * @param workbook */ public static HSSFCellStyle getCellStyle(HSSFWorkbook workbook) { /*//设置字体; HSSFFont font = workbook.createFont(); //设置字体大小; font.setFontHeightInPoints((short) 5); //设置字体名字; font.setFontName("Courier New");*/ //font.setItalic(true); //font.setStrikeout(true); //设置样式; HSSFCellStyle style = workbook.createCellStyle(); //设置底边框; style.setBorderBottom(HSSFCellStyle.BORDER_THIN); //设置底边框颜色; style.setBottomBorderColor(HSSFColor.BLACK.index); //设置左边框; style.setBorderLeft(HSSFCellStyle.BORDER_THIN); //设置左边框颜色; style.setLeftBorderColor(HSSFColor.BLACK.index); //设置右边框; style.setBorderRight(HSSFCellStyle.BORDER_THIN); //设置右边框颜色; style.setRightBorderColor(HSSFColor.BLACK.index); //设置顶边框; style.setBorderTop(HSSFCellStyle.BORDER_THIN); //设置顶边框颜色; style.setTopBorderColor(HSSFColor.BLACK.index); //在样式用应用设置的字体; //style.setFont(font); //设置自动换行; style.setWrapText(true); //设置水平对齐的样式为居中对齐; style.setAlignment(HSSFCellStyle.ALIGN_CENTER); //设置垂直对齐的样式为居中对齐; style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); return style; } /** * 方法描述:自定义设置标题样式,只有下边框
* 返回类型:HSSFCellStyle
* 作者:GQ
* 创建时间:2017年1月3日下午4:20:42
* @param workbook
*/ public static HSSFCellStyle getTitleStyle(HSSFWorkbook workbook){ HSSFCellStyle style = workbook.createCellStyle(); style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式 // 设置标题只有下边框 style.setBorderBottom(HSSFCellStyle.BORDER_THIN); return style; } /** * 方法描述:合并单元格
* 返回类型:int
* 作者:GQ
* 创建时间:2017年1月4日上午10:45:20
* @param sheet 工作簿
* @param firstRow 合并起止行(下标从0开始)
* @param lastRow 合并截止行(下标从0开始)
* @param firstCol 合并起止列(下标从0开始)
* @param lastCol 合并截止列(下标从0开始)
*/ public static int mergedRegion(HSSFSheet sheet,int firstRow, int lastRow, int firstCol, int lastCol){ return sheet.addMergedRegion(new CellRangeAddress(firstRow,lastRow,firstCol,lastCol)); } /** * 方法描述:将生成好的excel文件,写入到指定路径下的文件中.
* 返回类型:void
* 作者:GQ
* 创建时间:2017年1月4日上午10:57:04
* @param wb 一个workbook,对应一个Excel文件
* @param absolutePath excel文件的绝对路径
*/ public static void writeExcelToLocation(HSSFWorkbook wb,String absolutePath){ try { FileOutputStream fout = new FileOutputStream(absolutePath); wb.write(fout); fout.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 方法描述:获取workbook,将文件转换为workbook对象
* 返回类型:Workbook
* 作者:GQ
* 创建时间:2017年1月4日下午5:12:20
* @param absolutePath 文件的绝对路径(excel文件)
* @return
*/ public static Workbook getWorkBook(String absolutePath){ FileInputStream fis =null; Workbook wb = null; try{ // 获取一个绝对地址的流 fis = new FileInputStream(absolutePath); wb = new HSSFWorkbook(fis); }catch(IOException e){ // TODO Auto-generated catch block e.printStackTrace(); } return wb; } }
前台需要注意:

用的是表单提交.代码如下:

js代码:

//返回被选中的行数据,没有则返回空
var rows = $('#news_scheme_manage').datagrid('getSelections'); 
if(rows!=null && rows.length==1){
	var row = $('#news_scheme_manage').datagrid('getSelected');
        //id用于查询方案对应的类型
       var id=row.id;
       console.log("id:"+id);
       //到弹出框中进行编辑
       //类选择器获取表单. 
       var form = $( "#news_scheme_manage_excel_export" );
       //设置表单中的相应属性
       //设置提交方式为post.
       form.attr( "method", "post" );
       //设置提交按钮跳转地址 
       form.attr( "action", "newsSchemes/export/"+id );
       //若以上判断返回非false则表单提交. 
       form.submit();                 
     }else{       //选中多条或者没有选则弹出提示信息       $.messager.alert("提示信息","有且只能选择一条数据!","info"); }
 
   
 
   
 
   

 
   
 
   
 
   特殊声明:博主第一次写,格式什么的不要介意,只是自己的一个笔记,有些地方可能说的不是很明白,可能存在很多漏洞或者bug,还望多多包涵.希望会给刚入门的同学一点点启示作用.谢谢 
   











你可能感兴趣的:(java,poi,excel)