SpringBoot + Ant Design Vue实现数据导出功能

简介: 需求:1,以xlsx格式导出所选表格中的内容,2, 要求进行分级, 3,设置表头颜色。

一、需求

  • 以xlsx格式导出所选表格中的内容
  • 要求进行分级
  • 设置表头颜色。

二、前端代码实现

2.1 显示实现

首先我们需要添加一个用于到导出的按钮上去,像这样的:

<a-button @click="exportBatchlistVerify">批量导出</a-button>

至于它放哪里,是什么样式可以根据自己的需求决定。

2.2 代码逻辑

按钮有了,下来我们开始实现这个按钮的功能。

  1. 导出数据确定。

表格设置: 表头添加以下代码

<s-table    
    :row-key="(record) => record.id"
    :row-selection="options.rowSelection"
    >

Vue代码 :获取选中的目标ID数组

   import listApi from '@/api/listApi'
    let selectedRowKeys = ref([])
    const options = {
        alert: {
            show: false,
            clear: () => {
                selectedRowKeys = ref([])
            }
        },
        rowSelection: {
            onChange: (selectedRowKey, selectedRows) => {
                selectedRowKeys.value = selectedRowKey
            },
            //这里是设置复选框的宽度,可以删掉
            columnWidth : 6
        }
    }

按钮功能实现:

    const exportBatchlistVerify = () => {
        if (selectedRowKeys.value.length < 1) {
            message.warning('请输入查询条件或勾选要导出的信息')
        }
        if (selectedRowKeys.value.length > 0) {
            const params = {
                checklistIds: selectedRowKeys.value
                    .map((m) => {
                        return m
                    })
                    .join()
            }
            exportBatchChecklist(params)
            return
        }
        exportBatchList(params)

    }
    const exportBatchList= (params) => {
        listApi.listExport(params).then((res) => {
            downloadUtil.resultDownload(res)
            table.value.clearSelected()
        })
    }

listApi: 导入部分和 baseRequest 请参考 Vue封装axios实现

import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/list/` + url, ...arg)
    listExport(data) {
        return request('export', data, 'get', {
            responseType: 'blob'
        })
    },

三、后端代码实现

3.1 实体类

我们首先建一个简单的实体,展示将要导出的数据内容:

import com.baomidou.mybatisplus.annotation.TableName;
import com.fhs.core.trans.vo.TransPojo;
import lombok.Data;

/**
 * Auth lhd
 * Date 2023/6/21 9:42
 * Annotate 导出功能测试类
 */
@Data
@TableName("userTest")
public class UserTest implements TransPojo {

    private String id;
    private String name;
    private String tel;
    private String password;
    private String address;
}

3.2 接收参数和打印模板

有了实体类后,我们将开始进行具体的逻辑编写,但在这之前我们需要定义接收前端传参的类,和定义我们的打印模板。

接收参数:

import lombok.Data;

/**
 * Auth lhd
 * Date 2023/6/21 9:46
 * Annotate
 */
@Data
public class UserTestExportParam {
    private String listIds;
}

这部分很简单,我们只需要即将打印的内容ID即可。

打印模板:

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.HeadStyle;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import lombok.Data;

/**
 * Auth lhd
 * Date 2023/6/21 10:10
 * Annotate
 */
@Data
public class UserTestResult {

    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    @ExcelProperty({"人物名称"})
    private String name;

    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 29)
    @ExcelProperty({"基本信息","联系方式 "})
    private String tel;

    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 31)
    @ExcelProperty({"基本信息","地址 "})
    private String address;

    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 26)
    @ExcelProperty({"基本信息","不能外露","账号密码 "})
    private String password;

}

打印模板定义了我们们即将打印的表格的表头结构和列名、表头颜色。

备注:通过修改打印模板类的注解,可以实现自定义的表头和表头颜色

3.3 正式的逻辑

映射接口和XML:

  • 接口 UserTestMapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.modular.userTest.entity.UserTest;

/**
 * Auth lhd
 * Date 2023/6/21 10:02
 * Annotate
 */
public interface UserTestMapper extends BaseMapper<UserTest> {
}
  • XML UserTestMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 

</ma

核心逻辑接口和实现:

  • 逻辑接口 UserTestService
import com.baomidou.mybatisplus.extension.service.IService;
import com.modular.userTest.entity.UserTest;
import com.modular.userTest.param.UserTestExportParam;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Auth lhd
 * Date 2023/6/21 9:44
 * Annotate
 */
public interface UserTestService extends IService<UserTest> {
    void exportUserTestList(UserTestExportParam listExportParam, HttpServletResponse response) throws IOException;
}
  • 接口实现 UserTestServiceImpl
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fhs.trans.service.impl.TransService;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Service;
import com.modular.userTest.entity.UserTest;
import com.modular.userTest.mapper.UserTestMapper;
import com.modular.userTest.param.UserTestExportParam;
import com.modular.userTest.result.UserTestResult;
import com.modular.userTest.service.UserTestService;
import com.common.excel.CommonExcelCustomMergeStrategy;
import com.common.exception.CommonException;
import com.common.util.CommonDownloadUtil;
import com.common.util.CommonResponseUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Auth lhd
 * Date 2023/6/21 10:01
 * Annotate
 */
@Service
public class UserTestServiceImpl extends ServiceImpl<UserTestMapper, UserTest> implements UserTestService {

    @Resource
    private TransService transService;
    
    @Override
    public void exportUserTestList(UserTestExportParam listExportParam, HttpServletResponse response) throws IOException {
            File tempFile = null;
            try {
                QueryWrapper<UserTest> queryWrapper = new QueryWrapper<>();
                if(ObjectUtil.isNotEmpty(listExportParam.getListIds())) {
                    queryWrapper.lambda().in(UserTest::getId, StrUtil.split(listExportParam.getListIds(), StrUtil.COMMA));
                }
                String fileName = "人物信息表.xlsx";
                List<UserTest> userlists = this.list(queryWrapper);
                if(ObjectUtil.isEmpty(userlists)) {
                    throw new CommonException("无数据可导出");
                }
                transService.transBatch(userlists);
                List<UserTestResult> listResults = userlists.stream()
                        .map(userlist -> {
                            UserTestResult listExportResult = new UserTestResult();
                            BeanUtil.copyProperties(userlist, listExportResult);
                            listExportResult.setName(ObjectUtil.isNotEmpty(listExportResult.getName())?
                                    listExportResult.getName():"无检查地址");
                            return listExportResult;
                        }).collect(Collectors.toList());

                // 创建临时文件
                tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);

                // 头的策略
                WriteCellStyle headWriteCellStyle = new WriteCellStyle();
                WriteFont headWriteFont = new WriteFont();
                headWriteFont.setFontHeightInPoints((short) 14);
                headWriteCellStyle.setWriteFont(headWriteFont);

                // 水平垂直居中
                headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
                headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

                // 内容的策略
                WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
                // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
                contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
                // 内容背景白色
                contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
                WriteFont contentWriteFont = new WriteFont();

                // 内容字体大小
                contentWriteFont.setFontHeightInPoints((short) 12);
                contentWriteCellStyle.setWriteFont(contentWriteFont);

                //设置边框样式,细实线
                contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
                contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
                contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
                contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

                // 水平垂直居中
                contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
                contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

                // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
                HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle,
                        contentWriteCellStyle);

                // 写excel
                EasyExcel.write(tempFile.getPath(), UserTestResult.class)
                        // 自定义样式
                        .registerWriteHandler(horizontalCellStyleStrategy)
                        // 自动列宽
                        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                        // 机构分组合并单元格
                        .registerWriteHandler(new CommonExcelCustomMergeStrategy(listResults.stream().map(UserTestResult::getName)
                                .collect(Collectors.toList()), 0))
                        // 设置第一行字体
                        .registerWriteHandler(new CellWriteHandler() {
                            @Override
                            public void afterCellDispose(CellWriteHandlerContext context) {
                                WriteCellData<?> cellData = context.getFirstCellData();
                                WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
                                Integer rowIndex = context.getRowIndex();
                                if(rowIndex == 0) {
                                    WriteFont headWriteFont = new WriteFont();
                                    headWriteFont.setFontName("宋体");
                                    headWriteFont.setBold(true);
                                    headWriteFont.setFontHeightInPoints((short) 16);
                                    writeCellStyle.setWriteFont(headWriteFont);
                                }
                            }
                        })
                        // 设置表头行高
                        .registerWriteHandler(new AbstractRowHeightStyleStrategy() {
                            @Override
                            protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
                                if(relativeRowIndex == 0) {
                                    // 表头第一行
                                    row.setHeightInPoints(34);
                                } else {
                                    // 表头其他行
                                    row.setHeightInPoints(30);
                                }
                            }
                            @Override
                            protected void setContentColumnHeight(Row row, int relativeRowIndex) {
                                // 内容行
                                row.setHeightInPoints(20);
                            }
                        })
                        .sheet("人物信息表信息")
                        .doWrite(listResults);
                CommonDownloadUtil.download(tempFile, response);
            } catch (Exception e) {
                log.error(">>> 人物信息表导出异常:", e);
                CommonResponseUtil.renderError(response, "导出失败");
            } finally {
                FileUtil.del(tempFile);
            }
        }
}
这里只展示具体逻辑,common开头的公共类和工具类感兴趣的伙伴可以私信我获取~

3.4 Contorller

最后写一个简单的controller类即可:

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.modular.userTest.param.UserTestExportParam;
import com.modular.userTest.service.UserTestService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Auth lhd
 * Date 2023/6/21 10:17
 * Annotate
 */
@RestController
public class UserTestController {

    @Resource
    private UserTestService userTestService;

    @GetMapping(value="/list/export",produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void exportUser(UserTestExportParam listExportParam, HttpServletResponse response) throws IOException {
        userTestService.exportUserTestList(listExportParam, response);
    }
}

我们看看打印效果:
ebf3b41681fb4067b9149afdc560dcd1.png

目录
相关文章
|
23天前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
196 2
|
2月前
|
前端开发 安全 Java
基于springboot+vue开发的会议预约管理系统
一个完整的会议预约管理系统,包含前端用户界面、管理后台和后端API服务。 ### 后端 - **框架**: Spring Boot 2.7.18 - **数据库**: MySQL 5.6+ - **ORM**: MyBatis Plus 3.5.3.1 - **安全**: Spring Security + JWT - **Java版本**: Java 11 ### 前端 - **框架**: Vue 3.3.4 - **UI组件**: Element Plus 2.3.8 - **构建工具**: Vite 4.4.5 - **状态管理**: Pinia 2.1.6 - **HTTP客户端
247 4
基于springboot+vue开发的会议预约管理系统
|
6月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
543 1
|
7月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
467 7
|
3月前
|
前端开发 JavaScript Java
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
本系统基于SpringBoot与Vue3开发,实现校园食堂评价功能。前台支持用户注册登录、食堂浏览、菜品查看及评价发布;后台提供食堂、菜品与评价管理模块,支持权限控制与数据维护。技术栈涵盖SpringBoot、MyBatisPlus、Vue3、ElementUI等,适配响应式布局,提供完整源码与数据库脚本,可直接运行部署。
167 0
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
|
4月前
|
缓存 前端开发 Java
SpringBoot 实现动态菜单功能完整指南
本文介绍了一个动态菜单系统的实现方案,涵盖数据库设计、SpringBoot后端实现、Vue前端展示及权限控制等内容,适用于中后台系统的权限管理。
316 1
|
5月前
|
监控 数据可视化 JavaScript
springboot + vue的MES系统生产计划管理源码
MES系统(制造执行系统)的生产计划管理功能是其核心模块之一,涵盖生产计划制定与优化、调度排程、进度监控反馈、资源管理调配及可视化报告五大方面。系统基于SpringBoot + Vue-Element-Plus-Admin技术栈开发,支持多端应用(App、小程序、H5、后台)。通过实时数据采集与分析,MES助力企业优化生产流程,适用于现代化智能制造场景。
224 1
|
6月前
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
539 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
6月前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
下一篇
开通oss服务