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.創(chuàng)建一個workBook.

HSSFWorkbook wb = new HSSFWorkbook();

2.創(chuàng)建一張sheet

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

3.創(chuàng)建第一行

HSSFRow row = sheet.createRow(0);

構造方法中的數(shù)值表示創(chuàng)建第幾行砾嫉,索引從0開始

4.創(chuàng)建一個單元格

HSSFCell cell = row.createCell(0);

構造方法中的數(shù)值表示創(chuàng)建第幾列簇爆,索引從0開始

5.向表格中添加數(shù)據(jù)

cell.setCellValue().

此時谷市,一個excel的雛形已經(jīng)創(chuàng)建好了砂缩,但是胁出,怎么導出并下載呢沟启?

需要用到HttpServletResponse忆家。

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

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

2.設置字符編碼

response.setCharacterEncoding("utf-8");

3.根據(jù)瀏覽器進行轉(zhuǎn)碼德迹,使其支持中文文件名

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表格了芽卿。

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

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));

將多個單元格合成一個單元格,參數(shù)依次為起始行呻袭,結束行眨八,起始列,結束列左电。

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

1.先生成第一個單元格

HSSFCell cell = row.createCell(0);

2.合并

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

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

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

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方法,該方法為按鈕的點擊事件綁定的方法器仗,點擊后通過將參數(shù)拼接到url的方式進行傳參融涣。(有點丑,有更好的可以推薦G嘧啤)

?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();}

出現(xiàn)的問題:導出按鈕在一個iframe中暴心,使用ajax請求,服務器文件生成成功了杂拨,但是瀏覽器卻沒出現(xiàn)下載的文件专普。

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

function exportExcel() {

var url ='/export';

? ? var xhr =new XMLHttpRequest();

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

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

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

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

? ? 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("導出失敗!")

}

};

? ? // 發(fā)送ajax請求

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

ps:如果導出的excel數(shù)據(jù)量特別大檀夹,XSSFWorkbook 了解下筋粗。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市炸渡,隨后出現(xiàn)的幾起案子娜亿,更是在濱河造成了極大的恐慌,老刑警劉巖蚌堵,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件买决,死亡現(xiàn)場離奇詭異,居然都是意外死亡吼畏,警方通過查閱死者的電腦和手機督赤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泻蚊,“玉大人躲舌,你說我怎么就攤上這事⌒孕郏” “怎么了没卸?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長秒旋。 經(jīng)常有香客問我约计,道長,這世上最難降的妖魔是什么迁筛? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任病蛉,我火速辦了婚禮,結果婚禮上瑰煎,老公的妹妹穿的比我還像新娘。我一直安慰自己俗孝,他們只是感情好酒甸,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赋铝,像睡著了一般插勤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上革骨,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天农尖,我揣著相機與錄音,去河邊找鬼良哲。 笑死盛卡,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的筑凫。 我是一名探鬼主播滑沧,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼并村,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了滓技?” 一聲冷哼從身側(cè)響起哩牍,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎令漂,沒想到半個月后膝昆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡叠必,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年荚孵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挠唆。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡处窥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玄组,到底是詐尸還是另有隱情滔驾,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布俄讹,位于F島的核電站哆致,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏患膛。R本人自食惡果不足惜摊阀,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望踪蹬。 院中可真熱鬧胞此,春花似錦、人聲如沸跃捣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疚漆。三九已至酣胀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娶聘,已是汗流浹背闻镶。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丸升,地道東北人铆农。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像狡耻,于是被迫代替她去往敵國和親顿涣。 傳聞我的和親對象是個殘疾皇子波闹,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)涛碑,斷路器精堕,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法蒲障,內(nèi)部類的語法歹篓,繼承相關的語法,異常的語法揉阎,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • package com.steven.utils; import org.apache.commons.lang....
    月白風清L閱讀 1,336評論 0 1
  • 一庄撮、 1、請用Java寫一個冒泡排序方法 【參考答案】 public static void Bubble(int...
    獨云閱讀 1,375評論 0 6
  • 一. Java基礎部分.................................................
    wy_sure閱讀 3,811評論 0 11