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阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,600评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,587评论 18 399
  • package com.steven.utils; import org.apache.commons.lang....
    月白风清L阅读 1,322评论 0 1
  • 一、 1、请用Java写一个冒泡排序方法 【参考答案】 public static void Bubble(int...
    独云阅读 1,348评论 0 6
  • 一. Java基础部分.................................................
    wy_sure阅读 3,791评论 0 11