最近有个功能需要将excel展示到html 界面里面,看是简单的一个需求也是需要费尽心思才完得成
原始数据
想要把excel 读取出来,于是使用xlsl的插件
npm i xlsx
哔哩哔哩使用介绍 https://b23.tv/KJ3PUgH
通过插件可以获取到已经分析好的数据
然后使用sheet_to_html
将数据转换为html 再使用v-html加载数据
<div v-html="rowsHtml"
class="continertable"></div>
预览效果
由于行列内容太多看起来有些乱,这效果的确不是想要的,于是想到了使用element ui 的table 来加载
于是根据这个案例开始重新组织xlsx 加载返回的数据
首先要将数据行列重新组装
dealTableData (worksheet) {
// const worksheet = workbook.Sheets[sheetNames[0]];
// 拿到这张表中表格数据的范围,
const range = utils.decode_range(worksheet['!ref']);
// console.log(worksheet['!ref']); // A1:E5
//保存数据范围数据
const row_start = range.s.r; // 表格范围,开始行的数据
const row_end = range.e.r; // 表格范围,结束行的数据
const col_start = range.s.c; // 表格范围,开始列的数据
const col_end = range.e.c; // 表格范围,结束行的数据
const tableMerge = worksheet['!merges'] || []; // 表格中进行单元格合并操作的数据
var oo = [];
var tableArr = []; // 存储所以的td 数组
var preamble = "<tr>"; // 转 html 时进行拼接
// let rows = [], row_data, i, addr, cell;
//按行对 sheet 内的数据循环
//首先读取当前对象内的所有行数据,从开始到结束
for (var R = row_start; R <= row_end; ++R) {
var innerRow = []
var innerRowJson = []
// out.push(make_html_row(ws, r, R, o));
// 读取列数据,开始到结束
省略部分................
// 组装表头
this.assemblyTableData(tableArr);
this.asseblyTableColumn(tableArr);
},
再是组装行列,增加asseblyTableColumn
方法
这里由于是多级表头,所以需要一个二维数组
// 组装一个表单类字段
asseblyTableColumn (arr) {
const firstArr = arr[0];
const secondArr = arr[1];
const thirdArr = arr[2];
const secondChildren = []
let thirdObj = {}
const thirdChildren = []
// 数组第一个为表头
const resArr = [{
label: firstArr[0]['name'],
...firstArr[0]
}];
thirdArr.forEach(e => {
let propStr = e.id.match(propRegex)
thirdChildren.push({
label: e.name,
prop: propStr[0],
...e
})
})
secondArr.forEach(e => {
let propStr = e.id.match(propRegex)
// 包含colspan为下一个表头
if (e.hasOwnProperty('colspan')) {
thirdObj = {
label: this.removeHTMLTags(e.name),
...e,
children: thirdChildren,
}
} else {
secondChildren.push({
label: e.name,
prop: propStr[0],
...e
})
}
})
secondChildren['children'] = [thirdObj];
resArr[0]['children'] = secondChildren;
this.tableHeadArr = resArr
},
再增加一个重构表单数据的方法assemblyTableData
assemblyTableData (arr) {
this.categoryCN = [];
/**
* 合并信息
* [{
* rowNum:0,
* colNum:0,
* rowspan:0,
* colspan:0,
* }]
*/
const spInfo = [];
this.resTableData = [];
// 从第三一个开始
for (let i = 3; i < arr.length; i++) {
let eachObj = {}
let rowcolObj = {}
arr[i].forEach(e => {
let propStr = e.id.match(propRegex)
eachObj[propStr[0]] = this.removeHTMLTags(e.name);
const colName = propStr[0].match(/\w$/)[0];
const rowNum = e.id.match(rowNumRegex)[0]
if (e.hasOwnProperty('rowspan') && e.hasOwnProperty('colspan')) {
spInfo.push({
rowspan: e['rowspan'],
colspan: e['colspan'],
rowNum,
colNum: colNumArr.findIndex(e => e === colName)
})
} else if (e.hasOwnProperty('rowspan')) {
spInfo.push({
rowspan: e['rowspan'],
rowNum,
colNum: colNumArr.findIndex(e => e === colName)
})
} else if (e.hasOwnProperty('colspan')) {
spInfo.push({
colspan: e['colspan'],
rowNum,
colNum: colNumArr.findIndex(e => e === colName)
})
}
})
this.resTableData.push(eachObj)
}
const categoryCN = this.categoryCN;
// 根据colNum进行分组,便于合并
spInfo.forEach(cn => {
if (categoryCN[cn.colNum]) {
categoryCN[cn.colNum].push(cn)
} else {
categoryCN[cn.colNum] = [cn];
}
})
省略部分......
},
最后效果
看起来是要好很多了,接下来就是进行行列合并的操作了
待续…