1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 纯前端js(或者vue)导出excel实现:合并单元格 设置单元格样式 单元格内换行

纯前端js(或者vue)导出excel实现:合并单元格 设置单元格样式 单元格内换行

时间:2021-01-06 08:21:01

相关推荐

纯前端js(或者vue)导出excel实现:合并单元格 设置单元格样式 单元格内换行

前提是安装xlsx,已经可以导出普通的excel

npm install --save xlsx file-saver

然后需要安装

npm install xlsx-style

如果运行的时候报错

需要修改源码,然后重新运行:

1、在\node_modules\xlsx-style\dist\cpexcel.js 807行把 var cpt = require('./cpt' + 'able'); 改成 var cpt = cptable;2、在\node_modules\xlsx-style\ods.js 10行和13行把路径改为 require('./xlsx')

Blob.js 和Export2Excel.js 网上有很多

我在Export2Excel中做了修改,代码如下:

//Export2Excel.js

require('script-loader!file-saver');require('./Blob.js');//这里是你的Blob.js的地址require('script-loader!xlsx/dist/xlsx.core.min');import XLSXS from "xlsx-style"必须要引入才可以,否则报错

export function export_json_to_excelhb({multiHeader2 = [], // 第一行表头multiHeader = [], // 第二行表头header, // 第三行表头data,//传递的数据filename, //文件名merges = [], // 合并autoWidth = true,//用于设置列宽的bookType = 'xlsx'} = {}) {/* original data */filename = filename || '列表';data = [...data]data.unshift(header);for (let i = multiHeader2.length - 1; i > -1; i--) {data.unshift(multiHeader2[i])}for (let i = multiHeader.length - 1; i > -1; i--) {data.unshift(multiHeader[i])}var ws_name = "SheetJS";var wb = new Workbook(),ws = sheet_from_array_of_arrays(data);let borderAll = { //单元格外侧框线top: {style: 'medium',},bottom: {style: 'medium'},left: {style: 'medium'},right: {style: 'medium'}};for (let key in ws) {if (ws[key] instanceof Object) {ws[key].s = {border: borderAll,alignment: {horizontal: 'center', //水平居中对齐vertical: 'center',//垂直居中wrapText: 1,//自动换行},font: {sz: 10,//单元格中字体的样式与颜色设置color: {rgb: '495060'}},bold: true,numFmt: 0}}}ws['I2'] = ws['H2'] = ws['G2'] = ws['F2'] = ws['E2'] = ws['D2'] = ws['C2'] = ws['B2'] = ws['A2']//用于第二行的单元格的样式设置(如果是合并的第一行,就是1)if (merges.length > 0) {if (!ws['!merges']) ws['!merges'] = [];merges.forEach(item => {ws['!merges'].push(XLSX.utils.decode_range(item))})}if (autoWidth) {let colWidths = [];// 计算每一列的所有单元格宽度// 先遍历行data.forEach((row) => {// 列序号let index = 0// 遍历列for (const key in row) {if (colWidths[index] == null) colWidths[index] = []switch (typeof row[key]) {case 'string':case 'number':case 'boolean': colWidths[index].push(getCellWidth(row[key]))breakcase 'object':case 'function':colWidths[index].push(0)break}index++}})ws['!cols'] = [];colWidths.forEach((widths, index) => {// 计算列头的宽度widths.push(getCellWidth(header[index]))// 设置最大值为列宽ws['!cols'].push({wch: Math.max(...widths)})})}console.log(ws);/* add worksheet to workbook */wb.SheetNames.push(ws_name);wb.Sheets[ws_name] = ws;var wbout = XLSXS.write(wb, {bookType: bookType,bookSST: false,type: 'binary'});saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), `${filename}.${bookType}`);}export function getCellWidth(value) {if (value == null) {return 10} else if (value.toString().charCodeAt(0) > 255) {// 判断是否包含中文let length = value.toString().length * 2if (length > 60) {length = length - 40 //这里的宽度可以自己设定,在前面设置wrapText: 1可以在单元格内换行}return length} else {return value.toString().length * 1.2}}

在自己的文件中调用

数据的格式,比如:

data=[{mc:"aaa",sex:'女'},{mc:"bbb",sex:'男'}]

tHeader=["名称","性别"]

filterVal=["mc","sex"]

handleExportexcel() {//@/excel/Export2Excel是自己的Export2Excel的文件的地址import("@/excel/Export2Excel").then((excel) => {const multiHeader = [["光缆熔接纤序表"]];const multiHeader2 = [["设备名称"];const tHeader = [];const filterVal = []; // 表头所对应的字段,这里未填写,请自行填写对应的字段,按实际需求请自行处理该步let data = rjdata.map((v) => filterVal.map((j) => v[j])); //rjdata为请求的数据,此处理是为了对应字段,如不需要此处理,直接为data赋值即可// 进行所有表头的单元格合并let merges = ["A1:I1","A2:I2", //合并行"A4:A6","B4:B6",];//如果是A1到I1合并就写A1:I1let excelname = String(new Date().format("yyyy-MM-dd-HH-mm-ss")).replace(/[^0-9]/gi, "");//导出的excel的名字excel.export_json_to_excelhb({multiHeader, // 这里是第一行的表头multiHeader2, // 这里是第二行的表头header: tHeader, // 这里是第三行的表头data,filename: excelname,merges,});});},},

最终的实现结果如下图

参考了下面两个大佬的文章,我的需求比他们的复杂一点。

参考链接:JavaScript导出excel文件,并修改文件样式_FEWY的博客-CSDN博客_js导出excel设置样式

Vue 前端导出Excel表格,多级表头合并_迈向前端攻城狮的路上-CSDN博客_vue导出excel表格合并单元格

xlsx-style ./cptable' 报错解决办法 - 龙果果 - 博客园

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。