前端实现excel导出和导入(react项目)

课程推荐:web全栈就业班--融职教育精品课程

最近公司有个新需求,需要前端导出规定模板的excel,导入的时候前端解析excel文件,数据处理一下传给后台,下面分享下纯前端实现excel的导出和导入:

excel导出

handleClick = () => {
// 定制化改动地方
let excelData = this.state.excelData // 数据是后台返回渲染导出的excel数据的
let data = []
if (excelData.length) {
for (let i = 0; i < excelData.length; i++) {
let obj = {
'监控面编号': excelData[i].taskName,
'监控点编号': excelData[i].monitorPointNumber,
'高程(m)': '',
};
data.push(obj);
}
} else {
let obj = {
'监控面编号': '',
'监控点编号': '',
'高程(m)': '',
};
data.push(obj);
}
// 表格标题

const options = {
  dataTitle: '表名:哈哈哈',
  reportCompany: '说明:XXXX',
  date: `日期`,
  reportType: `施工工况`,
}
// 配置文件类型
const wopts = { bookType: 'xlsx', bookSST: true, type: 'binary', cellStyles: true };
this.recordExcelDown(data, wopts, options);

}
recordExcelDown = (json, type, options) => {
var tmpdata = json[0];
// 定制化改动地方
json.unshift({}, {}, {}, {}); // 向表格数据中插入4行位置(规定的模板)
const keyMap = []; // 获取keys
for (const k in tmpdata) { // 为插入的4行位置添加数据
keyMap.push(k);
// 定制化改动地方
json[3][k] = k; // json[3][k] = k 3为插入4行的最后一行索引,用于展示列头
}
var tmpdata = []; // 用来保存转换好的json
json
.map((v, i) => {
const data = keyMap.map((k, j) => {
return Object.assign(
{},
{
v: v[k],
position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 2), // 表格数据的位置
}
);
});
return data;
})
.reduce((prev, next) => prev.concat(next))
.forEach(
(v, i) =>
(tmpdata[v.position] = {
v: v.v,
})
);
let outputPos = Object.keys(tmpdata); // 设置区域,比如表格从A1到D10
// 定制化改动地方
tmpdata.A1 = { v: options.dataTitle }; // A1-A4区域的内容
tmpdata.A2 = { v: options.reportCompany };
tmpdata.A3 = { v: options.date };
tmpdata.A4 = { v: options.reportType };
tmpdata.C3 = { v: '2020-1-1' };
tmpdata.C4 = { v: '1号梁段挂篮就位' };
tmpdata.C6 = { v: '1.001' };
tmpdata.C1 = { v: 'tid' };
tmpdata.D1 = { v: this.props.taskId };
tmpdata.E1 = { v: 'bid' };
tmpdata.F1 = { v: this.props.bridgeRecord.id };
// 定制化改动地方
outputPos = ['A1'].concat(['A2'], ['A3'], ['A4'], ['C1'], ['C4'], ['C5'], ['C6'], ['D1'], ['D3'], ['D4'], ['D6'], ['E1'], ['F1'], outputPos);
// 定制化改动地方
tmpdata.A1.s = {
font: { sz: 14, bold: true, vertAlign: true },
alignment: { vertical: 'center', horizontal: 'center' }, // 垂直、水平
fill: { bgColor: { rgb: 'E8E8E8' }, fgColor: { rgb: 'E8E8E8' } },
}; // <====设置xlsx单元格样式
tmpdata.A2.s = {
font: { sz: 12, bold: true, vertAlign: true },
alignment: { vertical: 'center', horizontal: 'bottom' },
}; // <====设置xlsx单元格样式
tmpdata.A3.s = {
font: { sz: 12, bold: true, vertAlign: true },
alignment: { vertical: 'center', horizontal: 'bottom' },
}; // <====设置xlsx单元格样式
tmpdata.A4.s = {
font: { sz: 12, bold: true, vertAlign: true },
alignment: { vertical: 'center', horizontal: 'bottom' },
}; // <====设置xlsx单元格样式
// s-e 代表区域 c-r 代表列-行的索引
// 定制化改动地方
tmpdata['!merges'] = [
{
s: { c: 0, r: 0 },
e: { c: 1, r: 0 },
},
{
s: { c: 0, r: 1 },
e: { c: 9, r: 1 },
},
{
s: { c: 0, r: 2 },
e: { c: 1, r: 2 },
},
{
s: { c: 0, r: 3 },
e: { c: 1, r: 3 },
},
]; // <====合并单元格
let dataArrWidth = []
// 定制化改动地方
json.forEach(item => {
dataArrWidth.push({ wpx: 100 })
})
tmpdata['!cols'] = dataArrWidth;// <====设置一列宽度, 代表20列都是300宽
const tmpWB = {
SheetNames: ['mySheet'], // 保存的表标题
Sheets: {
mySheet: Object.assign(
{},
tmpdata, // 内容
{
'!ref': ${outputPos[0]}:${outputPos[outputPos.length - 1]}, // 设置填充区域(表格渲染区域)
}
),
},
};
const tmpDown = new Blob(
[
this.s2ab(
XLSX.write(
tmpWB,
{ bookType: type == undefined ? 'xlsx' : type.bookType, bookSST: false, type: 'binary' } // 这里的数据是用来定义导出的格式类型
)
),
],
{
type: '',
}
);
// 定制化改动地方
this.saveAs(tmpDown, ${'记录模板' + '.'}${type.bookType == 'biff2' ? 'xls' : type.bookType});
}

这边也是借鉴了百度的大佬,合并单元格可以生效的,不过样式的修改并没有生效,有需要的可以自己研究下。

excel导入

我选择的是原始的input type=file 来实现文件的上传解析,因为初始的这个标签效果并不是很好看,右边还默认带着一个未选择任何文件的字样,又改不掉样式,这边我用了个小技巧分享出来:
原理:input的样式设置display: none 用过div绝对定位在这儿,取原始input的id 并添加点击事件,从而实现点击div实现文件上传
html部分代码:

    <Col span={20} className={style.btnSpec}>
    <input
      type='file' accept='.xlsx, .xls' onChange={this.excelImport} style={{ height: '30px', lineHeight: '26px', display: 'none' }} id="batchUpload" />
      <div onClick={this.centerUploadBox} className={style.centerUploadBox}>
        文件上传
      </div>
    </Col>

js部分代码:

// div按钮实现上传
centerUploadBox = () => {
var me = this;
let batchUpload = document.querySelector('#batchUpload');
batchUpload.click();
let filesList = document.querySelector('#batchUpload').files;
batchUpload.addEventListener('change', function () {
filesList = document.querySelector('#batchUpload').files;
if (filesList.length == 0) {
return;
}
})
}
//导入excel
dataImport = file => {
const { dispatch } = this.props
// 获取上传的文件对象
const { files } = file.target;
// 通过FileReader对象读取文件
const fileReader = new FileReader();
fileReader.onload = event => {
// try {
const { result } = event.target;
// 以二进制流方式读取得到整份excel表格对象
const workbook = XLSX.read(result, { type: 'binary' });
// 存储获取到的数据
let params = []
let listRow = []; // 多少列的数组
let maxHeight = 0;
let indexK = 0

  console.log(workbook)
  let oriData = workbook.Sheets.mySheet;
  // 这边就是读取了excel的所有内容
  let excelFilterData = []

  for (let k in oriData) {
    ++indexK
    if (indexK == 1) {
      maxHeight = oriData[k].substring(oriData[k].lastIndexOf(":") + 2)
    } else {
      listRow.push(k.substring(0, 1))
    }

  }

  listRow = Array.from(new Set(listRow))
  listRow.splice(listRow.length - 1, 1)

  // 字母排序
  listRow = listRow.sort((s, t) => {
    let a = s.toLowerCase();
    let b = t.toLowerCase();
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
  })
  //找到最大列 eg.9
  //找到最大行 eg.39
  //这边主要是处理后台需要的数据
  for (let i = 2; i <= listRow.length - 1; i++) {
    //循环行
    if (oriData[listRow[i] + '3']) {
      if (oriData[listRow[i] + '3'].h) {
        excelFilterData.push(oriData[listRow[i] + '3'].h)
      } else if (oriData[listRow[i] + '3'].v) {
        excelFilterData.push(this.formatDate(oriData[listRow[i] + '3'].v, '-'))
      }
    }


    for (let j = 6; j <= Number(maxHeight); j++) {
      let reg = /^[0-9,.]*$/, item = {}

      if (oriData[listRow[i] + j] && oriData[listRow[i] + j].h && reg.test(oriData[listRow[i] + j].h)) {
        item = {
          calculationElevation: oriData[listRow[i] + j] ? oriData[listRow[i] + j].h : "",
          constructionMonitorPoint: {
            monitorPointNumber: oriData[`B${j}`] ? oriData[`B${j}`].h : "",
          },
          constructionMonitorTask: {
            taskName: oriData[`A${j}`] ? oriData[`A${j}`].h : "",
          },
          constructionMonitorTaskCollection: {
            checkTime: oriData[listRow[i] + '3'] ? oriData[listRow[i] + '3'].h ? oriData[listRow[i] + '3'].h : this.formatDate(oriData[listRow[i] + '3'].v, '-') : "",
            constructCondition: oriData[listRow[i] + '4'] ? oriData[listRow[i] + '4'].h : "",
          }
        }
        params.push(item)
      }
    }
  }
  this.setState({ excelFilterData: excelFilterData })
  console.log(params)
  this.setState({ filterVisible: true, excelParams: params })


};
// 以二进制方式打开文件
fileReader.readAsBinaryString(files[0]);

}

div按钮的样式:

.centerUploadBox {
margin-top: 8px;
height: 30px;
line-height: 26px;
width: 89px;
float: right;
margin-right: 623px;
cursor: pointer;
background: #fafafa;
padding: 0 10px;
padding-top: 1px;
font-size: 16px;
border-radius: 0px;
color: #000000e6;
border: solid 1px #000;
border-color: rgba(0, 0, 0, 0.31);
}

file
按钮就是这样的 哈哈哈哈哈哈 也不是很好看 根据需求和页面布局自行画吧 ~
以上就是纯前端实现excel导出和导入!!! 不足之处就是设置样式没有生效 ,导入的时候不能做到识别合并单元格,所以说很复杂或者规定样式的excel可能还得后台画,也有很大可能我是不会的-_-zzzzzzzz~

原文来自:https://blog.csdn.net/qq_37642495/article/details/109327705?utm_medium=distribute.pc_category.none-task-blog-hot-3.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-3.nonecase

Image placeholder
topYlian
未设置
  0人点赞

没有讨论,发表一下自己的看法吧

推荐文章
视频流媒体服务器对接宇视摄像机OCX插件出现error code 14001错误分析

背景需求随着雪亮工程、明厨亮灶、手机看店、智慧幼儿园监控等行业开始将传统的安防摄像头进行互联网、微信直播,我们知道摄像头直播的春天了。将安防摄像头或NVR上的视频流转成互联网直播常用的RTMP、HTT

怎么新建一个react项目

怎么新建一个react项目现在比较流行和常用的方式就是利用create-react-app脚手架来帮我们搭建一个初始的react项目,准备工作安装node环境,这个去百度搜索下node安装,在命令行中

如何运行一个react项目?

React起源于Facebook的内部项目,因为该公司对市场上所有JavaScriptMVC框架,都不满意,就决定自己写一套,用来架设Instagram的网站。做出来以后,发现这套东西很好用,就在20

怎么从0搭建react项目

怎么从0搭建react项目一、浏览器中通过标签直接引入React框架有两个核心的包,分别是react以及react-dom,如何想直接在浏览器中使用React,那么把这两个包直接引入就可以了。 如

怎么编译react项目

怎么编译react项目使用create-react-app脚手架搭建的react项目,只需要使用npmrunbuild命令就可以编译项目了,代码会被编译到build目录中。一、create-react

如何快速新建react项目?

创建一个react项目有三种方式:1.create-react-app快速脚手架(简单,类似于vue-cli工具)2.webpack一步一步构建3.第三方脚手架(generator-react-web

如何用vscode启动react项目

如何用vscode启动react项目要求:●具有nodejs环境、已安装npm●已安装vscode首先使用create-react-app脚手架创建一个项目。create-react-appdemo1

如何运行别人的react项目

如何运行别人的react项目1、从网上下载项目到本地,放在自己的工作空间中2、下载好的项目缺少项目依赖环境,我们需要自己安装。npminstall这个步骤将会新建该项目的node_modules文件夹

如何新建react项目

如何新建react项目前文中,我们介绍过了2种react项目的搭建方式,分别是webpack的方式搭建和create-react-app脚手架的方式搭建感兴趣的同学可以点击下方链接,进行学习。webp

如何启动react项目

如何启动react项目1、首先打开命令提示符工具开始——菜单——运行——cmd2、然后使用cd命令进入项目目录cdmy-app3、接着运行npmstart即可注:如果项目目录中没有node_modul

如何将react项目部署到服务器

如何将react项目部署到服务器前提要求:●nodejs环境●一个react项目●一个服务器(本地也行)1、首先打开项目目录,按下shift+右键,打开命令提示符,输入打包命令npmrunbuild2

如何访问已启动的react项目

如何访问已启动的react项目1、运行react项目都会开启一个终端窗口,只需要打开窗口,查看项目的运行地址即可。上面这个项目的地址是http://localhost:3000/,打开浏览器输入这个地

如何查看react项目端口?

如何查看react项目端口?react项目端口默认是3000,定义在node_modules\react-scripts\bin\react-scripts.js文件中,可以通过文本编辑器打开它,搜索

Jenkins export and import jobs 迁移导出导入任务实践小结

前言我遇到的Jenkins迁移项目并非可以通过简单的物理文件复制就可以轻松解决,需要考虑上千个不同项目的jobs分离,Jenkins1.x和2.x大版本兼容性,JenkinsPlugins插件,Jen

maatwebsite/Excel 3.1 使用教程 (导入篇)

maatwebsite/excel使用教程(导入篇) 官方文档 https://docs.laravel-excel.com/3.1/getting... GIT地址 https://github.c

Stack Overflow 上最火的一个问题:什么是 NullPointerException

在逛StackOverflow的时候,发现最火的问题竟然是:什么是NullPointerException(java.lang.NullPointerException),它是由什么原因导致的,有没有

PHP 高性能 Excel 扩展 1.2.7 发布

为什么使用php-ext-excel-export xlswriter是一个PHPC扩展,可用于在Excel2007+XLSX文件中写入多个工作表的文本,数字,公式和超链接。 它支持以下功能: 100

秒读 Excel 百万数据(第一篇)

读取前的准备工作 1.文件类型属于.xls、.xlsx,需要用办公软件WPS或Office将文件另存为.csv类型。不能直接重命名修改文件类型,直接重命名修改文件类型会导致数据格式不兼容,Window

xlsxwriter 操作 Excel

xlsxwriter简介 用于以Excel2007+XLSX文件格式编写文件 优点 文本,数字和公式写入,速度很快,占用内存小 支持诸如格式设置,图像,图表,页面设置,自动过滤器,条件格式设置等功能

xlsxwriter 操作 Excel

xlsxwriter简介用于以Excel2007+XLSX文件格式编写文件,相较之下PhpSpreadsheet支持更多的格式读写。优点文本,数字和公式写入,速度很快,占用内存小 支持诸如格式设置,图

Onvif/RTSP海康大华网络安防摄像机网页无插件直播方案EasyNVR如何使用Excel将通道配置简单化?

进入移动互联网时代以来,企业微信公众号已成为除官网以外非常重要的宣传渠道,当3.2亿直播用户与9亿微信用户的势能累加,在微信上开启直播已成为越来越多企业的必然选择。EasyNVR核心在于摄像机的音视频

Excel中怎么把文本格式变为数值?

课程推荐:web全栈开发就业班--拿到offer再缴学费--融职教育 很多时候在Excel表中,表中的数据是文本格式的,文本格式是不能使用公式的,只能是数值格式的才能使用公式,那么,我们怎样把文本格式

Python中的openpyxl如何对excel修改文件

推荐课程:Python开发工程师--学习猿地--送9个上线商业项目 Python安装openpyxl 首先我们应该配置pip详细配置教程地址:https://blog.csdn.net/hanhanw

eclipse如何导入vue项目?

eclipse导入vue项目的方法1、首先,我们需要去导入的项目根目录下看一下,是否包含.project和.classpath文件,我这里是没有这两个文件的。这里要注意显示文件夹下的隐藏文件。2、由于

前端react是什么?

前端react是什么?前端react指的是reactjs,是Facebook推出的一个用来构建用户界面的JavaScript库。React主要用于构建UI,很多人认为React是MVC中的V(视图)。