POI简介:Jakarta POI 是一套用于访问微软格式文档的Java API。Jakarta POI有很多组件组成,其中有用于操作Excel格式文件的HSSF和用于操作Word的HWPF,在各种组件中目前只有用于操作Excel的HSSF相对成熟。

官方主页http://poi.apache.org/index.html

API文档http://poi.apache.org/apidocs/index.html

现在用的比较多的都是用POI技术来导出或者导入Excel,用POI导出Excel我们首先要下载所需的jar包然后导入到我们的项目中,用maven的同学只需找到相关依赖加入到pom.xml里面即可。这里我用maven导包。

<!--POI处理EXCEL-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.6</version>
</dependency>

Jakarta POI HSSF API组件:

HSSF(用于操作Excel的组件)提供给用户使用的对象在rg.apache.poi.hssf.usermodel包中,主要部分包括Excel对象,样式和格式,有以下几种常用的对象:

常用组件:

HSSFWorkbook     excel的文档对象
HSSFSheet            excel的表单
HSSFRow               excel的行
HSSFCell                excel的格子单元
HSSFFont               excel字体
样式:
HSSFCellStyle         cell样式

基本操作步骤:

首先,我们应该要知道的是,一个Excel文件对应一个workbook,一个workbook中有多个sheet组成,一个sheet是由多个行(row)和列(cell)组成。那么我们用poi要导出一个Excel表格

的正确顺序应该是:

1、用HSSFWorkbook打开或者创建“Excel文件对象”

2、用HSSFWorkbook对象返回或者创建Sheet对象

3、用Sheet对象返回行对象,用行对象得到Cell对象

4、对Cell对象读写。

5、将生成的HSSFWorkbook放入HttpServletResponse中响应到前端页面

工具类代码:

package com.self.util;

import org.apache.poi.hssf.usermodel.*;

/**
 * @ClassName ExcelUtil
 * @Description Excel生成工具类
 * @Author zxl
 * @Date 2019/2/1 10:30
 * @Version 1.0
 */
public class ExcelUtil {
    /**
      *@Author S12434
      *@Description 导出Excel
      *@Date 10:36 2019/2/1
      *@Param [sheetName sheet名称, title 标题, values 内容, wb HHSWorkbook对象]
      *@Return org.apache.poi.hssf.usermodel.HSSFWorkbook
      */
    public static HSSFWorkbook getHHSWorkbook(String sheetName,String[] title,String[][] values,HSSFWorkbook wb ){
        //第一步,创建一个HSSFWorkbook,对应一个Excel文件
        if(wb==null){
            wb=new HSSFWorkbook();
        }

        //第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
        HSSFSheet sheet=wb.createSheet(sheetName);

        //第三步,在sheet中添加表头第0行,注意老版本poi对EXCEL的行数列数的限制
        HSSFRow row=sheet.createRow(0);

        //第四步,创建单元格,并设置值表头,设置表头居中
        HSSFCellStyle style=wb.createCellStyle();
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);

        //声明列对象
        HSSFCell cell=null;

        //创建标题
        for(int i=0;i<title.length;i++){
            cell=row.createCell(i);
            cell.setCellValue(title[i]);
            cell.setCellStyle(style);
        }

        //创建内容
        for(int i=0;i<values.length;i++){
            row = sheet.createRow(i + 1);
            for(int j=0;j<values[i].length;j++){
                row.createCell(j).setCellValue(values[i][j]);
            }
        }

        return wb;
    }
}

控制器代码:

package com.self.controller;

import com.self.common.Criteria;
import com.self.entity.OsInput;
import com.self.service.IOsInputService;
import com.self.util.ExcelUtil;
import com.self.util.QueryUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * @ClassName ExcelReportController
 * @Description Excel报表导出类
 * @Author zxl
 * @Date 2019/2/1 11:10
 * @Version 1.0
 */

@Controller
@RequestMapping("/excel")
public class ExcelReportController {

    @Autowired
    IOsInputService iOsInputService;

    @RequestMapping("/inputExport")
    @ResponseBody
    public Map<String,String> inputExport(HttpServletRequest request,HttpServletResponse response,String order,String sort) {
        Map<String,String> map= new HashMap<>();
        map.put("statusCode","200");
        map.put("message","导出成功!");
        Enumeration<?> e = request.getParameterNames();
        TreeMap<String, Object> params = new TreeMap<String, Object>();
        while (e.hasMoreElements()) {
            String name = (String) e.nextElement();
            Object value = request.getParameter(name);
            if (value != null && !"".equals(value)) {
                params.put(name, value);
            }
        }
        String[] sortBy = null;//排序的字段
        Sort s=null;
        if (sort != null) {
            sortBy = sort.split(",");
            Sort.Direction direction = Sort.Direction.ASC;
            if ("desc".equals(order)) {
                direction = Sort.Direction.DESC;
            }
            s = new Sort(direction, sortBy);
        }

        Criteria<OsInput> c = new Criteria<OsInput>();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
//           //Map里面有值表示有查询条件
            switch (entry.getKey().toString()){
                case "conditions":
                    QueryUtils.queryConditions(c, (String)entry.getValue());
                    break;
                default:
                    break;
            }
        }
        List<OsInput> list=iOsInputService.findAll(c,s);
        //excel标题
        String[] title = {"编号","用品名称","供应商","规格型号","类别","计量单位","库位","入库数量","单价","税后单价","税","金额","税后金额","入库时间","操作人工号","操作人姓名","备注"};

        //excel文件名
        String fileName = "办公用品出库记录"+System.currentTimeMillis()+".xls";

        //sheet名
        String sheetName = "办公用品出库记录表";

        String [][] content=new String[list.size()][title.length];
        for(int i=0;i<list.size();i++){
            OsInput osInput=list.get(i);
            content[i][0]=osInput.getOsiIndex().toString();//编号
            content[i][1]=osInput.getOsiName();//用品名称
            content[i][2]=osInput.getOsiSupName();//供应商
            content[i][3]=osInput.getOsiModel();//规格型号
            content[i][4]=osInput.getOsiTypeName();//类别
            content[i][5]=osInput.getOsiUnitName();//计量单位
            content[i][6]=osInput.getOsiStorehouse();//库位
            content[i][7]=osInput.getOsiInputqty().toString();//入库数量
            content[i][8]=osInput.getOsiPrice().toString();//单价
            content[i][9]=osInput.getOsiPricetax().toString();//税后单价
            content[i][10]=osInput.getOsiTaxname();//税
            content[i][11]=osInput.getOsiCost().toString();//金额
            content[i][12]=osInput.getOsiCosttax().toString();//税后金额
            content[i][13]=osInput.getOsiInputdate().toString();//入库时间
            content[i][14]=osInput.getOsiUsercode();//操作人工号
            content[i][15]=osInput.getOsiUsername();//操作人姓名
            content[i][16]=osInput.getOsiDesc();//备注
        }

        //创建HSSFWorkbook
        HSSFWorkbook wb= ExcelUtil.getHHSWorkbook(sheetName,title,content,null);

        try{
            this.setResponseHeader(response,fileName);
            OutputStream os=response.getOutputStream();
            wb.write(os);
            os.flush();
            os.close();
            return map;
        }catch (Exception ec){
            ec.printStackTrace();
            map.put("statusCode","500");
            map.put("message","导出失败:"+ec.getMessage()+"!");
            return map;
        }


    }

    /**
      *@Author zxl
      *@Description 发送响应流方法
      *@Date 13:40 2019/2/11
      *@Param [response, fileName]
      *@Return void
      */
    public void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            try {
                fileName = new String(fileName.getBytes(),"ISO8859-1");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename="+ fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

前端代码:

function excelExport(){
        var osiIndex = $("#osiIndex").combobox("getValue");//办公用品
        var osiSupid = $("#osiSupid").combobox("getValue");//供应商
        var osiModel = $("#osiModel").textbox("getValue");//规格型号
        var osiTypecode = $("#osiTypecode").combobox("getValue");//类别
        var startTime = $("#startTime").datebox("getValue").split("-").join("").split(" ").join("").split(":").join("");//入库日期从
        var endTime = $("#endTime").datebox("getValue").split("-").join("").split(" ").join("").split(":").join("");//至
        var osiUsercode = $("#osiUsercode").combobox("getValue");//操作人
        //结束时间不能比开始时间小
        if ("" != startTime && "" == endTime) {
        } else {
            if (!compareDateTime(endTime, startTime)) {
                $.messager.alert("警告", "结束时间大于开始时间", "warning");
                return;
            }
        }
        var conditions = [];
        conditions.push("osiIndex_equal:" + osiIndex);//办公用品
        conditions.push("osiSupid_equal:" + osiSupid);//供应商
        conditions.push("osiModel_like:" + osiModel);//规格型号
        conditions.push("osiTypecode_equal:" + osiTypecode);//类别
        conditions.push("osiInputdate_startTimeHms:" + startTime);//入库日期从
        conditions.push("osiInputdate_endTimeHms:" + endTime);//至
        conditions.push("osiUsercode_equalTotal:" + osiUsercode);//操作人

        // $.ajax({
        //     url:'../excel/inputExport?sort=osiInputdate&order=asc&conditions=' + conditions,
        //     dataType:'json',
        //     type:'post',
        //     traditional: true,
        //     success:function(data){
        //         alert(data.message);
        //
        //     }
        // });
        window.location.href='../excel/inputExport?sort=osiInputdate&order=asc&conditions=' + conditions;
    }

从前端代码可以看到,ajax访问后台的方式被注释了,那是因为$.ajax,$.post 不支持返回二进制文件流的类型,dataType只支持xml,json,script,html这几种格式,没有blob类型。所以若要采用异步导出EXCEL的方式,只能选择使用原生Ajax XMLReques对象进行处理。

原生ajax异步请求参考文档:

只需要修改前端代码即可。

var xhr ;
        if(window.XMLHttpRequest){//code for IE7+,Firefox,Chrome,Opera,Safari
            xhr = new XMLHttpRequest();
        }else{//code for IE6,IE5
            xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }
        var url = '../excel/inputExport?sort=osiInputdate&order=asc&conditions=' + conditions;
        //设置响应类型为blob类型
        xhr.responseType = "blob";
        xhr.open("post", url, true);
        xhr.onload = function () {
            if (this.status == "200") {
                //获取响应文件流  
                var blob = this.response;
                var reader = new FileReader();
                reader.readAsDataURL(blob);    // 转换为base64,可以直接放入a表情href
                reader.onload = function (e) {
                    // 转换完成,创建一个a标签用于下载
                    var a = document.createElement('a');
                    a.download = '办公用品.xls';
                    a.href = e.target.result;
                    $("body").append(a);    // 修复firefox中无法触发click
                    a.click();
                    $(a).remove();
                }
            }
        }


        xhr.send();

    }

 另:需总结JAVA文件下载的几种方式