vue xlsx插件导入

news2025/1/23 4:11:31

首先安装xlsx插件

yarn add xlsx@0.15.3

安装时候就有一个坑。版本问题第一次安装没有指定版本直接yarn add xlsx,安装的最新版本0.18多,会报XLSX没有read方法(读取Excel表格对象的方法)

具体代码

<el-upload class="upload-btn"
            ref="upload"
            action
            accept=".xls, .xlsx"
            :show-file-list="false"
            :on-change="readExcel"
            :auto-upload="false">
   <el-button slot="trigger"
              icon="el-icon-upload"
              size="small"
              type="primary">导入</el-button>
 </el-upload>
import XLSX from 'xlsx';

//导入 表单上传
	readExcel (file) {
	  // console.log('file', file);
	  const types = file.name.slice(file.name.lastIndexOf('.'))
	  const fileType = ['.xlsx', '.xls'].some(item => item === types)
	  // console.log(file.name.lastIndexOf('.'), types, fileType);
	  //  校验格式
	  if (!fileType) {
	    this.$message('格式错误!请重新上传')
	    return
	  }
	  // 返回workbook
	  this.file2Xce(file).then(tabJson => {
	    // console.log('tabJson', tabJson);
	    this.handleImportItem(tabJson)  //处理导入的数据使导入的数据在页面中展示。这个方法根据自己的需求,属于定制化
	  })
	},

  // 读表单,返回workbook
    file2Xce (file) {
      return new Promise(resolve => {
        const reader = new FileReader()
        reader.onload = e => {
          const data = e.target.result
          // 二进制流方式读取得到整份Excel表格对象
          this.excelData = XLSX.read(data, {
            type: 'binary'
          })
          // console.log('exvelData', this.excelData);
          // 只取第一个工作表
          const wsname = this.excelData.SheetNames[0]// 取第一张表
          const ws = XLSX.utils.sheet_to_json(this.excelData.Sheets[wsname])// 生成json表格内容
          resolve(ws)
        }
        // 以二进制方式打开文件
        reader.readAsBinaryString(file.raw); //file.raw取上传文件的File
      })
    },
 

需求
导入的Excel表格模板是这样格式的
在这里插入图片描述
可以发现第7行才是真正的表头。Excel中测量n列(是动态的),对应的项目表格中的样本数列。
在这里插入图片描述
需要根据Excel表中项目和项目中项目编号对应上,确定是哪一行的数据,然后把测量和样本对应上。

其中一种写法,写的有点麻烦,有时间用传入的tabs这种格式处理这种方法在写一遍

     // 处理导入的数据
    handleImportItem (tabs) {
      // console.log(tabs);
      // console.log('excelData', this.excelData);
      // 获取所有sheet页的name,不包括隐藏
      const sheetNames = (this.excelData.Workbook.Sheets.filter(l => l.Hidden !== 1) || []).map(l => l.name)
      // console.log(sheetNames);
      // 根据所有sheet页的name,解析sheet页的数据,变成A1(A列1行),B2这样单元格对象的数组 取第一个工作表
      const sheetData = sheetNames.map(l => {
        return {
          ...this.excelData.Sheets[l],
          sheetName: l
        }
      })[0]
      // console.log('sheetData', sheetData);
      // 取第7行之后有用数据 以A1,B2单元格的key值组成数组
      let cell = (Object.keys(sheetData).filter(l => /^[A-Z].*/.test(l)) || []).filter(c => c.replace(/[^0-9]/ig, "") >= 7);
      // console.log('cell', cell);
      // 导入的表格头
      let excelHeader = []
      cell.forEach(c => {
        let str = c.replace(/[^a-zA-Z]/g, "") //列 A,B,C...
        let num = c.replace(/[^0-9]/ig, "") //行 1,2,3...
        // console.log(str, num);
        // 动态表格头绑定code 第7行是真正的表格头
        if (num == 7) {
          // console.log(c, sheetData[c], sheetData['A7']);
          if (c == 'A7' && sheetData['A7'].v == '项目') {
            excelHeader.push({
              name: sheetData[c].v,
              code: 'itemCode',
              col: str,
            })
          } else {
            if (sheetData['A7'].v !== '项目') {
              this.$message('格式错误!请重新选择');
              return;
            } else {
              this.quantitativeData.forEach(q => {
                if (q.itemList) {
                  // console.log(q.sampleTableHeaders);
                  q.sampleTableHeaders.forEach(l => {
                    if (l.name.replace(/[^0-9]/ig, "") == sheetData[c].v.replace(/[^0-9]/ig, "")) {
                      excelHeader.push({
                        name: sheetData[c].v,
                        code: l.code,
                        col: str
                      })
                    }
                  })
                }
              })
            }
          }
        }

        // 赋值 导入的表格头里code与页面中表格头的code对应上就赋值
        // 通过项目编号判断是否是同一行
        excelHeader.forEach(l => {
          this.quantitativeData.forEach(q => {
            if (q.itemList) {
              // console.log('q', q);
              q.itemList.forEach(i => {
                // 判断项目编号
                if (sheetData[c].v == i.itemCode) {
                  // 项目编号对应上的行表头
                  let row = cell.filter(v => v.replace(/[^0-9]/ig, "") == num)
                  row.forEach(r => {
                    // 判断列号和导入的表格头的col 把样本对应上,样本列表要小于样本数
                    if (r.replace(/[^a-zA-Z]/g, "") == l.col && parseInt(l.code.replace(/[^0-9]/ig, "")) <= i.sampleCnt) {
                      // i[l.code] = sheetData[r].v
                      this.$set(i, l.code, sheetData[r].v)
                    }
                  })
                  this.checkSampleCnt(i, q)
                }
              })
            }
          })
        })
      })
      // console.log('excelHeader', excelHeader);
    },

来了来了
使用传入的tabs完成处理数据,赋值。(果然简单好多,代码量也蹭蹭减少,运行速度也快)
现在的需求也和上面的不太一样了,现在需求,页面加了来料批次列。需要项目和设备项目号匹配且批次一致,如果页面批次没有直接赋值就行。

因为是优化,所以想尽量减少循环,所以加了参数dataItem(页面中点击导入的大项)之前一直是循环整个页面,取到大项,再循环大项下的小项,直接就两层循环了,再加上处理数据赋值写的也麻烦,总共循环写了5层,里面还有filter。相当于最多循环6。。。实际操作随便几十条数据就卡死,别骂了别骂了,我知道写的烂到家了

upload组件on-change事件如果想传自定义参数,请这样写

<el-upload
                class="upload-btn"
                ref="upload"
                action
                accept=".xls, .xlsx"
                :show-file-list="false"
                :on-change="
                  (file, fileList) => {
                    readExcel(file, dataItem);
                  }
                "
                :auto-upload="false"
              >
                <el-button slot="trigger" icon="el-icon-upload" size="small" type="primary">导入</el-button>
              </el-upload>

处理数据,赋值简便写法

    handleImportItem(tabs, dataItem) {
      let excelHeader = [];
      tabs.forEach((tabData, index) => {
        if (index == 4 && Object.values(tabData)[0] !== '项目') {
          this.$message('格式错误!请重新选择');
          return;
        } else {
          if (Object.values(tabData)[0] === '项目') {
            for (let i in tabData) {
              let num = tabData[i].replace(/[^0-9]/gi, '');
              if (num) {
                if (num < 10) {
                  tabData[i] = 'data0' + tabData[i].replace(/[^0-9]/gi, '');
                } else {
                  tabData[i] = 'data' + tabData[i].replace(/[^0-9]/gi, '');
                }
              } else {
                if (tabData[i] === '名义值') tabData[i] = 'specsVal';
                if (tabData[i] === '上公差') tabData[i] = 'upperTol';
                if (tabData[i] === '下公差') tabData[i] = 'lowerTol';
                if (tabData[i] === '状态') tabData[i] = 'checkRsType';
                if (tabData[i] === '测量值') tabData[i] = 'data01';
              }
              excelHeader.push({
                name: tabData[i],
                code: i,
              });
            }
            // console.log('excelHeader', excelHeader);
          }
          if (index > 4) {
            dataItem.itemList.forEach(item => {
              // 设备项目号和项目对应
              if (
                excelHeader[0].name === '项目' &&
                item.eqpItemNo === tabData[excelHeader[0].code] &&
                (item.lotNo === tabs[2].__EMPTY || !item.lotNo)
              ) {
                // 来料批次
                if (!item.lotNo) this.$set(item, 'lotNo', tabs[2].__EMPTY);
                excelHeader.forEach(header => {
                  let headerNum = header.name.replace(/[^0-9]/gi, '');
                  // 测量数据小于样本数;
                  if (parseInt(headerNum) <= +item.sampleCnt) {
                    // 处理导入数据为指数
                    typeof tabData[header.code] === 'string' && tabData[header.code].indexOf('^') >= 0
                      ? (tabData[header.code] = Math.pow(
                          +tabData[header.code].split('^')[0],
                          +tabData[header.code].split('^')[1]
                        ))
                      : tabData[header.code];
                    this.$set(item, header.name, tabData[header.code]);
                  }
                  // 名义值,上下公差
                  if (!headerNum) {
                    if (tabData[header.code] === 'OK') tabData[header.code] = 'PASS';
                    if (tabData[header.code] === 'NG') tabData[header.code] = 'FAIL';
                    this.$set(item, header.name, tabData[header.code]);
                  }
                });
              }
              this.checkSampleCnt(item, dataItem);
            });
          }
        }
      });
    },

最近又遇到了导入的Excel 中数据有日期时间的
直接导入不太行会得到一串数字。
官方文档上有这两个参数是关于时间格式转换的
在这里插入图片描述

但是吧实际使用的时候dateNF这个参数不起作用,不管是XLSX.read上这个参数还是XLSX.utils.sheet_to_json这个上边dateNF参数都没起作用,不晓得为啥

导入日期时间解决

// 读表单,返回workbook
file2Xce (file) {
  return new Promise(resolve => {
    let reader = new FileReader()
    reader.onload = e => {
      let data = e.target.result
      this.excelData = XLSX.read(data, {
        type: 'binary',
        cellDates: true, // 格式转成中国标准时间
        dateNF: 'yyyy-MM-dd' // 没起作用
      })
      let wsname = this.excelData.SheetNames[0]
      console.log(this.excelData.Sheets[wsname]);
      let ws = XLSX.utils.sheet_to_json(this.excelData.Sheets[wsname],{row: true}) // 转日期格式时,最好加上row: true参数
      resolve(ws)
    }
    reader.readAsBinaryString(file.raw);
  })
},
// 赋值
handleGetFile(data) {
  data.forEach( row => {
    if(row['预计完成时间']) {
      this.filesInfo.caseActionTos.push({
        Date: moment(row['预计完成时间']).format('YYYY/MM/DD'), // 赋值时候转成想要的格式
      })
    }
  })
},

更详细的参数什么的看下边的
xlsx官方文档https://www.npmjs.com/package/xlsx

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

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

相关文章

uniapp配置网络请求

1.简介 由于平台的限制&#xff0c;小程序项目中不支持 axios&#xff0c;而且原生的 wx.request() API 功能较为简单&#xff0c;不支持拦截器等全局定制的功能。因此&#xff0c;建议在 uni-app 项目中使用 escook/request-miniprogram 第三方包发起网络数据请求。 官方文…

JavaScript常见数组方法,教你如何转置矩阵

&#x1f4dc;个人简介 ⭐️个人主页&#xff1a;微风洋洋&#x1f64b;‍♂️ &#x1f351;博客领域&#xff1a;编程基础,后端 &#x1f345;写作风格&#xff1a;干货,干货,还是tmd的干货 &#x1f338;精选专栏&#xff1a;【JavaScript】 &#x1f680;支持洋锅&#xff…

git提交规范,规范自己的提交标准

为了规范我的git提交内容&#xff0c;提交的时候commit -m “备注的信息”&#xff0c;但是每个人的备注信息千奇百怪&#xff0c;为了统一&#xff0c;我们进行了git的规范。 首先要全局安装commitizen npm i -g commitizen4.2.4然后安装插件 npm i cz-customizable6.3.0…

javascript获取url信息的常见方法

1、获取页面完整的url 1 2 var alocation.href; console.log(a); // “http://www.cnblogs.com/wuxibolgs329/p/5261577.html#flag?test12345” 2、获取页面的域名 var host window.location.host; //www.cnblogs.com var host2 document.domain; //www.cnblogs.com …

学生管理系统Element UI版

&#x1f482; 个人主页: 陶然同学&#x1f91f; 版权: 本文由【陶然同学】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦&#x1f485; 想寻找共同成长的小伙伴&#xff0c;请点击【Java全栈开发社区】…

微前端 - qiankun

前言 qiankun 是一个基于 single-spa 的微前端实现库&#xff0c;旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。 本文主要记录下如何接入 qiankun 微前端。主应用使用 vue2&#xff0c;子应用使用 vue3、react。 一、主应用 主应用不限技术栈&#xff0c;只需…

前后端分离式交互

目录 前言 1.javaEE环境安装 第一步&#xff1a;正常创建javase项目 第二步&#xff1a;右击项目&#xff0c;引入框架支持 第三步&#xff1a;将项目部署到Tomcat服务器上。Tomcat安装及配置 2.servlet搭建 请求格式为&#xff1a;ip:端口/项目名/servlet地址 3.servl…

uniapp -- 扫码记录(针对app场景)

背景 扫码需求日益增多&#xff0c;为了满足客户的需求&#xff0c;扫码演变的多种多样&#xff0c;其中有二维码&#xff0c;条形码居中&#xff0c;条形码又可以细分成几种,以下记录全屏和自定义页面扫码的在uniapp的技术实现 全屏扫码 uniapp自身带的api方法-uni.scanCod…

vscode的vue代码提示与补全没反应(vetur问题)

问题&#xff1a;vscode的里面写vue时候代码提示用不了了 问题原因&#xff1a;vetur这个插件升级了&#xff0c;与老版本的vscode不适配了 解决方案&#xff1a; 1.卸载vscode&#xff0c;与vscode官网下载最新版本vscode 2.安装老版本的vetur(感谢评论区另一个大佬推荐的…

刷题日常计~JS③

作者 : SYFStrive 博客首页 : 点击跳转HomePage &#x1f4dc;&#xff1a; 初编程JavaScript之每天10题 &#x1f449; 从质变到量变&#x1f4aa; &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f5…

关于WEB-INF目录及Tomcat部署方式、原理的简单理解

个人学习所用&#xff0c;有不足或错误之处欢迎指正和补充&#xff01; 目录 前言&#xff1a; 一、WEB-INF目录与META-INF目录 1. Web应用程序的目录结构 2. WEB-INF简介 3. WEB-INF的作用 4. 静态资源的访问 二、Tomcat部署本地工件 1. war和war exploded的区别 2.…

【HTML小游戏】推箱子网页版(附完整源码)

最近刚刚更新完了HTML,CSS的万字总结,有很多人已经学习完了文章,感觉反馈还不错,今天,用HTML,CSS,JS的知识编写了一个童年经典游戏 - 推箱子,供学习参考。 文章目录 1. 效果展示2. 游戏介绍3. 游戏规则4. 源码学习1. 效果展示 游戏主界面展示: 游戏界面展示: 2. 游戏…

ECMAScript6新特性【数组扩展(扩展运算符、新增方法一、新增方法二、新增方法三)】(四)-全面详解(学习总结---从入门到深化)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

【vue2】vuex的安装、配置与使用

一、前言 使用vuex可以实现数据的共享。 二、安装 vscode中新建终端安装vuex。由于vue2不能使用vuex4的版本&#xff0c;所以在安装时需要指定版本3 npm i vuex3 三、vuex工作流 vuex核心包括actions、mutations、state。 ①state用来存储数据&#xff1b; ②actions用…

vue+element-ui

一.使用图形化界面&#xff0c;创建vue项目 vue ui(在根目录下&#xff0c;打开cmd,启动图形化界面) 添加插件 添加element-ui插件 这里选择import on demand 安装好了 添加依赖 添加axios依赖 添加好了 二.创建Git仓库&#xff0c;连接并上传刚刚创建的项目 在项目文件目录下…

基于微信小程序的电影订票系统设计与实现(代码+数据库+论文)

项目简介 本系统是基于微信小程序的电影订票系统的设计与实现。基于B/S架构模式进行设计&#xff0c;使用了JavaScript、CSS、java语言等&#xff0c;后台数据库设计使用Mysql。本电影订票系统主要分为前端小程序订票系统和后台电影管理两部分。用户使用时接触的是系统前端小程…

学习Canvas基础-绘制矩形

学习Canvas基础-绘制矩形 canvas提供了三个API&#xff0c;分别是&#xff1a; 1.绘制矩形 rect(起点X, 起点Y, 绘制的矩形width, 绘制的矩形height) 但该方法不会出实际效果&#xff0c;需要配合 fill&#xff08;&#xff09;和stroke&#xff08;&#xff09;方法让其显现…

深入理解CSS之flex精要之 flex-basis flex-grow flex-shrink 实战讲解

这篇文章对flex不熟也可以看。这篇文章只讲这三个属性。为了简单化&#xff0c;不会提到主轴交叉轴&#xff0c;也不讲方向&#xff0c;默认方向就是水平方向从左往右。但并不影响对这三个概念的理解。 如果你觉得对flex比较了解&#xff0c;可以直接从第二小节开始看起。 1.…

window.print() 前端页面打印与预览PDF

window.print()打印是浏览器自带的打印&#xff0c;实现原理是将html转换为pdf可以在线预览打印或者导出pdf&#xff0c;在任何网页上可通过Ctilp快捷键调出浏览器打印程序&#xff0c;它可将整个网页打印出来&#xff0c;在我们开发中&#xff0c;其实并不需要将所有页面打印出…

js调用gpt3.5

参考链接&#xff1a;直接在前端调用 GPT-3 API 效果图&#xff1a; 小技巧&#xff1a; 1. shiftenter是发送消息的快捷键 2. 有本地聊天记录功能 3. 按delete按钮可以删除包括这条之后的记录 <!DOCTYPE html> <html><head><meta charset"UTF-8&…