0


vue xlsx插件导入

首先安装xlsx插件

  1. yarn add xlsx@0.15.3

安装时候就有一个坑。版本问题第一次安装没有指定版本直接

  1. yarn add xlsx

,安装的最新版本0.18多,会报XLSX没有read方法(读取Excel表格对象的方法)

具体代码

  1. <el-upload class="upload-btn"
  2. ref="upload"
  3. action
  4. accept=".xls, .xlsx"
  5. :show-file-list="false"
  6. :on-change="readExcel"
  7. :auto-upload="false">
  8. <el-button slot="trigger"
  9. icon="el-icon-upload"
  10. size="small"
  11. type="primary">导入</el-button>
  12. </el-upload>
  1. import XLSX from 'xlsx';
  2. //导入 表单上传
  3. readExcel (file) {
  4. // console.log('file', file);
  5. const types = file.name.slice(file.name.lastIndexOf('.'))
  6. const fileType = ['.xlsx', '.xls'].some(item => item === types)
  7. // console.log(file.name.lastIndexOf('.'), types, fileType);
  8. // 校验格式
  9. if (!fileType) {
  10. this.$message('格式错误!请重新上传')
  11. return
  12. }
  13. // 返回workbook
  14. this.file2Xce(file).then(tabJson => {
  15. // console.log('tabJson', tabJson);
  16. this.handleImportItem(tabJson) //处理导入的数据使导入的数据在页面中展示。这个方法根据自己的需求,属于定制化
  17. })
  18. },
  19. // 读表单,返回workbook
  20. file2Xce (file) {
  21. return new Promise(resolve => {
  22. const reader = new FileReader()
  23. reader.onload = e => {
  24. const data = e.target.result
  25. // 二进制流方式读取得到整份Excel表格对象
  26. this.excelData = XLSX.read(data, {
  27. type: 'binary'
  28. })
  29. // console.log('exvelData', this.excelData);
  30. // 只取第一个工作表
  31. const wsname = this.excelData.SheetNames[0]// 取第一张表
  32. const ws = XLSX.utils.sheet_to_json(this.excelData.Sheets[wsname])// 生成json表格内容
  33. resolve(ws)
  34. }
  35. // 以二进制方式打开文件
  36. reader.readAsBinaryString(file.raw); //file.raw取上传文件的File
  37. })
  38. },

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

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

  1. // 处理导入的数据
  2. handleImportItem (tabs) {
  3. // console.log(tabs);
  4. // console.log('excelData', this.excelData);
  5. // 获取所有sheet页的name,不包括隐藏
  6. const sheetNames = (this.excelData.Workbook.Sheets.filter(l => l.Hidden !== 1) || []).map(l => l.name)
  7. // console.log(sheetNames);
  8. // 根据所有sheet页的name,解析sheet页的数据,变成A1(A列1行),B2这样单元格对象的数组 取第一个工作表
  9. const sheetData = sheetNames.map(l => {
  10. return {
  11. ...this.excelData.Sheets[l],
  12. sheetName: l
  13. }
  14. })[0]
  15. // console.log('sheetData', sheetData);
  16. // 取第7行之后有用数据 以A1,B2单元格的key值组成数组
  17. let cell = (Object.keys(sheetData).filter(l => /^[A-Z].*/.test(l)) || []).filter(c => c.replace(/[^0-9]/ig, "") >= 7);
  18. // console.log('cell', cell);
  19. // 导入的表格头
  20. let excelHeader = []
  21. cell.forEach(c => {
  22. let str = c.replace(/[^a-zA-Z]/g, "") //列 A,B,C...
  23. let num = c.replace(/[^0-9]/ig, "") //行 1,2,3...
  24. // console.log(str, num);
  25. // 动态表格头绑定code 第7行是真正的表格头
  26. if (num == 7) {
  27. // console.log(c, sheetData[c], sheetData['A7']);
  28. if (c == 'A7' && sheetData['A7'].v == '项目') {
  29. excelHeader.push({
  30. name: sheetData[c].v,
  31. code: 'itemCode',
  32. col: str,
  33. })
  34. } else {
  35. if (sheetData['A7'].v !== '项目') {
  36. this.$message('格式错误!请重新选择');
  37. return;
  38. } else {
  39. this.quantitativeData.forEach(q => {
  40. if (q.itemList) {
  41. // console.log(q.sampleTableHeaders);
  42. q.sampleTableHeaders.forEach(l => {
  43. if (l.name.replace(/[^0-9]/ig, "") == sheetData[c].v.replace(/[^0-9]/ig, "")) {
  44. excelHeader.push({
  45. name: sheetData[c].v,
  46. code: l.code,
  47. col: str
  48. })
  49. }
  50. })
  51. }
  52. })
  53. }
  54. }
  55. }
  56. // 赋值 导入的表格头里code与页面中表格头的code对应上就赋值
  57. // 通过项目编号判断是否是同一行
  58. excelHeader.forEach(l => {
  59. this.quantitativeData.forEach(q => {
  60. if (q.itemList) {
  61. // console.log('q', q);
  62. q.itemList.forEach(i => {
  63. // 判断项目编号
  64. if (sheetData[c].v == i.itemCode) {
  65. // 项目编号对应上的行表头
  66. let row = cell.filter(v => v.replace(/[^0-9]/ig, "") == num)
  67. row.forEach(r => {
  68. // 判断列号和导入的表格头的col 把样本对应上,样本列表要小于样本数
  69. if (r.replace(/[^a-zA-Z]/g, "") == l.col && parseInt(l.code.replace(/[^0-9]/ig, "")) <= i.sampleCnt) {
  70. // i[l.code] = sheetData[r].v
  71. this.$set(i, l.code, sheetData[r].v)
  72. }
  73. })
  74. this.checkSampleCnt(i, q)
  75. }
  76. })
  77. }
  78. })
  79. })
  80. })
  81. // console.log('excelHeader', excelHeader);
  82. },

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

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

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

  1. <el-upload
  2. class="upload-btn"
  3. ref="upload"
  4. action
  5. accept=".xls, .xlsx"
  6. :show-file-list="false"
  7. :on-change="
  8. (file, fileList) => {
  9. readExcel(file, dataItem);
  10. }
  11. "
  12. :auto-upload="false"
  13. >
  14. <el-button slot="trigger" icon="el-icon-upload" size="small" type="primary">导入</el-button>
  15. </el-upload>

处理数据,赋值简便写法

  1. handleImportItem(tabs, dataItem) {
  2. let excelHeader = [];
  3. tabs.forEach((tabData, index) => {
  4. if (index == 4 && Object.values(tabData)[0] !== '项目') {
  5. this.$message('格式错误!请重新选择');
  6. return;
  7. } else {
  8. if (Object.values(tabData)[0] === '项目') {
  9. for (let i in tabData) {
  10. let num = tabData[i].replace(/[^0-9]/gi, '');
  11. if (num) {
  12. if (num < 10) {
  13. tabData[i] = 'data0' + tabData[i].replace(/[^0-9]/gi, '');
  14. } else {
  15. tabData[i] = 'data' + tabData[i].replace(/[^0-9]/gi, '');
  16. }
  17. } else {
  18. if (tabData[i] === '名义值') tabData[i] = 'specsVal';
  19. if (tabData[i] === '上公差') tabData[i] = 'upperTol';
  20. if (tabData[i] === '下公差') tabData[i] = 'lowerTol';
  21. if (tabData[i] === '状态') tabData[i] = 'checkRsType';
  22. if (tabData[i] === '测量值') tabData[i] = 'data01';
  23. }
  24. excelHeader.push({
  25. name: tabData[i],
  26. code: i,
  27. });
  28. }
  29. // console.log('excelHeader', excelHeader);
  30. }
  31. if (index > 4) {
  32. dataItem.itemList.forEach(item => {
  33. // 设备项目号和项目对应
  34. if (
  35. excelHeader[0].name === '项目' &&
  36. item.eqpItemNo === tabData[excelHeader[0].code] &&
  37. (item.lotNo === tabs[2].__EMPTY || !item.lotNo)
  38. ) {
  39. // 来料批次
  40. if (!item.lotNo) this.$set(item, 'lotNo', tabs[2].__EMPTY);
  41. excelHeader.forEach(header => {
  42. let headerNum = header.name.replace(/[^0-9]/gi, '');
  43. // 测量数据小于样本数;
  44. if (parseInt(headerNum) <= +item.sampleCnt) {
  45. // 处理导入数据为指数
  46. typeof tabData[header.code] === 'string' && tabData[header.code].indexOf('^') >= 0
  47. ? (tabData[header.code] = Math.pow(
  48. +tabData[header.code].split('^')[0],
  49. +tabData[header.code].split('^')[1]
  50. ))
  51. : tabData[header.code];
  52. this.$set(item, header.name, tabData[header.code]);
  53. }
  54. // 名义值,上下公差
  55. if (!headerNum) {
  56. if (tabData[header.code] === 'OK') tabData[header.code] = 'PASS';
  57. if (tabData[header.code] === 'NG') tabData[header.code] = 'FAIL';
  58. this.$set(item, header.name, tabData[header.code]);
  59. }
  60. });
  61. }
  62. this.checkSampleCnt(item, dataItem);
  63. });
  64. }
  65. }
  66. });
  67. },

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

但是吧实际使用的时候

  1. dateNF

这个参数不起作用,不管是

  1. XLSX.read

上这个参数还是

  1. XLSX.utils.sheet_to_json

这个上边dateNF参数都没起作用,不晓得为啥

导入日期时间解决

  1. // 读表单,返回workbook
  2. file2Xce (file) {
  3. return new Promise(resolve => {
  4. let reader = new FileReader()
  5. reader.onload = e => {
  6. let data = e.target.result
  7. this.excelData = XLSX.read(data, {
  8. type: 'binary',
  9. cellDates: true, // 格式转成中国标准时间
  10. dateNF: 'yyyy-MM-dd' // 没起作用
  11. })
  12. let wsname = this.excelData.SheetNames[0]
  13. console.log(this.excelData.Sheets[wsname]);
  14. let ws = XLSX.utils.sheet_to_json(this.excelData.Sheets[wsname],{row: true}) // 转日期格式时,最好加上row: true参数
  15. resolve(ws)
  16. }
  17. reader.readAsBinaryString(file.raw);
  18. })
  19. },
  20. // 赋值
  21. handleGetFile(data) {
  22. data.forEach( row => {
  23. if(row['预计完成时间']) {
  24. this.filesInfo.caseActionTos.push({
  25. Date: moment(row['预计完成时间']).format('YYYY/MM/DD'), // 赋值时候转成想要的格式
  26. })
  27. }
  28. })
  29. },

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


本文转载自: https://blog.csdn.net/cecoal/article/details/125217317
版权归原作者 cecoal 所有, 如有侵权,请联系我们删除。

“vue xlsx插件导入”的评论:

还没有评论