使用Apache POI 進行Excel報表的匯出下載(GET 請求 && POST請求)
阿新 • • 發佈:2018-12-29
簡介:之前專案有這樣的需求:按各種條件進行篩選資料,然後匯出Excel到本地
針對條件條件很少的情況下,使用的是GET請求的方式,直接在URL上拼接請求引數,這種形式很簡單就能匯出Excel。但是當條件很多很複雜時,就不適合使用GET請求的方式了,所以我使用了POST請求的方式,在這其中遇到了各種問題,估計大家也可能遇見到了。
遇到問題:
- 請求資料傳遞正確,資料獲取正確,Excel構建也沒報錯,但是就是不提示Excel下載,一切顯得詭異得安靜。
請求資料傳遞正確,資料獲取正確,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}}
</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}}
</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}}
</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}}
</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>
頁面效果
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);
}
}
}
}