SpringBoot之把数据库导出到Excel表
在上一篇的《SpringBoot之Excel表动态导入数据库》中我讲解了怎么样把我们本地的Excel文件中的数据导入到服务器端的数据库里面(当然这需要Excel表中的的数据格式与数据表中的字段格式一样的前提之下才可完成),所以在这一篇文章中我要讲解的是如何动态的把数据库中的数据导出到本地的Excel文件中。好了废话咋就不多说了,直接上操作代码。(前面三步的操作和上一篇基本一样)
- 用maven导入一些jar包
<!--导出excel表的依赖-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- 响应前端时转换json数据 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.11</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.11</version>
</dependency>
<!-- 转换json用 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
<!-- jackson转换json用 @ResponseBody默认调用jackson,将java对象转为json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.7</version>
</dependency>
- 前端代码(采用的是layui 框架,当然我是修改框架里面的源码的)
<!-- 导入/导出到 Excel 操作 -->
<div class="layui-btn-group" style="float: right; height: 55px; margin-top: 10px; margin-right: 35px;">
<button class="layui-btn layui-btn-sm refresh" dw-url="/BirthdayRecord/exportExcel">
<i class="layui-icon"></i>导出Excel
</button>
<button class="layui-btn layui-btn-sm operation-excel" id="operation-excel" dw-url="/BirthdayRecord/updateExcel">
<i class="layui-icon"></i>Excel导入
</button>
</div>
- JavaScript前端页面逻辑操作
<!-- 设置Excel文件上传 -->
<script>
layui.use('upload', function() {
var $ = layui.jquery
, upload = layui.upload;
//Excel文件上传
var uploadInst = upload.render({
elem: '#operation-excel',//触发元素
url: $('#operation-excel').attr("dw-url"),//上传服务器端的接收路径
auto: true,//可自动上传(选好文件后)
accept: 'file',//接收所有的文件类型
exts: 'xls|xlsx|excel',//校验上传文件的格式
before: function(){//文件上传前的钩子
if ($('#operation-excel').attr("dw-url") == undefined){
layer.msg("请给button加上dw-url属性");
return false;
}
},
done: function (res) {//文件上传成功后的钩子
if (res.code == 1) {
layer.msg('上传成功',{icon:6});
}else {
layer.msg('上传失败',{icon:6});
}
},
error: function () {//文件上传失败后的钩子
//演示失败状态,并实现重传
picText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>');
picText.find('.demo-reload').on('click', function () {
uploadInst.upload();
});
},
});
});
</script>
- Controller控制层
/**
* 需求功能:完成服务器端把数据库中的数据读出客户端Excel文件的功能
*
* @param response //把生成的Excel表响应到客户端
* @throws NoSuchMethodException //报错
* @throws IllegalAccessException //报错
* @throws InvocationTargetException //报错
* @throws InstantiationException //报错
*/
@GetMapping("/exportExcel")
public void exportExcel(HttpServletResponse response) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//先把数据库中的数据查询出来
List<BirthdayRecord> list1 = birthdayRecordService.selectList(null);
//一个设置Excel表标题信息的工具类,获取Excel表标题的字符串数组
String[] strings = ExcelTitlesHelperUtils.getBirthdayRecordTitles();
//一个能把对象集合转换成字符串数组集合的工具类,参数为对象集合,返回字符串数组集合
List<Object[]> list = ExcelValuesHelperUtils.exportExcel(list1);
try {
//一个能创建Excel表并完成发送客户端的工具类,第一个参数为字符串数组集合(Excel表内容),第二个参数为字符串数组(Excel表标题),第三个参数为响应器
ExportExcelUtils.createExcelUtils(list, strings, response);
} catch (Exception e){
//导表发生异常的时候
throw new MyException(ResultEnum.EXPORT_EXCEL_ERROR.getCode(),ResultEnum.EXPORT_EXCEL_ERROR.getMsg());
}
}
- 实体类
/**
* 生育纪录表
*/
public class BirthdayRecord implements Serializable {
private static final long serialVersionUID = 4849616019539107195L;
/**
* 自增主键
*/
@TableId(value = "bir_id", type = IdType.AUTO)
private Integer birId;
/**
* 头胎还是其他胎
*/
private String birType;
/**
* 产检医院
*/
private String birProdInspHos;
/**
* 分娩医院
*/
private String birMaterHos;
/**
* 计生证号码
*/
private String birNumber;
/**
* 手术日期
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birOperationTime;
/**
* 员工外键
*/
private Integer empId;
public BirthdayRecord() {
}
public BirthdayRecord(Integer birId, String birType, String birProdInspHos, String birMaterHos, String birNumber, Date birOperationTime, Integer empId) {
this.birId = birId;
this.birType = birType;
this.birProdInspHos = birProdInspHos;
this.birMaterHos = birMaterHos;
this.birNumber = birNumber;
this.birOperationTime = birOperationTime;
this.empId = empId;
}
public Integer getBirId() {
return birId;
}
public void setBirId(Integer birId) {
this.birId = birId;
}
public String getBirType() {
return birType;
}
public void setBirType(String birType) {
this.birType = birType;
}
public String getBirProdInspHos() {
return birProdInspHos;
}
public void setBirProdInspHos(String birProdInspHos) {
this.birProdInspHos = birProdInspHos;
}
public String getBirMaterHos() {
return birMaterHos;
}
public void setBirMaterHos(String birMaterHos) {
this.birMaterHos = birMaterHos;
}
public String getBirNumber() {
return birNumber;
}
public void setBirNumber(String birNumber) {
this.birNumber = birNumber;
}
public Date getBirOperationTime() {
return birOperationTime;
}
public void setBirOperationTime(Date birOperationTime) {
this.birOperationTime = birOperationTime;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
@Override
public String toString() {
return "BirthdayRecord{" +
", birId=" + birId +
", birType=" + birType +
", birProdInspHos=" + birProdInspHos +
", birMaterHos=" + birMaterHos +
", birNumber=" + birNumber +
", birOperationTime=" + birOperationTime +
", empId=" + empId +
"}";
}
}
- 一些辅助的工具方法
/**
* 一个提供设置Excel表标题内容的字符串数组
* @return
*/
public static String[] getBirthdayRecordTitles(){
String[] titles = {"ID","头胎/其他胎","产检医院","分娩医院","计生证号码","手术日期","员工外键"};
return titles;
}
===============================================================================
/**
* 功能分析:把对象集合转换成数组集合
*
* @param list:需要操作的实体类集合
* @return
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static List<Object[]> exportExcel(List list) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//设置用到的变量参数
String name = null, type = null, m_name = null;
Object value = null;
//创建一个二维字符串数组存放数据
List<Object[]> list1 = new ArrayList<>();
//获取实体类方法操作对象
Method m = null;
//判断要提取实体类属性数据的集合是否为空
if (list != null){
//遍历集合中的实体类
for (int y=0; y<list.size(); y++){
//获取每一个实体类
Object object = list.get(y);
//获取实体类的所有属性,返回Field数组
Field[] fields = object.getClass().getDeclaredFields();
//创建一个数组存放实体类属性数据
Object[] str = new Object[fields.length];
//遍历实体类的所有属性
for (int i=0; i<fields.length; i++){
name = fields[i].getName();//获取属性的名字
m_name = name.substring(0,1).toUpperCase()+name.substring(1); //将属性的首字符大写,方便构造get,set方法
type = fields[i].getGenericType().toString(); //获取属性的类型
//判断属性的类型修改数据结构
switch (type){
case "class java.lang.String":
m = object.getClass().getMethod("get"+m_name); //组装getter方法
value = (String) m.invoke(object); //调用getter方法获取属性值
if (value != null){
/**
* 你可以进行附加操作
*/
}
break;
case "class java.lang.Double":
m = object.getClass().getMethod("get"+m_name);
value = m.invoke(object); //调用getter方法获取属性值
if (value != null){
}
break;
case "class java.lang.Boolean":
m = object.getClass().getMethod("get"+m_name); //组装getter方法
value = m.invoke(object); //调用getter方法获取属性值
if (value != null){
}
break;
case "class java.lang.Integer":
m = object.getClass().getMethod("get"+m_name);
value = m.invoke(object); //调用getter方法获取属性值
if (value != null){
}
break;
case "class java.util.Date":
m = object.getClass().getMethod("get"+m_name);
value = m.invoke(object); //调用getter方法获取属性值
if (value != null){
value = new SimpleDateFormat("yyyy-MM-dd").format(value);//改变时间的格式
}
break;
case "class java.lang.Float":
m = object.getClass().getMethod("get"+m_name);
value = m.invoke(object); //调用getter方法获取属性值
if (value != null){
}
break;
case "class java.lang.Long":
m = object.getClass().getMethod("get"+m_name);
value = m.invoke(object); //调用getter方法获取属性值
if (value != null){
}
break;
case "class java.lang.Byte":
m = object.getClass().getMethod("get"+m_name);
value = m.invoke(object); //调用getter方法获取属性值
if (value != null){
}
break;
}
//把实体类中的属性存放到一个字符串数组中
str[i] = value;
}
//把字符串数组存放到集合中
list1.add(str);
}
}
return list1;
}
=================================================================================
public static void createExcelUtils(List<Object[]> values, String[] titles, HttpServletResponse httpServletResponse) throws IllegalAccessException, InstantiationException {
// 第一步,创建一个webbook,对应一个Excel文件
HSSFWorkbook wb = new HSSFWorkbook();
// 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet
HSSFSheet sheet = wb.createSheet("会议签到表");
// 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
HSSFRow row = sheet.createRow((int) 0);
// 第四步,创建单元格,并设置值表头 设置表头居中
HSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式
//第五步,创建标题
for (int i =0 ; i < titles.length ; i++){
HSSFCell cell = row.createCell((short) i);
cell.setCellValue(titles[i]);
}
//第六步,写入实体数据,遍历创建内容
for(int i=0;i<values.size();i++){//总共多少行
Object[] str = values.get(i);
row = sheet.createRow(i + 1);//第几行
for(int j=1;j<str.length;j++){
//将内容按顺序赋给对应的列对象
row.createCell(j-1).setCellValue(str[j].toString());//每行塞什么数据
}
}
//第六步,下载excel表格
OutputStream out = null;
try {
out = httpServletResponse.getOutputStream();
String fileName = UUID.randomUUID().toString()+".xls";// 文件名
httpServletResponse.setContentType("application/x-msdownload");//文件格式
httpServletResponse.setHeader("Content-Disposition", "attachment; filename="
+ URLEncoder.encode(fileName, "UTF-8"));//响应头以及文件名,编码格式
wb.write(out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
基本完成了,一些自定义的报错赋值类可查看上一篇《SpringBoot之Excel表动态导入数据库》