Java 使用Apache POI生成并導出excel

項目中使用POI生成excle報表

maven:

<groupId>org.apache.poi ? <artifactId>poi? <version>4.0.1</dependency>?

POI中概念:

HSSFWorkbook : 相當于一個excel文件

HSSFSheet:一張excel表,excel左下角的sheet0,sheet1..

HSSFRow:一張表格中的某一行

HSSFCell:一張表格中的一個單元格

1.創建一個workBook.

HSSFWorkbook wb = new HSSFWorkbook();

2.創建一張sheet

HSSFSheet sheet = wb.createSheet("sheet0");

3.創建第一行

HSSFRow row = sheet.createRow(0);

構造方法中的數值表示創建第幾行,索引從0開始

4.創建一個單元格

HSSFCell cell = row.createCell(0);

構造方法中的數值表示創建第幾列,索引從0開始

5.向表格中添加數據

cell.setCellValue().

此時,一個excel的雛形已經創建好了,但是,怎么導出并下載呢?

需要用到HttpServletResponse。

1.設置響應類型,告知類型為excel文件

response.setContentType("application/vnd.ms-excel");

2.設置字符編碼

response.setCharacterEncoding("utf-8");

3.根據瀏覽器進行轉碼,使其支持中文文件名

String browse = Excelutil.checkBrowse(request);String fileName ="新建表格";try {if ("MSIE".equalsIgnoreCase(browse.substring(0, 4))) {response.setHeader("content-disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8") +".xls");? ? }else {String newtitle =new String(fileName.getBytes("UTF-8"), "ISO8859-1");? ? ? ? response.setHeader("content-disposition", "attachment;filename=" + newtitle +".xls");? ? }}catch (Exception e) {e.printStackTrace();}?

4.導出

OutputStream out =null;try {out = response.getOutputStream();? ? wb.write(out);}catch (Exception e) {e.printStackTrace();}finally {if (null != out) {try {out.close();? ? ? ? }catch (IOException e) {e.printStackTrace();? ? ? ? }}}


到此為止可以導出一個excel表格了。

還沒完,實際生產過程中需要用到的報表格式要復雜得多

1.首先,設置各個單元格的格式,比如大小,居中什么的(新版本的API可能不一樣,具體可以看看官方API)

設置格式需要用到HSSFCellStyle。由HSSFWorkbook 生成,在方法定義中明確表示一個workbook

最多只能有4000個HSSFCellStyle

HSSFCellStyle cs = wb.createCellStyle();cs.setAlignment(HSSFCellStyle.ALIGN_CENTER);水平居中cs.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);垂直居中cs.setWrapText(true);字體是否加粗,默認為falsecs.setBorderBottom(BorderStyle.DOTTED);設置下邊框樣式,BorderStyle是一個枚舉,有很多類型,具體可以看官方文檔。cs.setBorderTop(BorderStyle.DOTTED)cs.setBorderLeft(BorderStyle.DOTTED)cs.setBorderRight(BorderStyle.DOTTED)cs.setBottomBorderColor(short color)設置邊框顏色,有對應的上下左右方法cs.setFillBackgroundColor(short color)設置背景顏色cs.setFilllBackgroundColor(short color)設置前景顏色cs.setFont(HSSFFont font)設置字體HSSFFont font = wb.createFont();font.setFontName("黑體“)font.setFontHeightInPoints((short)12)設置字體


讓格式生效

cell.setCellStyle(cs)

也可以使用

sheet.setColumnWidth(int columnIndex,int width);

設置某一列的寬度

2.合并單元格

sheet.addMergedRegion(new CellRangeAddress(int firstRow,int lastRow,int firstCol, int lastCol));

將多個單元格合成一個單元格,參數依次為起始行,結束行,起始列,結束列。

使用時先生成一個單元格,比如我要合并第一行的第一個和第二個單元格

1.先生成第一個單元格

HSSFCell cell = row.createCell(0);

2.合并

sheet.addMergedRegion(new CellRangeAddress(0,0,0, 1));

3.如果要生成下一個單元格,記得單元格的下標應該為2而不是1,因為你已經合并了一個單元

格,原則:生成新的單元格的時候要判斷前面是否有合并的單元格,如果有,需要將合并的單元格也算進去。

4.poi也可以通過讀取excel模板來生成新的excel報表

首先,需要將excel模板文件放入項目資源文件夾中,然后獲取該模板文件的路徑

String path = AbroadCountUtils.class.getClassLoader().getResource("abroad.xls").getPath();

File file =newFile(path);

生成HSSFWorkbook

HSSFWorkbook wb =newHSSFWorkbook();

生成HSSFSheet

HSSFSheet sheet = wb.createSheet("sheet0");

后面的步驟就是一樣的了,通過導入模板可以簡化生成復雜表頭的步驟,避免出錯。

5.checkbrowser方法

private final staticStringIE11="rv:11.0";

private final staticStringIE10="MSIE 10.0";

private final staticStringIE9="MSIE 9.0";

private final staticStringIE8="MSIE 8.0";

private final staticStringIE7="MSIE 7.0";

private final staticStringIE6="MSIE 6.0";

private final staticStringMAXTHON="Maxthon";

private final staticStringQQ="QQBrowser";

private final staticStringGREEN="GreenBrowser";

private final staticStringSE360="360SE";

private final staticStringFIREFOX="Firefox";

private final staticStringOPERA="Opera";

private final staticStringCHROME="Chrome";

private final staticStringSAFARI="Safari";

private final staticStringOTHER="其它";

public staticStringcheckBrowse(HttpServletRequest request) {

String userAgent = request.getHeader("USER-AGENT");

if(regex(OPERA,userAgent))

returnOPERA;

if(regex(CHROME,userAgent))

returnCHROME;

if(regex(FIREFOX,userAgent))

returnFIREFOX;

if(regex(SAFARI,userAgent))

returnSAFARI;

if(regex(SE360,userAgent))

returnSE360;

if(regex(GREEN,userAgent))

returnGREEN;

if(regex(QQ,userAgent))

returnQQ;

if(regex(MAXTHON,userAgent))

returnMAXTHON;

if(regex(IE11,userAgent))

returnIE11;

if(regex(IE10,userAgent))

returnIE10;

if(regex(IE9,userAgent))

returnIE9;

if(regex(IE8,userAgent))

returnIE8;

if(regex(IE7,userAgent))

returnIE7;

if(regex(IE6,userAgent))

returnIE6;

returnOTHER;

}

public static booleanregex(String regex,String str) {

Pattern p = Pattern.compile(regex,Pattern.MULTILINE);

Matcher m = p.matcher(str);

returnm.find();}



貼上從前端請求到后端處理的整個代碼。

1.前端js方法,該方法為按鈕的點擊事件綁定的方法,點擊后通過將參數拼接到url的方式進行傳參。(有點丑,有更好的可以推薦!)

?function exportExcel() { var startDate = $('#startTime').val(); var endDate = $('#endTime').val(); var condition = $('#condition').val(); var url = 'exportExcel.do'; url = url + '?start=' + startDate + '&end=' + endDate + '&condition=' + condition; location.href = url;}

2.controller中的方法

?@RequestMapping("exportExcel.do")

public void exportExcel(HttpServletRequest request, HttpServletResponse response) {

String start = request.getParameter("start");

String end = request.getParameter("end");

String condition = request.getParameter("condition");

List titleList = new ArrayList<>();

titleList.add("ID");

titleList.add("name");

titleList.add("age");

List<List<String>> content = new ArrayList();

HSSFWorkbook wb = GenerateExcelUtil.generateExcel(titleList, content);

response.setContentType("application/vnd.ms-excel");

response.setCharacterEncoding("utf-8");

String browse = GenerateExcelUtil.checkBrowse(request);

String fileName = "newExcel";

try { if ("MSIE".equalsIgnoreCase(browse.substring(0, 4))) {

response.setHeader("content-disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8") + ".xls"); }

else { String newtitle = new String(fileName.getBytes("UTF-8"), "ISO8859-1"); response.setHeader("content-disposition", "attachment;filename=" + newtitle + ".xls"); }

} catch (Exception e) { e.printStackTrace(); } OutputStream out = null; try { out = response.getOutputStream(); wb.write(out); } catch (Exception e) { e.printStackTrace(); }finally { if (null != out) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } }}

3.生成excel工具類

public class GenerateExcelUtil {

private final static String IE11="rv:11.0";

private final static String IE10="MSIE 10.0";

private final static String IE9="MSIE 9.0";

private final static String IE8="MSIE 8.0";

private final static String IE7="MSIE 7.0";

private final static String IE6="MSIE 6.0";

private final static String MAXTHON="Maxthon";

private final static String QQ="QQBrowser";

private final static String GREEN="GreenBrowser";

private final static String SE360="360SE";

private final static String FIREFOX="Firefox";

private final static String OPERA="Opera";

private final static String CHROME="Chrome";

private final static String SAFARI="Safari";

private final static String OTHER="其它";

public static HSSFWorkbook generateExcel(List<String> titles, List<List<String>> contents){

HSSFWorkbook wb = new HSSFWorkbook();

HSSFSheet sheet = wb.createSheet();

sheet.setColumnWidth(1,256*32); sheet.setColumnWidth(4,256*20);

sheet.setColumnWidth(5,256*50); sheet.setColumnWidth(6,256*20);

sheet.setColumnWidth(8,256*20);

sheet.setDefaultRowHeight((short)(20*20));

HSSFRow row = sheet.createRow(0);

for (int i = 0 ;i< titles.size();i++) {

HSSFCell cell = row.createCell(i);

cell.setCellValue(titles.get(i));

HSSFCellStyle cs = wb.createCellStyle();

cs.setAlignment(HSSFCellStyle.ALIGN_CENTER);

cs.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

cs.setWrapText(true); cell.setCellStyle(cs); }

for (int i = 1;i<=contents.size();i++) {

HSSFRow row1 = sheet.createRow(i);

List list = contents.get(i - 1);

for(int j= 0;j<list.size();j++){

? ? HSSCell cell = row1.createCell(j);

?? cell.setCellValue(list.get(j))

}

public static String checkBrowse(HttpServletRequest request) {

String userAgent = request.getHeader("USER-AGENT");

if(regex(OPERA,userAgent)){ return OPERA; }

if(regex(CHROME,userAgent)){ return CHROME;}

if(regex(FIREFOX,userAgent)){ return FIREFOX;}

if(regex(SAFARI,userAgent)){ return SAFARI;}

if(regex(SE360,userAgent)){ return SE360;}

if(regex(GREEN,userAgent)){ return GREEN;}

if(regex(QQ,userAgent)){ return QQ;}

if(regex(MAXTHON,userAgent)){ return MAXTHON;}

if(regex(IE11,userAgent)){ return IE11;}

if(regex(IE10,userAgent)){ return IE10;}

if(regex(IE9,userAgent)){ return IE9;}

if(regex(IE8,userAgent)){ return IE8;}

if(regex(IE7,userAgent)){ return IE7;}

if(regex(IE6,userAgent)){ return IE6;}

return OTHER;}

private static boolean regex(String regex, String str) {

Pattern p = Pattern.compile(regex, Pattern.MULTILINE);

Matcher m = p.matcher(str);

return m.find();}

出現的問題:導出按鈕在一個iframe中,使用ajax請求,服務器文件生成成功了,但是瀏覽器卻沒出現下載的文件。

解決方式:借助FileSaver插件https://github.com/eligrey/FileSaver.js

function exportExcel() {

var url ='/export';

? ? var xhr =new XMLHttpRequest();

? ? xhr.open('POST', url, true);? ? // 也可以使用POST方式,根據接口

? ? xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

? ? xhr.responseType ="blob";? // 返回類型blob

? ? // 定義請求完成的處理函數,請求前也可以增加加載框/禁用下載按鈕邏輯

? ? xhr.onload =function () {

var data =this.response;

? ? ? ? // 請求完成

? ? ? ? if (this.status ===200) {

var blob =new Blob([data], {type:"application/vnd.ms-excel"});

? ? ? ? ? ? saveAs(blob, "demo.xls");

? ? ? ? }else {

alert("導出失敗!")

}

};

? ? // 發送ajax請求

?? xhr.send($("#form").serialize())}

ps:如果導出的excel數據量特別大,XSSFWorkbook 了解下。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,818評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,733評論 18 399
  • package com.steven.utils; import org.apache.commons.lang....
    月白風清L閱讀 1,345評論 0 1
  • 一、 1、請用Java寫一個冒泡排序方法 【參考答案】 public static void Bubble(int...
    獨云閱讀 1,408評論 0 6
  • 一. Java基礎部分.................................................
    wy_sure閱讀 3,829評論 0 11