1. 程式人生 > >使用Apache POI 進行Excel報表的匯出下載(GET 請求 && POST請求)

使用Apache POI 進行Excel報表的匯出下載(GET 請求 && POST請求)

簡介:之前專案有這樣的需求:按各種條件進行篩選資料,然後匯出Excel到本地

針對條件條件很少的情況下,使用的是GET請求的方式,直接在URL上拼接請求引數,這種形式很簡單就能匯出Excel。但是當條件很多很複雜時,就不適合使用GET請求的方式了,所以我使用了POST請求的方式,在這其中遇到了各種問題,估計大家也可能遇見到了。

遇到問題

  1. 請求資料傳遞正確,資料獲取正確,Excel構建也沒報錯,但是就是不提示Excel下載,一切顯得詭異得安靜。
    這裡寫圖片描述
  2. 請求資料傳遞正確,資料獲取正確,Excel構建也沒報錯,提示下載了,但是下載的是一個莫名的空Excel,並且檔名稱是一串數字。
    這裡寫圖片描述這裡寫圖片描述
    3.請求資料傳遞正確,資料獲取正確,Excel構建也沒報錯,提示下載了,但是出現的結果時未找到對應的檔案。
    這裡寫圖片描述

    這裡寫圖片描述

    大概的問題就這樣,具體的程式碼我就不貼了,我們來看看能實現效果的程式碼。

我這邊使用的相關技術是: freemarker+Html+AngularJS+Hibernate+POI+AbstractXlsView

先來前端頁面HTML

<style>
.div_parent{
    width:100%;
    height:700px;
    vertical-align: middle;
    position:relative;
}
.div_child {
    width:600px;
    height:400px;
    margin
: auto
; position: absolute; top: 0; left: 0; bottom: 0; right: 0; border: 1px solid #b59898; }
.div_child_custom{ width:700px; height:580px; margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; border: 1px solid #b59898; } .div_tiaojian{ display
: inline
; border: 1px dashed; margin-bottom: 10px; }
.lable_tiaojian{ padding-left: 0; margin-left: 20px; }
</style> <div class="well well-sm" style="background:white;"> <ol class="breadcrumb"> <li style="color:#0b8d39;padding-left:15px;"> 當前位置:</li> <li><a href="#/">首頁</a></li> <li>決策輔助系統</li> <li><a href="javascript::" ui-sref="statisticalAnalysis">統計分析主頁</a></li> <li class="active">
{{vm.title}}</li> </ol> <div class="div_parent"> <!-- 專案總庫固定類 --> <div class="div_child" ng-if="vm.isProjectFixed"> <form class="form-horizontal" role="form" style="margin-top: 100px;"> <div class="form-group"> <label class="col-md-3 control-label">篩選條件:</label> <div class="col-md-5"> <select class="form-control" ng-model="vm.isIncludLibrary"> <option value="true" ng-selected="vm.isIncludLibrary == true">已納入專案庫</option> <option value="false" ng-selected="vm.isIncludLibrary == false">未納入專案庫</option> </select> </div> </div> <div class="form-group"> <label class="col-md-3 control-label">匯出項:</label> <div class="col-md-9"> <div style="margin-bottom: 10px;"> <!--**get請求匯出Excel,請求引數拼接在url上面**--> <a class="btn btn-success btn-sm" href="/management/auxDeci/statisticalAnalysis/exportExcelForProject?classDesc=unit&isIncludLibrary={{vm.isIncludLibrary}}">按專案單位分類</a> <a class="btn btn-success btn-sm" href="/management/auxDeci/statisticalAnalysis/exportExcelForProject?classDesc=category&isIncludLibrary={{vm.isIncludLibrary}}">按專案類別分類</a> </div> <div> <a class="btn btn-success btn-sm" href="/management/auxDeci/statisticalAnalysis/exportExcelForProject?classDesc=industry&isIncludLibrary={{vm.isIncludLibrary}}">按專案行業分類</a> <a class="btn btn-success btn-sm" href="/management/auxDeci/statisticalAnalysis/exportExcelForProject?classDesc=stage&isIncludLibrary={{vm.isIncludLibrary}}">按專案階段分類</a> </div> </div> </div> </form> </div> <!-- 專案總庫自定義類 --> <div class="div_child_custom" ng-if="vm.isProjectCustom"> <!--**post請求匯出Excel,請求引數的繫結以及方法在js程式碼中,這裡是觸發**--> <form class="form-horizontal" role="form" style="margin-top: 10px;" ng-submit="vm.exportExcelForProjectByCustom()"> <div class="form-group"> <label class="col-md-2 control-label lable_tiaojian">行業分類:</label> <div class="col-md-9 div_tiaojian"> <label class="control-label" ng-repeat="x in vm.basicData.projectIndustry_ZF | orderBy:'itemOrder'"> <input type="checkbox" value="{{x.id}}" ng-click="vm.selectProjectIdustry(x.id)"/>{{x.description}}&nbsp;&nbsp; </label> </div> <label class="col-md-2 control-label lable_tiaojian">專案階段:</label> <div class="col-md-9 div_tiaojian"> <label class="control-label" ng-repeat="x in vm.basicData.projectStage"> <input type="checkbox" value="{{x.id}}" ng-click="vm.selectProjectStage(x.id)"/>{{x.description}}&nbsp;&nbsp; </label> </div> <label class="col-md-2 control-label lable_tiaojian">專案類別:</label> <div class="col-md-9 div_tiaojian"> <label class="control-label" ng-repeat="x in vm.basicData.projectCategory"> <input type="checkbox" value="{{x.id}}" ng-click="vm.selectProjectCategory(x.id)"/>{{x.description}}&nbsp;&nbsp; </label> </div> <label class="col-md-2 control-label lable_tiaojian">申報單位:</label> <div class="col-md-9 div_tiaojian"> <label class="control-label" ng-repeat="x in vm.basicData.userUnit"> <input type="checkbox" value="{{x.id}}" ng-click="vm.selectProjectUnit(x.id)"/>{{x.unitName}}&nbsp;&nbsp; </label> </div> <label class="col-md-2 control-label lable_tiaojian">總投資範圍:</label> <div class="col-md-9" style="margin-bottom: 10px;"> <input type="number" step="any" class="form-control" style="width:200px;" ng-model="vm.projectInvestSumBegin"/> <span>~</span> <input type="number" step="any" class="form-control" style="width:200px;" min="{{vm.projectInvestSumBegin}}" ng-model="vm.projectInvestSumEnd"/> <span>(萬元)</span> </div> </div> <div class="form-group text-center"> <button type="submit" class="btn btn-success btn-sm">匯出</button> </div> </form> </div> </div> </div>

頁面效果
這裡寫圖片描述這裡寫圖片描述
get請求觸發頁面
post請求觸發頁面
js程式碼

原理是利用form表單提交完後之後跳轉下載頁面進行Excel的下載
//post請求下載檔案
/**
 * options:{
 *  url:請求地址
 *  method:請求方法
 *  data:請求資料
 * }
 */
vm.postDownLoadFile = function (options) {
    var config = $.extend(true, { method: 'post' }, options);
    var $iframe = $('<iframe id="down-file-iframe" />');
    var $form = $('<form target="down-file-iframe" method="' + config.method + '" />');
    $form.attr('action', config.url);
    for (var key in config.data) {
        $form.append('<input type="hidden" name="' + key + '" value="' + config.data[key] + '" />');
    }
   $iframe.append($form);
    $(document.body).append($iframe);
    $form[0].submit();
    $iframe.remove();
}

vm.exportExcelForProjectByCustom=function(){
    vm.postDownLoadFile({
        url:url+"/exportExcelForProjectByCustom",//請求地址,替換就好了
        data:vm.model,//請求引數,使用物件封裝或者json格式的鍵值對均可
        method:'post'
     });
}

後臺java 控制類 :GET請求的響應

/**get請求直接返回ModelAndView即可**/
@RequestMapping(name="專案總庫-專案分類統計",path="exportExcelForProject",method=RequestMethod.GET)
public ModelAndView exportExcelForProject(HttpServletRequest request,@RequestParam String classDesc,@RequestParam String isIncludLibrary) throws ParseException{
    List<ProjectStatisticsBean> data = ProjectService.getProjectStatistics(classDesc,isIncludLibrary);
    return new ModelAndView(new ProjectStatisticsView(classDesc,isIncludLibrary), "data", data);
}
//get 請求很簡單的,直接查詢資料,構建Excel即可,例子中ProjectStatisticsView物件就是Excel頁面的設計物件,物件的構造方法可有可無。

GET請求的Excel設定

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.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.web.servlet.view.document.AbstractXlsView;

import cs.model.Statistics.ProjectStatisticsBean;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 
 * @ClassName: ProjectStatisticsView 
 * @Description: 專案總庫專案匯出Excel頁面設計類
 * @author cx
 * @date 2018年1月24日 下午4:17:34 
 *
 */
public class ProjectStatisticsView extends AbstractXlsView {
    private String type;
    private String isIncludLibrary;
    public ProjectStatisticsView(String type,String isIncludLibrary){
        this.type=type;
        this.isIncludLibrary=isIncludLibrary; 
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String typeDesc=type.equals("unit")?"專案單位":type.equals("category")?"專案類別":type.equals("industry")?"專案行業":type.equals("stage")?"專案階段":"";
        isIncludLibrary=isIncludLibrary.equals("true")?"已納入專案庫專案":isIncludLibrary.equals("false")?"未納入專案庫專案":isIncludLibrary.equals("all")?"專案總庫":"";

        String fileName = "光明新區政府投資專案庫"+isIncludLibrary+typeDesc+"分類彙總表.xls";
        response.setHeader("Content-Disposition", "attachment;filename=" +new String(fileName.getBytes("gb2312"), "iso8859-1"));
        Sheet sheet = workbook.createSheet("表1");

        CellStyle cellStyleTitle = workbook.createCellStyle();
        CellStyle cellStyleSubTitleLeft = workbook.createCellStyle();
        CellStyle cellStyleO = workbook.createCellStyle();

        //設定字型
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 14); // 字型高度
        font.setFontName(" 黑體 "); // 字型
        cellStyleTitle.setFont(font);
        //設定表格邊框
        cellStyleTitle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyleTitle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyleTitle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyleTitle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        cellStyleSubTitleLeft.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyleSubTitleLeft.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyleSubTitleLeft.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyleSubTitleLeft.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        cellStyleO.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyleO.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyleO.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyleO.setBorderLeft(HSSFCellStyle.BORDER_THIN);

        //建立行
        Row title=sheet.createRow(0);
        Row subTitle=sheet.createRow(1);
        Row row_head = sheet.createRow(2);

        //設定行高
        title.setHeight((short)800);
        subTitle.setHeight((short)500);
        row_head.setHeight((short)360);

        //begin#標題
        //建立列
        createCellAlignCenter(workbook,title,0,"光明新區政府投資專案庫"+isIncludLibrary+typeDesc+"分類彙總表",cellStyleTitle);
        //合併標題
        //引數1:開始行、結束行、開始列、結束列
        CellRangeAddress cellRangeTitle = null;
        cellRangeTitle = type.equals("unit")?new CellRangeAddress(0,0,0,8):new CellRangeAddress(0,0,0,3);
        setRegionStyle(sheet,cellRangeTitle,cellStyleTitle);
        sheet.addMergedRegion(cellRangeTitle);
        //end#標題

        //begin#子標題
        createCellAlignLeft(workbook,subTitle,0,"列印日期:"+new SimpleDateFormat("yyyy年MM月dd日").format(new Date()),cellStyleSubTitleLeft);
        CellRangeAddress cellRangeSubTitleLeft = null;
        if(type.equals("unit")){
             //設定子標題列寬
            sheet.setColumnWidth(1, 256*30+184);
            sheet.setColumnWidth(2, 256*13+184);
            sheet.setColumnWidth(7, 256*16+184);
            sheet.setColumnWidth(8, 256*15+184);

            createCellAlignRight(workbook,subTitle,8,"資金:萬   元\n面積:平方米",workbook.createCellStyle());
            cellRangeSubTitleLeft = new CellRangeAddress(1,1,0,7);
        }else{
             //設定子標題列寬
            sheet.setColumnWidth(1, 256*26+184);
            sheet.setColumnWidth(2, 256*25+184);
            sheet.setColumnWidth(3, 256*27+184);

            createCellAlignRight(workbook,subTitle,3,"資金:萬   元\n面積:平方米",workbook.createCellStyle());
            cellRangeSubTitleLeft = new CellRangeAddress(1,1,0,2);
        }
        setRegionStyle(sheet,cellRangeSubTitleLeft,cellStyleSubTitleLeft);
        sheet.addMergedRegion(cellRangeSubTitleLeft);
        //end#子標題

        //begin表格頭
        createCellAlignCenter(workbook,row_head,0,"序號",cellStyleO);
        if(type.equals("unit")){
            Row row_subHead = sheet.createRow(3);
            row_subHead.setHeight((short)400);
            createCellAlignCenter(workbook,row_head,1,"專案單位",cellStyleO);
            createCellAlignCenter(workbook,row_head,2,"專案數量",cellStyleO);
            createCellAlignCenter(workbook,row_subHead,2,"前期儲備階段",cellStyleO);
            createCellAlignCenter(workbook,row_subHead,3,"前期階段",cellStyleO);
            createCellAlignCenter(workbook,row_subHead,4,"施工階段",cellStyleO);
            createCellAlignCenter(workbook,row_subHead,5,"停工階段",cellStyleO);
            createCellAlignCenter(workbook,row_subHead,6,"竣工階段",cellStyleO);
            createCellAlignCenter(workbook,row_subHead,7,"固定資產登記階段",cellStyleO);
            createCellAlignCenter(workbook,row_head,8,"專案總投資",cellStyleO);

            CellRangeAddress cellRange0 = new CellRangeAddress(2,3,0,0);
            CellRangeAddress cellRange1 = new CellRangeAddress(2,3,1,1);
            CellRangeAddress cellRange2 = new CellRangeAddress(2,2,2,7);
            CellRangeAddress cellRange3 = new CellRangeAddress(2,3,8,8);

            setRegionStyle(sheet,cellRange0,cellStyleO);
            setRegionStyle(sheet,cellRange1,cellStyleO);
            setRegionStyle(sheet,cellRange2,cellStyleO);
            setRegionStyle(sheet,cellRange3,cellStyleO);

            sheet.addMergedRegion(cellRange0);
            sheet.addMergedRegion(cellRange1);
            sheet.addMergedRegion(cellRange2);
            sheet.addMergedRegion(cellRange3);
        }
        else{
            createCellAlignCenter(workbook,row_head,1,typeDesc,cellStyleO);
            createCellAlignCenter(workbook,row_head,2,"專案數量",cellStyleO);
            createCellAlignCenter(workbook,row_head,3,"專案總投資",cellStyleO);
        }
        //end#表格頭

        //begin#資料列
        int rowNum=type.equals("unit")?4:3;//資料載入開始行
        int index=1;


        @SuppressWarnings("unchecked")
        List<ProjectStatisticsBean> data = (List<ProjectStatisticsBean>) model.get("data");
        for (ProjectStatisticsBean obj:data) {
            Row row = sheet.createRow(rowNum);
            //建立資料
            createCellAlignCenter(workbook,row,0, index,cellStyleO);//序號
            createCellAlignCenter(workbook,row,1, obj.getClassDesc(),cellStyleO);//專案統計分類
            if(type.equals("unit")){
                createCellAlignCenter(workbook,row,2, obj.getPrereserveNumbers(),cellStyleO);//前期儲備階段專案數
                createCellAlignCenter(workbook,row,3, obj.getPreNumbers(),cellStyleO);//前期階段專案數
                createCellAlignCenter(workbook,row,4, obj.getConstructionNumbers(),cellStyleO);//施工階段專案數
                createCellAlignCenter(workbook,row,5, obj.getShutdownNumbers(),cellStyleO);//停工階段專案數
                createCellAlignCenter(workbook,row,6, obj.getCompletedNumbers(),cellStyleO);//竣工階段專案數
                createCellAlignCenter(workbook,row,7, obj.getFixedAssetsNumbers(),cellStyleO);//固定資產登記階段專案數
                createCellAlignCenter(workbook,row,8, obj.getProjectInvestSum(),cellStyleO);//專案總投資
            }else{
                createCellAlignCenter(workbook,row,2, obj.getProjectNumbers(),cellStyleO);//專案總數
                createCellAlignCenter(workbook,row,3, obj.getProjectInvestSum(),cellStyleO);//專案總投資
            }
            rowNum++;index++;
        }
        //end#資料列
    }
//建立值為string字型居中的單元格    
    @SuppressWarnings("deprecation")
    private void createCellAlignCenter(Workbook workbook,Row row, int cellNumber,String value,CellStyle cellStyle){
        //設定邊框
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        createCell(workbook,row,cellNumber,value,CellStyle.ALIGN_CENTER,CellStyle.VERTICAL_CENTER,cellStyle);
    }
    @SuppressWarnings("deprecation")
//建立值為double字型居中的單元格    
    private void createCellAlignCenter(Workbook workbook,Row row, int cellNumber,double value,CellStyle cellStyle){
        //設定邊框
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        createCell(workbook,row,cellNumber,value,CellStyle.ALIGN_CENTER,CellStyle.VERTICAL_CENTER,cellStyle);
    }
    @SuppressWarnings("deprecation")
//建立值為string字型居左的單元格
    private void createCellAlignLeft(Workbook workbook,Row row, int cellNumber,String value,CellStyle cellStyle){
        //設定邊框
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        createCell(workbook,row,cellNumber,value,CellStyle.ALIGN_LEFT,CellStyle.VERTICAL_CENTER,cellStyle);
    }
    @SuppressWarnings("deprecation")
//建立值為string字型居右的單元格    
    private void createCellAlignRight(Workbook workbook,Row row, int cellNumber,String value,CellStyle cellStyle){
        //設定邊框
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        createCell(workbook,row,cellNumber,value,CellStyle.ALIGN_RIGHT,CellStyle.VERTICAL_CENTER,cellStyle);
    }
    @SuppressWarnings("deprecation")
//重寫建立列
    private void createCell(Workbook workbook,Row row, int cellNumber,String value, short halign, short valign,CellStyle cellStyle){
        Cell cell=row.createCell(cellNumber);
        cell.setCellValue(value);

        cellStyle.setAlignment(halign);
        cellStyle.setVerticalAlignment(valign);
        cellStyle.setWrapText(true);
      //設定邊框
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        cell.setCellStyle(cellStyle);
    }
    @SuppressWarnings("deprecation")
  //重寫建立列
    private void createCell(Workbook workbook,Row row, int cellNumber,double value, short halign, short valign,CellStyle cellStyle){
        Cell cell=row.createCell(cellNumber);// 建立單元格
        cell.setCellValue(value);// 設定值

        cellStyle.setAlignment(halign);// 設定單元格水平方向對齊方式
        cellStyle.setVerticalAlignment(valign);// 設定單元格垂直方向對齊方式
        cellStyle.setWrapText(true);
        //設定邊框
        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        cell.setCellStyle(cellStyle);
    }


    /**
     * 
     * @Title: setRegionStyle 
     * @Description: 設定單元格樣式
     * @param sheet 當前表
     * @param region 合併列
     * @param cs  樣式
     */
    public static void setRegionStyle(Sheet sheet, CellRangeAddress region, CellStyle cs) {
        for (int i = region.getFirstRow(); i <= region.getLastRow(); i++) {
            HSSFRow row = (HSSFRow) sheet.getRow(i);
            if (row == null)
                row = (HSSFRow) sheet.createRow(i);
            for (int j = region.getFirstColumn(); j <= region.getLastColumn(); j++) {
                HSSFCell cell = row.getCell(j);
                if (cell == null) {
                    cell = row.createCell(j);
                    cell.setCellValue("");
                }
                cell.setCellStyle(cs);
            }
        }
    }
}