ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringBoot+Vue+POI+Mybatis-Plus+实现数据导出到Excel表格

2022-03-19 23:03:34  阅读:213  来源: 互联网

标签:style Vue java SpringBoot Excel 设置 org import com


作者: Memory(星哥) Wechat:/QQ: 574373426
整理不易,感谢支持,欢迎 收藏 转发 分享
专注IT职业教育多年,学编程找星哥

利用Apache POI将数据导出到Excel

技术栈

前后端分离
后端采用 SpringBoot框架,整合 web , Mybtais-Plus , Apache POI , lombok
前端采用 Vue, ElementUI 做一个简易的页面发起请求(只有一个按钮)
数据库采用 Mysql
开发工具 IDEA2020.3.4

准备前端页面

前端页面采用Vue+ElementUI
为了方便测试,没有构建Vue项目,直接引入对应的js文件
采用cdn在线引入的方式,也可以下载到本地引入
发起请求的方式: 采用 window.open(url)
作用: 发起请求,在新窗口打开,后续我们点击导出后,会在新窗口下载excel文件
也可以使用axios或者其他ajax发起请求,但需要注意要设置返回值类型
这里为了方便 直接使用 window.open(url) 效果是一样的
效果如下: 只有一个按钮
在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<!-- Vue开发环境版本,包含了有帮助的命令行警告 -->
		<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
		<!-- Element 引入样式 -->
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<!-- Element引入组件库 -->
		<script src="https://unpkg.com/element-ui/lib/index.js"></script>
		<div id="app">
			  <el-button type="primary" @click="exportTest">导出</el-button>
		</div>
		<script>
			var vue = new Vue({
				el: "#app",
				methods: {
					exportTest(){
					 	// 这里可以传入一些查询参数,我在这里传入了标题内容 
					 	// 将标题内容作为导出的Excel文件名,此处的标题内容后期可动态改变
					    var url = 'http://localhost:8080/reportExport/prodTest?excelTitle=用户管理'
					    window.open(url)
					  }
				}
			})	
		</script>
	</body>
</html>

创建SpringBoot项目

使用阿里云脚手架创建SpringBoot项目: https://start.aliyun.com
在这里插入图片描述
在这里插入图片描述
勾选Web依赖
创建项目后手动在pom.xml中添加也行 , 图个方便 , 就顺手勾一下
在这里插入图片描述

导入相关依赖

web,POI,jdbc,Mybatis-Plus,lombok

<dependencies>
        <!--web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- POI EXCEL 文件读写 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-excelant</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.1.2</version>
        </dependency>
        <!--jdbc依赖包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--spring整合mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.4.3</version>
        </dependency>
        <!--添加lombok的包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

准备数据库数据

User表存储 用户ID 用户名 密码 用户状态信息
后期将此数据导出到Excel表格中
在这里插入图片描述
数据库文件

#创建数据库
CREATE database poidata DEFAULT CHARACTER SET utf8;
#使用数据库
use poidata;
#创建表格
create table user(
id int primary key auto_increment,
name varchar(10),
pwd varchar(10),
status int
) charset utf8;
#插入数据
insert into user(id,name,pwd,status) value (null,'张三','123',1);
insert into user(id,name,pwd,status) value (null,'学编程找星哥','574373426',1);
insert into user(id,name,pwd,status) value (null,'李四','123',0);

在Application.yml配置文件中整合数据源

server:
  port: 8080

#管理数据源
spring:
  datasource:
    #高版本驱动使用
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/poidata?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    #设定用户名和密码
    username: root
    password: root

创建实体类对象

在 com.xg.pojo 中创建实体类User
实体类属性要与数据库字段名保持一致

@Data
public class User {
    private Integer id;
    private String name;
    private String pwd;
    private Integer status;
}

创建Mapper

在com.xg.mapper下创建ReportMapper
并继承BaseMapper,必须范型User
Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能

package com.xg.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xg.pojo.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface ReportMapper extends BaseMapper<User> {

}

创建Controller

在controller方法中可直接注入HttpServletResponse对象

package com.xg.controller;

import com.xg.service.ReportService;
import org.apache.tools.ant.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;

@Controller
@CrossOrigin //允许跨域请求
public class RequestController {

    @Autowired
    ReportService reportService;

    @GetMapping("/reportExport/prodTest")
    public Object prodTest(HttpServletResponse response, String excelTitle) throws IOException {
        // 创建导出文件名称 当前日期+前台传递过来的标题名(excelTitle)
        String fileName = DateUtils.format(new Date(),"yyyyMMddHHmmss") +"-"+excelTitle+".xls";
        // 设置返回的消息头和返回值类型 并设置编码 不设置编码文件名为中文的话 不会显示
        // 当设置成如下返回值时,浏览器才会执行下载文件动作
        response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
        response.setContentType("APPLICATION/OCTET-STREAM;charset=UTF-8");
        // 创建输出流,调用service中exportTest方法,参数:输出流 标题名
        reportService.exportTest(response.getOutputStream(), excelTitle);
        return null;
    }
}

创建Service

在com.xg.service包下创建 ReportService 接口

package com.xg.service;

import java.io.IOException;
import java.io.OutputStream;

public interface ReportService {
    void exportTest(OutputStream out, String excelTitle) throws IOException;
}

在com.xg.service包下创建 ReportServiceImpl 实现类,重写exportTest方法
exportTest方法接收Controller传递过来的输出流以及标题名

package com.xg.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xg.mapper.ReportMapper;
import com.xg.pojo.User;
import com.xg.util.ExportExcel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ReportServiceImpl implements ReportService{
    @Autowired
    ReportMapper reportMappe;

    @Override
    public void exportTest(OutputStream out, String excelTitle) throws IOException {
        // 定义列标 就是一个Excel的标题而已 下面有图介绍
        String[] rowsName = new String[]{"用户id", "用户名", "密码", "是否禁用"};
        // 创建导出数据集合 后续会将dataList中的数据写到Excel
        List<Object[]> dataList = new ArrayList<Object[]>();
        // 从数据库查询用户列表
        QueryWrapper queryWrapper = new QueryWrapper();
        List<User> userList = reportMappe.selectList(queryWrapper);
        User user = null;
        // 将用户列表信息封装到一个Object数组
        // 我这里封装Object数组 是为了方便后续代码复用,不会将对象类型写死
        // 当然也可以在下一层使用反射来做,太麻烦了 还是这样转一下吧
        for (int i=0;i<userList.size();i++){
        	//将数据库查到的每条数据 循环封装到Object[]
            user=userList.get(i);
            Object[] objs = new Object[]{user.getId(),user.getName(),user.getPwd(),user.getStatus()};
            //将转换好的数据 存入dataList
            dataList.add(objs);
        }
        // 创建ExportExcel工具类对象 通过构造方法赋值
        ExportExcel ex = new ExportExcel(excelTitle, rowsName, dataList);
        try {
        // 调用生成Excel的方法,将数据通过输出流写出
            ex.export(out);
        } catch (Exception e) {
            e.printStackTrace();
        }
        out.flush();
        out.close();
    }
}

核心: ExportExcel工具类(创建Excel,Sheet,行,表格,样式)

这个工具类里封装的就是Apache POI 给我们提供的对象,用来创建一个Excel表格
一定要仔细看以下图文,看懂你才能了解业务代码,话不多说,线上成果图,结合结果进行理解

首先在生成Excel前,我们需要理解一下Excel文件的构成。
在POI中式这样理解的 :
一个Excel对应一个workbook对象
一个workbook是由若干个sheet组成
一个sheet有多个row 行
一个row有多个列cell 列/单元格

在这里插入图片描述

对于生成Excel,POI提供了如下几个基本对象
HSSFWorkbook : excel的文档对象
HSSFSheet : excel的一个sheet
HSSFRow : excel的行
HSSFCell : excel的子单元格

ExportExcel工具类

HSSFCellStyle()方法是设置 表格标题样式
HSSFCellStyle()方法是设置 表格数据样式
当然样式不设置也行,我们导出Excel后手动在Excel中设置也行,千万不要认为代码一大堆看起来就烦,其实真正核心的代码没多少

标题(title) 就是上图中蓝色背景的用户管理,当然不设标题也行,随便喽
列标就是上图 用户id,用户名,密码,是否禁用,一般表格都有列标题吧

package com.xg.util;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class ExportExcel {
    // 导出表的标题
    private String title;
    // 导出表的列名
    private String[] rowName;
    // 导出表的数据
    private List<Object[]> dataList = new ArrayList<Object[]>();

    // 构造函数,传入要导出的数据
    public ExportExcel(String title, String[] rowName, List<Object[]> dataList) {
        this.dataList = dataList;
        this.rowName = rowName;
        this.title = title;
    }

    // 导出数据
    public void export(OutputStream out) throws Exception {
        try {
            //1.创建一个workbook,一个workbook 对应一个Excel文件
            HSSFWorkbook workbook = new HSSFWorkbook();
            //2.创建 sheet excel中多个sheet组成一个excel文件 至少有一个sheet
            HSSFSheet sheet = workbook.createSheet(title);

            //3.在sheet中添加表头第0行
            HSSFRow rowm = sheet.createRow(0);
            //4.创建单元格
            HSSFCell cellTitle = rowm.createCell(0);

            //5.定义标题样式 和 数据样式
            HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
            HSSFCellStyle style = this.getStyle(workbook);
            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1)));
            cellTitle.setCellStyle(columnTopStyle);
            //6.给单元格设置值
            cellTitle.setCellValue(title);

            //7.获取列标长度
            int columnNum = rowName.length;
            // 创建列 相当于一行 2代表第三行 因为上面的总标题占了两行为 0 1
            HSSFRow rowRowName = sheet.createRow(2);

            //8.将列标题设置到单元格中
            for (int n = 0; n < columnNum; n++) {
                HSSFCell cellRowName = rowRowName.createCell(n);
                cellRowName.setCellType(CellType.STRING);
                HSSFRichTextString text = new HSSFRichTextString(rowName[n]);
                cellRowName.setCellValue(text);
                cellRowName.setCellStyle(style);
            }

            //9.将数据设置到单元格中
            for (int i = 0; i < dataList.size(); i++) {
                Object[] obj = dataList.get(i);
                HSSFRow row = sheet.createRow(i + 3);
                for (int j = 0; j < obj.length; j++) {
                    HSSFCell cell = null;
                    cell = row.createCell(j, CellType.STRING);
                    if (!"".equals(obj[j]) && obj[j] != null) {
                        cell.setCellValue(obj[j].toString());
                    } else {
                        cell.setCellValue(" ");
                    }
                    cell.setCellStyle(style);
                }
            }


            if (workbook != null) {
                try {
                    //10.将整个表格写出
                    workbook.write(out);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) { }
    }

    /**
     * 表格标题样式
     */
    public HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
        // 设置字体
        HSSFFont font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short) 11);
        // 设置字体颜色
        font.setColor(IndexedColors.WHITE.getIndex());
        // 字体加粗
        font.setBold(true);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置标题背景色
        style.setFillForegroundColor(IndexedColors.DARK_TEAL.getIndex());
        // 设置背景颜色填充样式
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 设置低边框
        style.setBorderBottom(BorderStyle.THIN);
        // 设置低边框颜色
        style.setBottomBorderColor(IndexedColors.ROYAL_BLUE.getIndex());
        // 设置右边框
        style.setBorderRight(BorderStyle.THIN);
        // 设置顶边框
        style.setTopBorderColor(IndexedColors.ROYAL_BLUE.getIndex());
        // 设置顶边框颜色
        style.setTopBorderColor(IndexedColors.ROYAL_BLUE.getIndex());
        // 在样式中应用设置的字体
        style.setFont(font);
        // 设置自动换行
        style.setWrapText(false);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;
    }

    /**
     * 表格数据样式
     */
    public HSSFCellStyle getStyle(HSSFWorkbook workbook) {
        // 设置字体
        HSSFFont font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short) 10);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式;
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置底边框;
        style.setBorderBottom(BorderStyle.THIN);
        // 设置底边框颜色;
        style.setBottomBorderColor(IndexedColors.ROYAL_BLUE.getIndex());
        // 设置左边框;
        style.setBorderLeft(BorderStyle.THIN);
        // 设置左边框颜色;
        style.setLeftBorderColor(IndexedColors.ROYAL_BLUE.getIndex());
        // 设置右边框;
        style.setBorderRight(BorderStyle.THIN);
        // 设置右边框颜色;
        style.setRightBorderColor(IndexedColors.ROYAL_BLUE.getIndex());
        // 设置顶边框;
        style.setBorderTop(BorderStyle.THIN);
        // 设置顶边框颜色;
        style.setTopBorderColor(IndexedColors.ROYAL_BLUE.getIndex());
        // 在样式用应用设置的字体;
        style.setFont(font);
        // 设置自动换行;
        style.setWrapText(false);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(HorizontalAlignment.CENTER);
        // 设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;
    }
}

启动项目测试

整体项目结构如下
在这里插入图片描述

启动项目测试,点击导出
在这里插入图片描述
在这里插入图片描述

如果逻辑不清晰,建议跟着流程先把代码复制下去,实现了效果,自己在打断点跟流程
整理不易,感谢支持
学编程找星哥,么么哒

标签:style,Vue,java,SpringBoot,Excel,设置,org,import,com
来源: https://blog.csdn.net/qq_40300227/article/details/123603406

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有