springboot2.1.8使用poi导出数据生成excel(.xlsx)文件
springboot2.1.8使用poi导出数据生成excel(.xlsx)文件
前言:在实际开发中经常需要将数据库的数据导出成excel文件,poi方式则是其中一种较为常用的导出框架。简单读取excel文件在之前的一篇有说明
本项目实现需求:user发出一个导出student信息的请求,直接下载包含所有student信息的excel文件到本机。只贴出关键代码,未贴出的很简单,自行脑补
整体流程(服务器端):接收请求------>取出数据库数据------>将数据存成excel临时文件------>通过响应头让浏览器下载此临时文件------>删除临时文件
项目结构:
org.apache.poi
poi
4.1.0
org.apache.poi
poi-ooxml
4.1.0
package com.zjk.excel.controller;
import com.zjk.excel.service.UserServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
/**
* @Auther: zjk
* @Date: 2019/9/16
* @Description:
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
UserServiceI userServiceI;
@RequestMapping("/export")
public void exportStu(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 = new File(downloadPath);
try {
//通过FileInputStream读临时文件,ServletOutputStream将临时文件写给浏览器
inputStream = new FileInputStream(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();
}
}
package com.zjk.excel.service.impl;
import com.zjk.excel.dao.StudentDao;
import com.zjk.excel.dao.UserDao;
import com.zjk.excel.entity.Student;
import com.zjk.excel.service.UserServiceI;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.util.List;
import java.util.UUID;
/**
* @Auther: zjk
* @Date: 2019/9/16
* @Description:
*/
@Service
public class UserService implements UserServiceI {
//创建临时文件存放的路径
private String temp="d:\\temp\\excel\\";
@Autowired
UserDao userDao;
@Autowired
StudentDao studentDao;
@Override
public String exportStu() {
List list = studentDao.queryAllStu();
//创建工作簿
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
//创建工作表
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 = new File(temp);
if(!file.exists()){
file.mkdirs();
}
//临时文件路径/文件名
String downloadPath = file + "\\" +System.currentTimeMillis() + UUID.randomUUID();
OutputStream outputStream = null;
try {
//使用FileOutputStream将内存中的数据写到本地,生成临时文件
outputStream = new FileOutputStream(downloadPath);
xssfWorkbook.write(outputStream);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return downloadPath;
}
}
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请求
https://www.cnblogs.com/fqfanqi/p/6172223.html
springboot2.1.8使用poi导出数据生成excel(.xlsx)文件相关教程
详解木头自动填表浏览器使用方法
详解木头自动填表浏览器使用方法 用木头多功能浏览器如何自动填写网页表单?下面用soso网站做为例子,说明具体分析方法和设置步骤。 1、首先打开木头浏览器,在自动控制菜单中,找到并打开项目管理器 2、在项目管理器中,选择默认项目,点击右键,再在弹出的
SQL优化--使用 EXISTS 代替 IN 和 关联查询(inner join) (转载)
SQL优化--使用 EXISTS 代替 IN 和 关联查询(inner join) (转载)http://www.cnblogs.com/zping/archive/2008/08/05/126095... 在使用Exists时,如果能正确使用,有时会提高查询速度: 1,使用Exists代替inner join 2,使用Exists代替 in 1,使用Exists代替in
python——虚拟环境之pipenv的安装及使用(windows1064位)
python——虚拟环境之pipenv的安装及使用(windows10,64位) 1 简介 pipenv是requests作者的一个项目,整合了virtualenv、pip、pipfile , 用于更方便地为项目建立虚拟环境并管理虚拟环境中的第三方模块。不需要再分别使用pip和virtualenv,直接使用pipenv即可
@程序员,React 使用如何避坑?
@程序员,React 使用如何避坑? @程序员,如何更好地写React? 作者 |Alex K 译者 |苏本如,责编 | 郭芮出品 | CSDN(ID:CSDNnews) 以下为译文: 在Stack Overflow上回答与React框架相关的问题时,我注意到人们对于这个框架有几类主要的问题。我决定将一些
SVN的使用
SVN的使用 工作蛮久了,关于代码管理工具:开源代码一般都是使用github,它的使用大多都是以命令行的形式进行(有在coding上做一些demo,但对github命令还是不熟,只能说会用一点,久了还得再看);很多企业用的大多是svn,vs自带的团队资源管理(TFS)。TFS
iTOP4412精英版QtE5.7编译_putty工具的使用
iTOP4412精英版QtE5.7编译_putty工具的使用 本章节讲解:基于iTOP4412精英版之上QtE5.7编译_putty工具的使用 用户手册 3.3.5 小节介绍 SSH 工具,在 Ubuntu16.04 上有一定的概率使用不了,本节介 绍替换 SSH 控制台的工具 putty。 putty 工具是网盘“iTOP-44
Java进阶教程:使用Lombok提升开发效率
Java进阶教程:使用Lombok提升开发效率 Java进阶教程:使用Lombok提升开发效率 Lombok Lombok是一种Java?实用工具,可用来帮助开发人员消除Java的冗长代码,尤其是对于简单的Java对象(POJO)。它通过注释实现这一目的 。通过在开发环境中实现Lombok,开发人
李洪强iOS开发之自定义cell的使用
李洪强iOS开发之自定义cell的使用 第一步: 创建自定义cell类,继承自UItableVIewcell 第二步: 在sb中布局自己需要的视图控件并且将此cell与我刚刚创建的cell类进行关联.并且连线 第三步: 创建modle类,继承自NSobject 第四步: 在modle中定义自定义cell需要的属