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

目录
相关文章
|
4天前
|
前端开发 JavaScript Java
SpringBoot+Vue+token实现(表单+图片)上传、图片地址保存到数据库。上传图片保存位置自己定义、图片可以在前端回显(一))
这篇文章详细介绍了在SpringBoot+Vue项目中实现表单和图片上传的完整流程,包括前端上传、后端接口处理、数据库保存图片路径,以及前端图片回显的方法,同时探讨了图片资源映射、token验证、过滤器配置等相关问题。
|
4天前
|
前端开发 数据库
SpringBoot+Vue+token实现(表单+图片)上传、图片地址保存到数据库。上传图片保存位置到项目中的静态资源下、图片可以在前端回显(二))
这篇文章是关于如何在SpringBoot+Vue+token的环境下实现表单和图片上传的优化篇,主要改进是将图片保存位置从磁盘指定位置改为项目中的静态资源目录,使得图片资源可以跨环境访问,并在前端正确回显。
|
3天前
|
前端开发 数据库
SpringBoot+Vue实现商品不能重复加入购物车、购物车中展示商品的信息、删除商品重点提示等操作。如何点击图片实现图片放大
这篇文章介绍了如何在SpringBoot+Vue框架下实现购物车功能,包括防止商品重复加入、展示商品信息、删除商品时的提示,以及点击图片放大的前端实现。
SpringBoot+Vue实现商品不能重复加入购物车、购物车中展示商品的信息、删除商品重点提示等操作。如何点击图片实现图片放大
|
4天前
|
JSON JavaScript 前端开发
基于SpringBoot + Vue实现单个文件上传(带上Token和其它表单信息)的前后端完整过程
本文介绍了在SpringBoot + Vue项目中实现单个文件上传的同时携带Token和其它表单信息的前后端完整流程,包括后端SpringBoot的文件上传处理和前端Vue使用FormData进行表单数据和文件的上传。
16 0
基于SpringBoot + Vue实现单个文件上传(带上Token和其它表单信息)的前后端完整过程
|
3天前
|
JavaScript Java 数据库
Vue+SpringBoot+ElementUi+mybatis-plus 实现用户信息的修改及模拟充值
这篇文章展示了如何使用Vue结合SpringBoot、ElementUI和mybatis-plus实现用户信息的修改以及模拟充值的功能。文章首先介绍了模拟充值的过程,包括充值前后的账户余额和数据库信息的截图。然后,文章展示了用户信息修改前后的界面和数据库信息。核心代码部分演示了如何使用mybatis-plus轻松实现用户信息的修改操作,同时指出了异常处理和代码组织的最佳实践。
|
4天前
|
存储 前端开发 JavaScript
2022年超详细的SpringBoot+Vue+Jwt实现token的认证(重点部分讲解和完整的代码设计)
这篇文章详细介绍了使用SpringBoot、Vue.js和Jwt实现token认证的完整流程和代码设计,包括后端的jwt依赖引入、token生成和认证过滤器编写,以及前端的路由守卫、Vuex状态管理和token的存储与使用,确保用户登录状态的维护和验证。
|
4天前
|
存储 NoSQL Java
基于SpringBoot+Redis实现查找附近用户的功能
使用Redis的GEO命令结合SpringBoot实现查找附近用户的功能,通过`GEOADD`命令添加地理位置信息和`GEORADIUS`命令查询附近用户。
9 0
|
4天前
|
存储 NoSQL Redis
基于SpringBoot+Redis实现点赞/排行榜功能,可同理实现收藏/关注功能,可拓展实现共同好友/共同关注/关注推送功能
在SpringBoot项目中使用Redis的Set和ZSet集合实现点赞和排行榜功能,并通过示例代码展示了如何使用`stringRedisTemplate`操作Redis来完成这些功能。
26 0
|
4天前
|
druid Java 数据库连接
SpringBoot项目整合MybatisPlus持久层框架+Druid数据库连接池,以及实现增删改查功能
SpringBoot项目整合MybatisPlus和Druid数据库连接池,实现基本的增删改查功能。
18 0
|
前端开发 JavaScript Java
SpringBoot实现国际化i18n功能
SpringBoot实现国际化i18n功能
1034 0
SpringBoot实现国际化i18n功能