Excel 导入和导出--前后端整合

news2024/11/14 3:01:12

文章目录

      • Excel基础
      • Easy Excel
        • 导出会员数据
        • 导入会员数据
    • 前端代码:
      • 代码解析
      • 总结
      • 组件简介
      • 详细解释
      • 总结

用来操作excel文件的。
银行网银系统导出交易明细数据各种业务系统导出excel报表数据批量导入业务数据

Excel基础

  • **工作簿 workbook
    **就是一个文件
  • 工作表 sheet
    属于工作簿
  • 行 row
    属于工作表
  • 单元格 cell属于行,如C2,表示第二行第三列

Easy Excel

官网地址: 对于操作excel十分的方便。
关于Easyexcel | Easy Excel 官网 (alibaba.com)

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

image.png
根据excel表格编写导出的实体类。
在实体类的每一个属性上面添加注解@Excel, name是excel的列名,orderNum表示在第几列,下标从0开始。
width表示列的宽度,有些列数据比较多长度会比较大。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SpMemberVO {

    @Excel(name = "用户名", orderNum = "0", width = 20)
    @ApiModelProperty(value = "用户名")
    private String username;

    @Excel(name = "邮箱", orderNum = "1", width = 30)
    @ApiModelProperty(value = "邮箱")
    private String email;

    @Excel(name = "性别", orderNum = "2", width = 15)
    @ApiModelProperty(value = "性别")
    private String gender;
    @Excel(name = "QQ号", orderNum = "3", width = 10)
    @ApiModelProperty(value = "qq")
    private String qq;
    @Excel(name = "手机", orderNum = "4", width = 25)
    @ApiModelProperty(value = "手机")
    private String phone;
    @Excel(name = "学历", orderNum = "5", width = 10)
    @ApiModelProperty(value = "学历")
    private String education;
    @Excel(name = "爱好", orderNum = "6", width = 10)
    @ApiModelProperty(value = "爱好")
    private String hobby;
    @Excel(name = "简介", orderNum = "7", width = 30)
    @ApiModelProperty(value = "简介")
    private String introduce;

}

导出会员数据

controller层代码

@ApiOperation("导出会员信息")
@GetMapping("/export")
public void export(@RequestParam(defaultValue = "1")Integer pageNum, @RequestParam(defaultValue = "5") Integer pageSize, Member member, HttpServletResponse resp) throws IOException {
    //导出所有的选学生新信息
    Workbook workbook = memberService.export(pageNum, pageSize, member);
    // 设置响应内容
    resp.setContentType("application/vnd.ms-excel");  
    //设置响应头                                                           //如果需要中文 就要这样编写
    resp.setHeader("Content-Disposition", "attachment;filename=" + new String("会员信息表.xlsx".getBytes("utf-8"), "iso8859-1"));
                     //将workbook写入到响应流中去
    workbook.write(resp.getOutputStream());
    
}
这个方法虽然没有显式的返回值,但是它通过 HttpServletResponse 对象将数据直接写入了响应流
,这使得它能够将内容发送到前端。

service层代码:

@Override
public Workbook export(Integer pageNum, Integer pageSize, Member member) {
    PageHelper.startPage(pageNum, pageSize); //开启分页
    List<SpMemberVO> memberList = memberMapper.selectByPage(member); //分页查找
     //设置导出数据 第一个参数 标题 第二个参数 页表标题
    ExportParams exportParams = new ExportParams("会员信息", "会员信息表");
                  //调用工具类生成book 返回book
    Workbook book = ExcelExportUtil.exportExcel(exportParams, SpMemberVO.class, memberList);
    return book;
}

导入会员数据
@ApiOperation("导入会员信息")
@PostMapping("/import")         
public Result importExcel(@RequestParam("file") MultipartFile file) throws IOException {
    System.out.println(file.getSize());
    memberService.importFile(file.getInputStream());
    return Result.success();
}

@RequestParam("file") MultipartFile file 是在 Spring MVC 中用来处理文件上传的参数定义。它的作用是将 HTTP 请求中上传的文件绑定到控制器方法的参数 file 上。下面是详细解释:

MultipartFileSpring 提供的一个接口,用于封装上传的文件。它包含了一些常用的方法,例如 getOriginalFilename()(获取文件的原始名称)、getBytes()(获取文件的字节内容)、getInputStream()(获取文件的输入流)等。
通过将 MultipartFile 作为方法参数,Spring MVC 可以自动处理多部分表单数据,将上传的文件封装为 MultipartFile 对象,并传递给方法供其使用。

对于传过来的file可以使用下面的方法
getOriginalFilename(): 返回上传文件的原始文件名。
getBytes(): 以字节数组的形式返回文件内容。
getInputStream(): 获取文件内容的输入流,用于更复杂的文件处理操作。
transferTo(File dest): 将上传的文件直接保存到指定的文件路径。

serive层代码
image.png

@SneakyThrows
@Override
public void importFile(InputStream inputStream){
System.out.println(inputStream);
ImportParams params = new ImportParams();
params.setTitleRows(1);  //导入的数据 设置标题
params.setHeadRows(1);    //设置最上面一栏                          //这边读取的是vo中的配置
List<SpMemberVO> list = ExcelImportUtil.importExcel(inputStream, SpMemberVO.class, params);
//导入的数据和实际的数据有差别的,通过stream流进行转换
List<Member> collect = list.stream().map(item -> {
    Member member = new Member();
    BeanUtils.copyProperties(item, member);
    member.setPassword(PwdUtil.encrypt(MemberConstant.DEFAULT_PASSWORD));
    member.setCreateTime(new Date());
    member.setUpdateTime(new Date());
    member.setIsDeleted(MemberConstant.NO_DELETED);
    return member;
}).collect(Collectors.toList());
//进行批量的插入
memberMapper.insertBatch(collect);
}

批量插入的mapper.xml代码

<insert id="insertBatch" parameterType="Member">
  INSERT INTO sp_member (username, password, email, gender, qq, phone, education, hobby, introduce, create_time, update_time, is_deleted)
  VALUES
  <!-- 通过foreach标签  -->
  <foreach collection="list" item="item" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.gender}, #{item.qq}, #{item.phone}, #{item.education}, #{item.hobby}, #{item.introduce}, #{item.createTime}, #{item.updateTime}, #{item.isDeleted})
  </foreach>

</insert>

验证:
image.pngimage.png
image.png

前端代码:

// 导出
  async exportMember(type) {
    console.log(type)
    let tip = type ? '是否确定导出全部的会员信息?' : '是否确定导出当前页的会员信息?'
    this.$confirm(tip, '提示', {
      confirmButtonText: '导出',
      cancelButtonText: '取消',
      type: 'warning',
    })
      .then(async () => {
        // 要传递的参数
        let params = { ...this.queryInfo }
        // 是否是导出全部匹配数据
        if (type) {
          params.pageNum = 1
          params.pageSize = this.total
        }
        // 导出
        const res = await this.$http.get(`members/export`, {
          params,
          responseType: 'blob',
        })
        const file = new Blob([res.data], {
          type: 'application/vnd.ms-excel',
        })
        const url = URL.createObjectURL(file)
        const a = document.createElement('a')
        a.href = url
        a.download = 'member.xlsx'
        a.click()
        // 释放临时的a
        URL.revokeObjectURL(url)
      })
      .catch(() => {
        this.$message({
          type: 'info',
          message: '已取消导出',
        })
      })
  }, 

这段代码是一个 Vue.js 组件的方法,exportMember(type),用于导出会员信息。它根据用户选择导出全部会员数据或仅导出当前页的数据。下面是对代码的详细解释:

代码解析

  1. 方法签名与参数:
    • async exportMember(type):这是一个异步方法,type 参数用于指示导出类型。如果 typetrue,则导出全部会员信息;如果为 false,则仅导出当前页的会员信息。
  2. 确认导出提示:
let tip = type ? '是否确定导出全部的会员信息?' : '是否确定导出当前页的会员信息?'
this.$confirm(tip, '提示', {
  confirmButtonText: '导出',
  cancelButtonText: '取消',
  type: 'warning',
})
  • 根据 type 的值,设置不同的提示信息,让用户确认他们要导出的数据范围。
  • 使用 Vue.js 的 this.$confirm 方法显示一个确认对话框,用户可以选择继续导出或取消。
  1. 确认后的处理逻辑:
    • then(async () => {...}):如果用户点击了“导出”,执行这个块中的逻辑。
  2. 设置请求参数:
let params = { ...this.queryInfo }
if (type) {
  params.pageNum = 1
  params.pageSize = this.total
}
  • params 是请求参数对象,通常包含查询条件和分页信息。
  • 如果 typetrue(导出全部),则将 pageNum 设置为 1,将 pageSize 设置为总记录数,意味着请求所有数据。
  1. 发起导出请求:
const res = await this.$http.get(`members/export`, {
  params,
  responseType: 'blob',//指定格式
})
  • 使用 this.$http.get 发起 GET 请求,传递查询参数 params
  • responseType: 'blob' 指定返回的数据类型为 blob,即二进制文件数据。
  1. 处理文件下载:
const file = new Blob([res.data], {
  type: 'application/vnd.ms-excel',
})
const url = URL.createObjectURL(file)
const a = document.createElement('a')
a.href = url
a.download = 'member.xlsx'
a.click()
URL.revokeObjectURL(url)
  • 使用 Blob 将返回的二进制数据创建为一个文件对象。
  • URL.createObjectURL(file) 创建一个指向 Blob 对象的临时 URL。
  • 创建一个隐藏的 <a> 标签,通过设置 href 属性为刚创建的 URL,并设置 download 属性为 member.xlsx,触发文件下载。
  • 下载完成后,通过 URL.revokeObjectURL(url) 释放临时 URL 以节省内存。
  1. 取消导出:
.catch(() => {
  this.$message({
    type: 'info',
    message: '已取消导出',
  })
})
  • 如果用户点击“取消”,或者导出操作失败,则执行这个块,提示用户导出已取消。

总结

这段代码实现了一个文件导出功能,通过用户的选择导出全部会员数据或当前页的数据。它使用了 Vue.js 的 this.$confirm 方法来提示用户确认操作,并通过 axios 发起 HTTP 请求以获取文件数据,再使用 Blob 和动态创建的 <a> 标签完成文件下载。这种方法常用于处理从后端导出 Excel 文件或其他二进制文件的场景。

导入

<!-- 导入 -->
<el-upload :action="importUrl" :headers="importHearders" :show-file-list="false" accept=".xls, .xlsx"
  :before-upload="beforeUpload" :on-success="importSuccess" style="display: inline-block; margin-left: 10px">
  <el-button type="info" icon="el-icon-upload">导入</el-button>
</el-upload>
        

这段代码是一个使用 Element UI 构建的文件上传组件,主要用于上传 Excel 文件(.xls.xlsx 格式)。以下是对各个部分的详细解释:

组件简介

<el-upload> 是 Element UI 提供的上传组件,能够处理文件的上传,并提供丰富的配置选项来定制上传行为。

详细解释

  1. :action="importUrl":
    • :actionel-upload 组件的一个属性,用于指定文件上传的 URL。这里通过 importUrl 绑定了一个动态的上传接口地址。
    • 在实际开发中,importUrl 通常是一个包含服务器上传接口的变量,用户选择文件后,文件将被上传到这个 URL 对应的服务器端处理接口。
  2. :headers="importHearders":
    • :headers 属性用于设置上传请求的 HTTP 头信息。
    • 这里 importHearders 绑定了一个包含头信息的对象变量,可以用于设置如 Authorization 令牌等,用于身份验证或其他用途。
importHearders: {  //拿到存储在本地的token信息
        Authorization: JSON.parse(localStorage.getItem('userInfo')).token,
      },
  1. :show-file-list="false":
    • :show-file-list 控制是否显示上传文件的列表。
    • 设为 false 表示不显示文件上传列表,这样用户不会看到已经上传的文件名等信息。
  2. accept=".xls, .xlsx":
    • accept 属性用于限制用户可以选择的文件类型。
    • 这里设置为 ".xls, .xlsx",表示只能选择 Excel 文件,这样确保用户上传的文件格式是符合预期的。
  3. :before-upload="beforeUpload":
beforeUpload(file) {
  // 这里可以进行文件验证,例如大小、类型等
  return true; // 或者返回一个 Promise
}
  • :before-upload 是一个钩子函数,绑定到 beforeUpload 方法。
  • 这个函数会在文件上传之前执行,通常用于验证文件类型、大小等。通过返回 false 可以阻止文件上传,返回 Promise 则可以控制异步验证逻辑。
  1. :on-success="importSuccess":
importSuccess(response, file, fileList) {
  // 处理上传成功后的逻辑
}
  • :on-success 是一个钩子函数,绑定到 importSuccess 方法。
  • 当文件上传成功后,这个方法会被调用,通常用于处理成功上传后的逻辑,例如通知用户上传成功或处理返回的数据。
  1. <el-button>:
    • 这个按钮是上传组件的触发器,点击按钮将会打开文件选择框。
    • type="info" 设置按钮的样式为 info 颜色,icon="el-icon-upload" 设置按钮图标为上传图标,按钮的文本是“导入”。
  2. style="display: inline-block; margin-left: 10px":
    • 内联样式,用于调整按钮的布局和外观。display: inline-block 使按钮与其他元素在同一行显示,margin-left: 10px 给按钮左侧增加了 10 像素的间距。

总结

这段代码定义了一个用于导入 Excel 文件的上传按钮,使用了 Element UI 的 el-upload 组件。用户点击按钮后,可以选择一个 .xls.xlsx 文件上传。上传过程可以通过 beforeUpload 方法进行前置检查,通过 importSuccess 方法处理上传成功后的响应。所有配置(如上传地址、请求头等)都可以通过绑定的 Vue.js 数据动态控制。

// 导入成功的回调
importSuccess(res) {
  // console.log(res)
  if (res.status != 200) {
    return this.$message.error('导入失败,请确认会员名唯一')
  }
  this.$message.success('导入成功')
  this.getMemberList()
},
// 导入前的钩子
beforeUpload(file) {
  const fileSuffix = file.name.substring(file.name.lastIndexOf('.') + 1)

  const whiteList = ['xls', 'xlsx']


  //校验导出的格式
  if (whiteList.indexOf(fileSuffix) === -1) {
    this.$message.error('上传文件只能是 xls、xlsx格式')
    return false
  }


  //校验文件的大小  不能大于10MB
  const isLt10M = file.size / 1024 / 1024 < 10

  if (!isLt10M) {
    this.$message.error('上传文件大小不能超过 10MB')
    return false
  }
},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2081437.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

element的el-date-picker组件实现只显示年月日时分,不显示秒

需求&#xff1a;使用element的el-date-picker组件&#xff0c;只显示时分&#xff0c;不消失秒 效果&#xff1a; 解决方法&#xff1a; <el-date-pickerv-model"ruleForm.startTime"type"datetime"placeholder"开始时间"format"yyyy-…

萌化人心!AI宠物视频,1条视频涨粉1W+,千万级播放量(附教程)

大家晚上好&#xff0c;今天给大家分享一个创意玩法—用AI 生成超萌动物&#xff0c;打造宠物互动虚拟场景。 这种视频内容非常受欢迎&#xff0c;吸引了大量观众。某音上有位博主通过这种创新方式迅速构建了AI宠物系列账号&#xff0c;短时间内便积累了大量粉丝。 比如这条视…

【前端】控制台彩蛋彩色键盘

效果如图 代码如下 const colors {reset: "\x1b[0m",red: "\x1b[31m",green: "\x1b[32m",yellow: "\x1b[33m",blue: "\x1b[34m",magenta: "\x1b[35m",cyan: "\x1b[36m",white: "\x1b[37m"…

神经网络算法 - 一文搞懂 Softmax 函数

本文将从Softmax的本质、Softmax的原理、Softmax的应用三个方面&#xff0c;带您一文搞懂 Softmax 函数。 Softmax激活函数 Softmax一般用来作为神经网络的最后一层&#xff0c;用于多分类问题的输出。其本质是一种激活函数&#xff0c;将一个数值向量归一化为一个概率分布向量…

《机器学习》 SVM支持向量机 推导、参数解析、可视化实现

目录 一、SVM支持向量机 1、什么是SVM 例如&#xff1a; 2、SVM的主要特点是&#xff1a; 二、SVM方程 1、超平面方程 2、标签问题 3、决策函数&#xff1a; 符号函数&#xff1a; 整合&#xff1a; 4、距离问题 1&#xff09;点到直线距离 2&#xff09;点到平面…

Python使用Tesseract OCR识别文字

Tesseract-OCR是一款由Google维护的开源光学字符识别&#xff08;OCR&#xff09;引擎&#xff0c;它能够从图像中识别出文本&#xff0c;并将其转换为可编辑的文本格式。以下是关于Tesseract-OCR的详细介绍&#xff1a; 一、背景与发展 起源&#xff1a;Tesseract最初是惠普…

5G Hz WiFi 频段划分

5GHz WiFi频段被划分为多个Band&#xff0c;这主要是基于国际通信标准和各国监管机构的规定。在常见的划分中&#xff0c;5GHz频段被分为以下几个部分&#xff1a; Band 1 (U-NII-1): 频率范围为5.15~5.25GHz&#xff0c;带宽为100MHz。Band 2 (U-NII-2 或 U-NII-2A/2C): 通常…

Visual Studio Code 自定义字体大小

常用编程软件自定义字体大全首页 文章目录 前言具体操作1. 打开首选项设置对话框2. 在Font Family里面输入字体 前言 Visual Studio Code 自定义字体大小&#xff0c;统一设置为 Cascadia Code SemiBold &#xff0c;大小为 14 具体操作 【文件】>【首选项】>【设置】&…

SSRF漏洞(服务器端请求伪造)相关案例

目录 前言&#xff1a; 案例&#xff1a;Web-ssrfme 一、redis未授权访问攻击 1.1 进入题目给出源码 1.2 测试ssrf 1.3 查看phpinfo发现主机 1.4 发现服务 1.5 攻击访问 1.6 FLAG 二、redis未授权写入任务计划 2.1 探测开放端口 2.2 导入任务计划 2.3 反弹shell成…

开源跨平台支持400多个国家语言屏幕键盘虚拟键盘Keyman开发指南

很多嵌入式开发平台或者移动端&#xff0c;桌面端开发都需要用到自定义的键盘&#xff0c;想要开发一个能够支持多国语言键盘布局的开源Keyboard可不容易&#xff0c;工作量非常大。 很多公司都是只开发英汉两种键盘布局&#xff0c;连Qt自带的VirtualKeyboard实际上要支持多国…

C++内存对齐和无符号有符号数混合运算

记录一下笔试中遇到的几个问题&#xff1a; C中无符号数与有符号数一起运算时&#xff0c;都会转换成无符号数运算 int main() {unsigned int a 100;signed b -100;cout << (unsigned)b << endl; // 4294967196signed c, d;c a / b; // 相当于 100 / 429496…

TCP数据包——报文头部组成

TCP协议报头包括以下字段: 源端口和目标端口:分别是发送方和接收方的端口号,用于标识通信的应用程序。 序列号:用于标识数据流的序列号,保证数据包的顺序性。每一个报文都有一个序列号。 确认号:用于确认收到的数据包序列号,用于实现可靠传输。每发送一个数据包都需要收…

系统分析师5-数据库特训专题

文章目录 1 数据库设计概述2 规范化与反规范化2.1 规范化2.2 反规范化2.3 案例分析例题1 3 数据库索引与视图的应用3.1 数据库索引3.2 数据库视图3.3 案例分析例题2 4 分布式数据库系统5 数据库分区分表分库5.1 案例分析例题3 6 分布式事务增补6.1 案例分析例题4 7 NoSQL8 附录…

优雅实现远程调用-OpenFeign

目录 OpenFeign介绍 OpenFeign最佳实践 我再来遇到个问题&#xff0c;我创建的com.xx.xxx包&#xff0c;放到一起了&#xff0c;不是那种一个在一个下面的那种 Nacos&#xff0c;只要看见这种什么网络报错啥的&#xff0c;java.net.SocketException: Network is unreachabl…

十、软件工程基础知识(考点篇)

1 软件工程 软件开发生命周期&#xff1a; 软件定义时期&#xff1a;包括可行性研究和详细需求分析过程&#xff0c;任务是确定软件开发工程必须完成的总目 标&#xff0c;具体(步骤)可分成问题定义、可行性研究、需求分析等。 软件开发时期&#xff1a;就是软件的设计与实…

Hive的体系架构、安装

目录 一、Hive体系架构二、安装1.嵌入模式2.本地模式和远程模式 一、Hive体系架构 二、安装 1.嵌入模式 特点 不需要Mysql支持&#xff0c;数据存储在自带的derby中只支持一个链接&#xff0c;即一时间只能有一个用户操作 部署 根据如下文件自行编写hive-site.xml hive-sit…

Docker 部署 Kafka 可视化 Kafka-UI

前言 本文部署的Kafka-UI 是基于Docker Compose 部署 Kafka的KRaft模式&#xff0c;如有需要可访问下文链接 Docker Compose 部署 Kafka的KRaft模式 不用依赖 Zookeeper 此部署也适用于不是docker部署的kafka集群 1.启动 Kafka-UI 服务 1.1 kafka 来自docker安装 docker r…

无法验证 Anaconda 仓库证书

无法验证 Anaconda 仓库证书 这个错误表明无法验证 Anaconda 仓库的证书。你可以尝试添加参数 --no-check-certificate 来解决这个问题&#xff08;不推荐但还挺好用&#xff0c;嘻嘻&#xff09;&#xff1a; wget --no-check-certificate https://repo.anaconda.com/archive…

【案例63】SSL RC4 加密套件支持检测 (Bar Mitzvah)修复方案

漏洞详情信息 漏洞名称 SSL RC4 加密套件支持检测 (Bar Mitzvah) 漏洞等级 高 漏洞描述 远程主机支持在一个或多个密码组中使用 RC4。 RC4 密码在伪随机字节流的生成中存在缺陷&#xff0c;导致引入了各种各样的小偏差&#xff0c;降低了其随机 性。 如果反复加密明文&am…

【北森-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…