基于springBoot、vue导出Excel文件

文章目录

  • 前言
  • 一、运行环境
  • 二、使用步骤
    • 1.导入依赖
    • 2.前端代码
    • 3.后端代码
    • 4.运行结果


前言

最近在做公司管理系统的Excel导出功能,使用的是Poi。查阅了许多网上的代码,基本上都不是很全面,代码跑不起来。在不停的试错之后终于实现了,下面贴上代码和相关注释。


一、运行环境

SpringBoot、jdk15(版本不影响)、vue3.0

二、使用步骤

1.导入依赖

在pom.xml中添加poi的依赖:

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.14</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.14</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.14</version>
		</dependency>

2.前端代码

代码如下(示例):

 exportExcel:function(){
				this.$http({
					//发送ajax获得后台查询的数据往表里添
				    url: this.$http.adornUrl('/student/student/export'),
				    method: 'post',
					responseType: 'blob',//必须加该属性,设置响应头的格式
				    data: this.$http.adornData({
				    //里面为我传的条件查询参数,可无视
				        'classId':this.exportExcelParams.classId,
				        'school':this.exportExcelParams.school,
				        'createTime':this.exportExcelParams.createTime,
						'checkBox':this.exportExcelParams.checkInfoOptions
				    })
				}).then(function(response) {
					if(response &&response.data!=null){
						//将后台获得的数据传给blob对象
						let blob = new Blob([response.data], {
						type: "application/vnd.ms-excel;charset=utf-8",
						}); 
						//创建dom元素
						let downloadElement = document.createElement('a');
						let href = window.URL.createObjectURL(blob); //创建下载的链接
						downloadElement.href = href;
						//设置文件名
						const date = new Date()
						downloadElement.download = '学生信息表'+date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate()+'.xls'; //下载后文件名
						document.body.appendChild(downloadElement);
						downloadElement.click(); //点击下载
						document.body.removeChild(downloadElement); //下载完成移除元素
						window.URL.revokeObjectURL(href); //释放掉blob对象
					}else{
						this.$message.error('导出失败')
					}

				})
            }
           

3.后端代码

DAO层:

@Mapper
public interface StudentDao extends BaseMapper<StudentEntity> {
    
    //根据查询条件导出excel文件
    List<ExportStudentExcel> searchStuListForExcel(HashMap map);
}

mapper:

<select id="searchStuListForExcel" resultType="cn.tentact.modules.student.form.ExportStudentExcel" parameterType="Hashmap">
        SELECT
        st.id,
        st.name,
        st.sex,
        st.birthday,
        st.politics,
        st.pid,
        st.school,
        st.major,
        st.education,
        st.g_time,
        st.g_status,
        st.home_address,
        st.current_address,
        st.tel,
        st.wechat,
        st.email,
        st.intent_place,
        st.intent_job,
        st.parent_name,
        st.parent_tel,
        stt.type,
        c.class_name,
        st.s_status,
        st.remark,
        st.user_id,
        st.create_time
        FROM
        tb_student st
        LEFT JOIN tb_class c
        ON st.class_id=c.id
        LEFT JOIN tb_student_type stt
        ON st.type_id=stt.id
        WHERE 1=1
        <if test="school!=null and sex!=''">
            AND st.school like CONCAT('%',#{school},'%')
        </if>
        <if test="classId!=null and classId!=''">
            AND st.class_id=#{classId}
        </if>
        <if test="createTime!=null">
            AND st.create_time >=#{createTime} AND st.create_time &lt;= date_add(#{createTime} ,interval 1 day)
        </if>
        ORDER BY st.id DESC
    </select>

实体类:

@Data
@TableName("tb_student")
public class ExportStudentExcel {
    /**
     * 学生id
     */
    @TableId
    private Long id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 性别
     */
    private String sex;
    /**
     * 出生日期
     */
    private String birthday;
    /**
     * 政治面貌
     */
    private String politics;
    /**
     * 身份证号
     */
    private String pid;
    /**
     * 学校
     */
    private String school;
    /**
     * 专业
     */
    private String major;
    /**
     * 毕业时间
     */
    @TableField("g_time")
    private String gTime;
    /**
     * 学历
     */
    private String education;
    /**
     * 毕业情况
     */
    @TableField("g_status")
    private String gStatus;
    /**
     * 家庭住址
     */
    private String homeAddress;
    /**
     * 当前住址
     */
    private String currentAddress;
    /**
     * 电话
     */
    private String tel;
    /**
     * 微信号
     */
    private String wechat;
    /**
     * 邮箱
     */
    private String email;
    /**
     * 意向就业地
     */
    private String intentPlace;
    /**
     * 意向岗位
     */
    private String intentJob;
    /**
     * 父母姓名
     */
    private String parentName;
    /**
     * 父母电话
     */
    private String parentTel;
    /**
     * 关联学生来源表ID
     */
    private String type;
    /**
     * 隶属班级ID
     */
    private String className;
    /**
     * 学习状态
     */
    @TableField("s_status")
    private String sStatus;
    /**
     * 备注
     */
    private String remark;

    /**
     * 用户id
     */
    private Long userId;
    /**
     * 填表日期
     */
    private Date createTime;

}

Export工具类(直接复制粘贴是可用的):

package cn.tentact.common.utils;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;

public class ExportExcelUtils {
    /**
     * 导出Excel
     *
     * @param excelName 要导出的excel名称
     * @param list      要导出的数据集合
     * @param fieldMap  中英文字段对应Map,即要导出的excel表头
     * @param response  使用response可以导出到浏览器
     * @param 
     */
    public static <T> void export(String excelName, List<T> list, LinkedHashMap<String, String> fieldMap, HttpServletResponse response) {

        try {
            response.setHeader("Content-Disposition", "attachment;filename="+excelName);
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        try {
            //创建一个WorkBook,对应一个Excel文件
            HSSFWorkbook wb = new HSSFWorkbook();
            //在Workbook中,创建一个sheet,对应Excel中的工作薄(sheet)
            HSSFSheet sheet = wb.createSheet(excelName);
            //创建单元格,并设置值表头 设置表头居中
            HSSFCellStyle style = wb.createCellStyle();
            //创建一个居中格式
            style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
            //设置边框线
            style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
            style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
            style.setBorderTop(XSSFCellStyle.BORDER_THIN);
            style.setBorderRight(XSSFCellStyle.BORDER_THIN);
            // 填充工作表
            fillSheet(sheet, list, fieldMap, style);
            //渲染第一行背景色为灰色,并设置列宽为10个字节
            for (int i = 0; i <= sheet.getLastRowNum(); i++) {
                HSSFRow row1 = sheet.getRow(i);
                for (int j = 0; j < row1.getLastCellNum(); j++) {
                    HSSFCell cell1 = row1.getCell(j);
                    row1.setHeightInPoints(24);
                    cell1.setCellStyle(style);
                    sheet.setColumnWidth((short)j,10*256);

                }

            }
            //渲染第一行的背景色为灰色
            HSSFRow row = sheet.getRow(0);
            HSSFCellStyle style1 = wb.createCellStyle();
            style1.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            style1.setFillPattern(CellStyle.SOLID_FOREGROUND);
            style1.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            style1.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            //设置边框线
            style1.setBorderBottom(XSSFCellStyle.BORDER_THIN);
            style1.setBorderLeft(XSSFCellStyle.BORDER_THIN);
            style1.setBorderTop(XSSFCellStyle.BORDER_THIN);
            style1.setBorderRight(XSSFCellStyle.BORDER_THIN);
            for (int i = 0; i < row.getLastCellNum() ; i++) {
                HSSFCell cell = row.getCell(i);
                cell.setCellStyle(style1);
            }

            //将文件输出
            OutputStream ouputStream = response.getOutputStream();
            wb.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public boolean chooseIntoField(List<String> list,String name){
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).equals("name")){
                return true;
            }
        }
        return false;
    }

    /**
     * 根据字段名获取字段对象
     *
     * @param fieldName 字段名
     * @param clazz     包含该字段的类
     * @return 字段
     */
    public static Field getFieldByName(String fieldName, Class<?> clazz) {
        // 拿到本类的所有字段
        Field[] selfFields = clazz.getDeclaredFields();

        // 如果本类中存在该字段,则返回
        for (Field field : selfFields) {
            //如果本类中存在该字段,则返回
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }

        // 否则,查看父类中是否存在此字段,如果有则返回
        Class<?> superClazz = clazz.getSuperclass();
        if (superClazz != null && superClazz != Object.class) {
            //递归
            return getFieldByName(fieldName, superClazz);
        }

        // 如果本类和父类都没有,则返回空
        return null;
    }

    /**
     * 根据字段名获取字段值
     *
     * @param fieldName 字段名
     * @param o         对象
     * @return 字段值
     * @throws Exception 异常
     */
    public static Object getFieldValueByName(String fieldName, Object o)
            throws Exception {

        Object value = null;
        //根据字段名得到字段对象
        Field field = getFieldByName(fieldName, o.getClass());

        //如果该字段存在,则取出该字段的值
        if (field != null) {
            field.setAccessible(true);//类中的成员变量为private,在类外边使用属性值,故必须进行此操作
            value = field.get(o);//获取当前对象中当前Field的value
        } else {
            throw new Exception(o.getClass().getSimpleName() + "类不存在字段名 "
                    + fieldName);
        }

        return value;
    }

    /**
     * 根据带路径或不带路径的属性名获取属性值,即接受简单属性名,
     * 如userName等,又接受带路径的属性名,如student.department.name等
     *
     * @param fieldNameSequence 带路径的属性名或简单属性名
     * @param o                 对象
     * @return 属性值
     * @throws Exception 异常
     */
    public static Object getFieldValueByNameSequence(String fieldNameSequence,
                                                     Object o) throws Exception {
        Object value = null;

        // 将fieldNameSequence进行拆分
        String[] attributes = fieldNameSequence.split("\\.");
        if (attributes.length == 1) {
            value = getFieldValueByName(fieldNameSequence, o);
        } else {
            // 根据数组中第一个连接属性名获取连接属性对象,如student.department.name
            Object fieldObj = getFieldValueByName(attributes[0], o);
            //截取除第一个属性名之后的路径
            String subFieldNameSequence = fieldNameSequence
                    .substring(fieldNameSequence.indexOf(".") + 1);
            //递归得到最终的属性对象的值
            value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
        }
        return value;

    }

    /**
     * 向工作表中填充数据
     *
     * @param sheet    excel的工作表名称
     * @param list     数据源
     * @param fieldMap 中英文字段对应关系的Map
     * @param style    表格中的格式
     * @throws Exception 异常
     */
    public static <T> void fillSheet(HSSFSheet sheet, List<T> list,
                                     LinkedHashMap<String, String> fieldMap, HSSFCellStyle style) throws Exception {
        // 定义存放英文字段名和中文字段名的数组
        String[] enFields = new String[fieldMap.size()];
        String[] cnFields = new String[fieldMap.size()];

        // 填充数组
        int count = 0;
        for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
            enFields[count] = entry.getKey();
            cnFields[count] = entry.getValue();
            count++;
        }

        //在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
        HSSFRow row = sheet.createRow((int) 0);

        // 填充表头
        for (int i = 0; i < cnFields.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(cnFields[i]);
            cell.setCellStyle(style);
            sheet.autoSizeColumn(i);
        }

        // 填充内容
        for (int index = 0; index < list.size(); index++) {
            row = sheet.createRow(index + 1);
            // 获取单个对象
            T item = list.get(index);
            for (int i = 0; i < enFields.length; i++) {
                Object objValue = getFieldValueByNameSequence(enFields[i], item);
                String fieldValue = objValue == null ? "" : objValue.toString();

                row.createCell(i).setCellValue(fieldValue);
            }
        }
    }

}

serviceImpl层:

@Override
    @Transactional
    public List<ExportStudentExcel> searchStuListForExcel(HashMap map) {
        List<ExportStudentExcel> userList = studentDao.searchStuListForExcel(map);
        
        return userList;
    }

controller层(其中的for循环为判断条件,可无视,直接使用fieldMap.put(“与实体类对应的字段名”,“显示在excel中的表头字段”)即可):

/**
     * 导出excel文件
     */
    @RequestMapping(value = "/export")
    public List<ExportStudentExcel> exportExcel(@RequestBody Map<String,Object> params, HttpServletResponse response){
        List<ExportStudentExcel> userList = studentService.searchStuListForExcel((HashMap) params);
        List<HashMap> checkBox = (List<HashMap>) params.get("checkBox");
        List<String> optionCn=new ArrayList<>();
        List<String> optionEn=new ArrayList<>();
        for(HashMap option :checkBox){
            optionCn.add(option.get("label").toString());
            optionEn.add(option.get("value").toString());
        }
        LinkedHashMap<String,String> fieldMap = new LinkedHashMap<String,String>();
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("id")){
                fieldMap.put("id","序号");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("name")){
                fieldMap.put("name","姓名");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("sex")){
                fieldMap.put("sex","性别");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("birthday")){
                fieldMap.put("birthday","出生日期");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("politics")){
                fieldMap.put("politics","政治面貌");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("pid")){
                fieldMap.put("pid","身份证");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("school")){
                fieldMap.put("school","学校");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("major")){
                fieldMap.put("major","专业");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("time")){
                fieldMap.put("gTime","毕业时间");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("education")){
                fieldMap.put("education","学历");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("gStatus")){
                fieldMap.put("gStatus","毕业情况");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("homeAddress")){
                fieldMap.put("homeAddress","家庭住址");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("currentAddress")){
                fieldMap.put("currentAddress","当前住址");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("tel")){
                fieldMap.put("tel","电话");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("wechat")){
                fieldMap.put("wechat","微信号");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("email")){
                fieldMap.put("email","邮箱");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("intentPlace")){
                fieldMap.put("intentPlace","意向城市");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("intentJob")){
                fieldMap.put("intentJob","意向工作");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("parentName")){
                fieldMap.put("parentName","父母姓名");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("parentTel")){
                fieldMap.put("parentTel","父母电话");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("type")){
                fieldMap.put("type","学生来源");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("className")){
                fieldMap.put("className","班级");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("sStatus")){
                fieldMap.put("sStatus","学习状态");

                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("remark")){
                fieldMap.put("remark","备注");
                break;
            }
        }
        for (int i = 0; i < optionEn.size(); i++) {
            if (optionEn.get(i).equals("createTime")){
                fieldMap.put("createTime","入学时间");
                break;
            }
        }
        String title = "学生信息表";
        ExportExcelUtils.export(title,userList,fieldMap,response);
        return userList;
    }

4.运行结果

基于springBoot、vue导出Excel文件_第1张图片
基于springBoot、vue导出Excel文件_第2张图片基于springBoot、vue导出Excel文件_第3张图片


若有不对的地方烦请指出,如果对你有帮助的话不忘点个赞!

你可能感兴趣的:(springboot,vue,spring,boot,vue,poi)