赞
踩
前言:在实际开发中经常需要将数据库的数据导出成excel文件,poi方式则是其中一种较为常用的导出框架。简单读取excel文件在之前的一篇有说明
本项目实现需求:user发出一个导出student信息的请求,直接下载包含所有student信息的excel文件到本机。只贴出关键代码,未贴出的很简单,自行脑补
整体流程(服务器端):接收请求------>取出数据库数据------>将数据存成excel临时文件------>通过响应头让浏览器下载此临时文件------>删除临时文件
项目结构:
1.导入依赖
org.apache.poi
poi
4.1.0
org.apache.poi
poi-ooxml
4.1.0
2.controller
packagecom.zjk.excel.controller;importcom.zjk.excel.service.UserServiceI;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importjavax.servlet.http.HttpServletResponse;import java.io.*;/*** @Auther: zjk
* @Date: 2019/9/16
* @Description:*/@Controller
@RequestMapping("/user")public classUserController {
@Autowired
UserServiceI userServiceI;
@RequestMapping("/export")public voidexportStu(HttpServletResponse response){//设置默认的下载文件名
String name = "学生信息表.xlsx";try{//避免文件名中文乱码,将UTF8打散重组成ISO-8859-1编码方式
name = new String (name.getBytes("UTF8"),"ISO-8859-1");
}catch(UnsupportedEncodingException e) {
e.printStackTrace();
}//设置响应头的类型
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");//让浏览器下载文件,name是上述默认文件下载名
response.addHeader("Content-Disposition","attachment;filename=\\"" + name + "\\"");
InputStream inputStream=null;
OutputStream outputStream=null;//在service层中已经将数据存成了excel临时文件,并返回了临时文件的路径
String downloadPath =userServiceI.exportStu();//根据临时文件的路径创建File对象,FileInputStream读取时需要使用
File file = newFile(downloadPath);try{//通过FileInputStream读临时文件,ServletOutputStream将临时文件写给浏览器
inputStream = newFileInputStream(file);
outputStream=response.getOutputStream();int len = -1;byte[] b = new byte[1024];while((len = inputStream.read(b)) != -1){
outputStream.write(b);
}//刷新
outputStream.flush();
}catch(Exception e) {
e.printStackTrace();
}finally{//关闭输入输出流
try{if(inputStream != null) {
inputStream.close();
}
}catch(IOException e) {
e.printStackTrace();
}try{if(outputStream != null) {
outputStream.close();
}
}catch(IOException e) {
e.printStackTrace();
}
}//最后才能,删除临时文件,如果流在使用临时文件,file.delete()是删除不了的
file.delete();
}
}
3.service
packagecom.zjk.excel.service.impl;importcom.zjk.excel.dao.StudentDao;importcom.zjk.excel.dao.UserDao;importcom.zjk.excel.entity.Student;importcom.zjk.excel.service.UserServiceI;importorg.apache.poi.xssf.usermodel.XSSFCell;importorg.apache.poi.xssf.usermodel.XSSFRow;importorg.apache.poi.xssf.usermodel.XSSFSheet;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;import java.io.*;importjava.util.List;importjava.util.UUID;/*** @Auther: zjk
* @Date: 2019/9/16
* @Description:*/@Servicepublic class UserService implementsUserServiceI {
//创建临时文件存放的路径private String temp="d:\\\\temp\\\\excel\\\\";
@Autowired
UserDao userDao;
@Autowired
StudentDao studentDao;
@OverridepublicString exportStu() {
List list =studentDao.queryAllStu();//创建工作簿
XSSFWorkbook xssfWorkbook = newXSSFWorkbook();//创建工作表
XSSFSheet sheet =xssfWorkbook.createSheet();
xssfWorkbook.setSheetName(0,"学生信息表");//创建表头
XSSFRow head = sheet.createRow(0);
String[] heads= {"编号","姓名","年龄","性别","手机号"};for(int i = 0;i < 5;i++){
XSSFCell cell=head.createCell(i);
cell.setCellValue(heads[i]);
}for (int i = 1;i <= 4;i++) {
Student student= list.get(i - 1);//创建行,从第二行开始,所以for循环的i从1开始取
XSSFRow row =sheet.createRow(i);//创建单元格,并填充数据
XSSFCell cell = row.createCell(0);
cell.setCellValue(student.getS_id());
cell= row.createCell(1);
cell.setCellValue(student.getS_name());
cell= row.createCell(2);
cell.setCellValue(student.getS_age());
cell= row.createCell(3);
cell.setCellValue("男".equals(student.getS_gender().trim())?"男":"女");
cell= row.createCell(4);
cell.setCellValue(student.getS_tel());
}//创建临时文件的目录
File file = newFile(temp);if(!file.exists()){
file.mkdirs();
}//临时文件路径/文件名
String downloadPath = file + "\\\\" +System.currentTimeMillis() +UUID.randomUUID();
OutputStream outputStream= null;try{
//使用FileOutputStream将内存中的数据写到本地,生成临时文件
outputStream= newFileOutputStream(downloadPath);
xssfWorkbook.write(outputStream);
outputStream.flush();
}catch(Exception e) {
e.printStackTrace();
}finally{try{if(outputStream != null) {
outputStream.close();
}
}catch(IOException e) {
e.printStackTrace();
}
}returndownloadPath;
}
}
4.效果
WPS打开后:可以说是非常的丑陋了,接下来优化一下
在service中增加如下代码:总体而言还是很麻烦的,创建CellStyle,还要在你想改变样式的cell进行cell.setCellStyle(style1)才可以
*博主用的版本比较新,所以很多地方较旧版本有区别
//创建styleHead
CellStyle styleHead =xssfWorkbook.createCellStyle();
styleHead.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());//背景色
styleHead.setFillPattern(FillPatternType.SOLID_FOREGROUND);
styleHead.setAlignment(HorizontalAlignment.CENTER);//水平居中
XSSFFont font =xssfWorkbook.createFont();
font.setBold(true);//加粗
font.setFontHeight((short)240);//字体大小
styleHead.setFont(font);//创建style1
CellStyle style1 =xssfWorkbook.createCellStyle();
style1.setFillForegroundColor(IndexedColors.LEMON_CHIFFON.getIndex());//背景色
style1.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style1.setAlignment(HorizontalAlignment.CENTER);//水平居中//创建style2
CellStyle style2 =xssfWorkbook.createCellStyle();
style2.setFillForegroundColor(IndexedColors.LIGHT_TURQUOISE.getIndex());//背景色
style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style2.setAlignment(HorizontalAlignment.CENTER);//水平居中 sheet.setColumnWidth(4,3500);//给第5列设置宽度(tel栏)
优化后:
总结一下:
poi的简单使用还是不难的,说白了就数据库一个表对应一个sheet,表的一行对应一个row,表某一行的一个数据对应一个cell,嗯,就是这么简单。
说到调样式就非常头疼了,而且新版本的较之前改动比较大,百度出来的东西很多都没法用,勉强捣鼓了一些出来。
最后给自己打打气-——世上无难事,只要肯登攀!
注意事项:
不要使用post请求,应该用get请求
最后推荐一个中文poi文档:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。