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
  }
},
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈阿星

您的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值