Vue项目之---使用xlsx实现批量导入导出功能

520 阅读4分钟

“携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

安装 xlsx

  • npm i xlsx

导入

封装导入组件

改造 vue-element-admin(点击复制UploadExcel组件代码)
  • 封装成一个全局组件 src/components/UploadExcel

注册全局导入组件

 // src/component/index.js
 import UploadExcel from './UploadExcel'
 export default {
   install(Vue) {
     Vue.component('UploadExcel', UploadExcel) // 注册导入excel组件
   }
 }
 ​
 // main.js
 import Component from '@/component'
 Vue.use(Component)

利用element-ui修改样式和布局

 <template>
  <div class="upload-excel">
     <div class="btn-upload">
       <el-button :loading="loading" size="mini" type="primary" @click="handleUpload">
         点击上传
       </el-button>
     </div>
     <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
     <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
       <i class="el-icon-upload" />
       <span>将文件拖到此处</span>
     </div>
   </div>
 </template>
 <style scoped lang="scss">
 .upload-excel {
   display: flex;
   justify-content: center;
    margin-top: 100px;
    .excel-upload-input{
        display: none;
         z-index: -9999;
      }
    .btn-upload , .drop{
       border: 1px dashed #bbb;
       width: 350px;
       height: 160px;
       text-align: center;
       line-height: 160px;
    }
    .drop{
        line-height: 80px;
        color: #bbb;
       i {
         font-size: 60px;
         display: block;
       }
    }
 }
 </style>

实现导入excel的功能:

  1. 创建 import 组件 views/import/index.vue
  2. 建立公共导入的页面路由
     {
         path: '/import',
         component: Layout,
         hidden: true, // 隐藏在左侧菜单中
         children: [{
           path: '', // 二级路由path什么都不写 表示二级默认路由
           component: () => import('@/views/import')
         }]
       },
    
  3. 封装导入数据的api接口
  4. 实现excel导入
    • import组件中获取导入的 excel 数据,导入 excel接口

      • success({result})
    • 为了让这个页面可以服务更多的导入功能,我们可以在页面中用参数来判断,是否是导入员工

      • @click="$router.push('/import?type=order')"(使用)
      • type: this.$route.query.type
    • 中英文对照

      • Object.keys(userRelations)
    实现代码:
     // views/import/index.vue
     ​
     async success({ results }) {
       const arr = results.map(item => this.zhToEn(item, this.type))
       await importOrder(arr)
       this.$message.success('导入数据成功!')
       this.$router.back() // 回到上一页
     },
         
     zhToEn(zhs, type) {
       const orderInfo = {}
       if (type === 'order') {
         const orderRelations = {
           订单量: 'orderVol',
           订单号: 'orderNum',
           名称: 'orderName',
           签订日期: 'signTime',
           ...
         }
         Object.keys(zhs).map(item => {
           console.log(item)
           const value = orderRelations[item]
           if (value === 'signTime' || value === 'xxTime') {
             console.log(1111)
             // 因为 Excel 存储的日期是从 1900 年 1 月 1 日开始按天数来计算的,也就是说 1900 年 1 月 1 日在 Excel 中是 1。
             // 因此我们需要对时间进行格式化
            orderInfo[value] = this.formatExcelDate(zhs[item])
           } else {
           orderInfo[value] = zhs[item]
           }
         })
         return orderInfo
       }
     },
     ​
     formatExcelDate(num, format = '-') {
       if (!/^\d+$/.test(num)) return
       num = parseInt(num)
       let millisecond = 0 // 转化后的毫秒数
       if (num > 60) {
         // 对大于 60 的日期进行减 1 处理
         millisecond = (num - 25568 - 1) * 3600 * 24 * 1000
       } else {
         millisecond = (num - 25568) * 3600 * 24 * 1000
       }
       const date = new Date(millisecond) // 根据转化后的毫秒数获取对应的时间
       const yy = date.getFullYear()
       const m = date.getMonth() + 1
       const mm = m >= 10 ? m : '0' + m
       const d = date.getDate()
       const dd = d >= 10 ? d : '0' + d
       return yy + format + mm + format + dd // 返回格式化后的日期
     }
    
    
    
 ​
 ​
 ​
 ### 导出
 ​
 1. #### 安装excel所需依赖
 ​
    ```js
    npm install xlsx file-saver -S
    npm install script-loader -S -D
  1. 基本数据

    • 因为数据中的key是英文,想要导出的表头是中文的话,需要将中文和英文做对应

      • const headers = {'手机号':'mobile',...}
      • const { rows } = await getEmployeeList({ page: 1, size: this.page.total })
  2. 书写按需格式化函数

    • formatJson(headers, rows)

      • 该方法负责将数组转化成二维数组
      • 映射中英文
    • formatDate

      • 格式化时间
      • import { formatDate } from '@/filters/index'
  3. excel导出基本的结构

     import('@/vendor/Export2Excel').then(excel => {
       excel.export_json_to_excel({
        header: Object.keys(headers), //表头 必填 Array
        data, //具体数据 必填 Array
        filename: 'excel-list', //导出文件名 非必填
        autoWidth: true, //单元格是否要自适应宽度非必填
        bookType: 'xlsx' //导出文件类型 非必填
       })
     })
    
  4. 复杂表头的导出

实现代码:

 exportFn() {
   const headers = {
     订单量: 'orderVol',
     订单号: 'orderNum',
     名称: 'orderName',
     签订日期: 'signTime',
   }
   // 导出 excel
   import('@/vendor/Export2Excel').then(async excel => {
     //  excel 是引入文件的导出对象
     // 导出  header 从哪里来
     // data 从哪里来
     // 现在没有一个接口获取所有的数据
     // 获取订单的接口 页码 每页条数    100   1 10000
     const { rows } = await getOrderList({ page: 1, size: this.page.total })
     const data = this.formatJson(headers, rows) // 返回的 data 就是 要导出的结构
     const multiHeader = [['订单量', '订单号', '', '', '', '', '名称']]
     const merges = ['A1:A2', 'B1:F1', 'G1:G2']
     excel.export_json_to_excel({
       header: Object.keys(headers),
       data,
       filename: '订单资料表',
       multiHeader, // 复杂表头
       merges // 合并选项
     })
   })
 },
 // 将表头数据和数据进行对应
 // [{}]  =>   [[]]
 formatJson(headers, rows) {
   return rows.map(item => {
     // item 是一个对象  { orderName: 132111,ordername: '小米手机'  }
     // ["订单号", "订单量", "名称" 。。]
     return Object.keys(headers).map(key => {
       // 需要判断 字段
       if (headers[key] === 'signTime' || headers[key] === 'xxTime') {
         // 格式化日期
         return formatDate(item[headers[key]])
       } 
       return item[headers[key]]
     })
     // ["132", '张三’, ‘’,‘’,‘’d]
   })
   // return rows.map(item => Object.keys(headers).map(key => item[headers[key]]))
   // 需要处理时间格式问题
 },

难点:

难点是导出的时候,需要把请求到的数据转换为xlsx要求的格式才能导出成功;实现批量导入功能的时候,也需要把通过xlsx插件解析好的Excel表格数据转换为接口需要的数据格式

比如:批量导入数据时,因为获取到的Excel表格数据字段都是中文名的,但是后端接口需要的是英文名,因此我们把数据通过接口传递给后端之前需要先把数据转换为后端规定的格式,我们的做法是先准备好一个中英文字段对照字典表,然后再根据字典表把Excel表格的中文字段名替换成英文字段名,从而实现数据转换。