因为我的项目中有需要要展现excel(内容只有一些简略的地址/地区等信息,没有简单的款式,只是蕴含了一些合并的表格),所以利用XLSX的读写性能,对读取后的数据进行二次解决并展现。
成果截图在最下边
先上代码(间接从我的项目中摘抄出一部分,并附上了正文):
//过后我的项目用的是vue,为了省事只将有用的局部筛选了进去<template> <div class="about"> <button @click="createBook">生成excel</button> <br> <input type="file" id="inputFile" @change="fileChange"> <table id="tableView" style="min-width: 100%; border-collapse:collapse; border: 1px solid;"> <tr v-for="(item, index) in dataSource" :key="index" style="height: 28px;"> <template v-for="(sub, subIndex) in item" :key="subIndex"> <td v-if="sub.rowspan !== 0 && sub.colspan !== 0" :rowspan="sub.rowspan || 1" :colspan="sub.colspan || 1" style="width: auto; min-width: 120px; padding: 3px 5px; border: 1px solid;"> {{sub.name}} </td> </template> </tr> </table> </div></template><script> import {axios} from '@/utils/request' const XLSX = require('@/utils/xlsx.full.min') export default { data() { return { dataSource: [], } }, methods: { //获取本地文件 fileChange() { let files = document.getElementById('inputFile').files this.fileReader(files[0]) }, // //获取网络文件 // getNetworkFile(url) { // axios({ // url, //文件地址 // method: 'get', // responseType: 'blob' // }).then(blobData => { // console.log(blobData) // //将blob转为file类型 // let file = new File([blobData], '样例', {type: blobData.type}) // this.fileReader(file) // }) // }, fileReader(file) { let reader = new FileReader() //读入file reader.readAsBinaryString(file) reader.onload = e => { let data = e.target.result //读取file, 提取数据 let workbook = XLSX.read(data, {type: 'binary', cellStyles: true}) console.log(workbook) // workbook.SheetNames 是工作表名称的有序列表 // workbook.Sheets 是一个对象,其键是工作表名称,其值是工作表对象 this.sheetNames = workbook.SheetNames this.sheets = workbook.Sheets //默认显示第一个sheet this.parsingTable(this.sheets[this.sheetNames[0]]) } }, //对数据进行解决,实现表格合并展现的性能 parsingTable(table) { let header = [] //表格列 let keys = Object.keys(table) let maxRowIndex = 0 //最大行数 //!ref工作表范畴 if (table['!ref'] && table['!ref'].includes(':')) { let refs = table['!ref'].split(':') maxRowIndex = refs[1].replace(/[A-Z]/g, '') } for (let [i, h] of keys.entries()) { //提取key中的英文字母 let col = h.replace(/[^A-Z]/g, '') //单元格是以A-1的模式展现的,所以排除蕴含!的key h.indexOf('!') === -1 && header.indexOf(col) === -1 && header.push(col) //如果!ref不存在时, 设置某一列最初一个单元格的索引为最大行数 if ((!table['!ref'] || !table['!ref'].includes(':')) && header.some(c => table[`${c}${i}`])) { maxRowIndex = i > maxRowIndex ? i : maxRowIndex } } header = header.sort((a, b) => a.localeCompare(b)) //按字母程序排序 [A, B, ..., E, F] // console.log(header) // console.log(maxRowIndex) let dataSource = [] //表格数据 //excel的行示意为 1, 2, 3, ......, 所以index起始为1 for (let index = 1; index <= maxRowIndex; index++) { let row = [] //行 //每行的单元格汇合, 例: [A1, ..., F1] row = header.map(item => { let key = `${item}${index}` let cell = table[key] return { key, name: cell ? cell.v : '', // style: cell ? cell.s : '', //单元格的款式/主题, 有些不实用 } }) dataSource.push(row) } //合并单元格 if (table['!merges']) { for (let item of table['!merges']) { //s开始 e完结 c列 r行 (行、列的索引都是从0开始的) for (let r = item.s.r; r <= item.e.r; r++) { for (let c = item.s.c; c <= item.e.c; c++) { // console.log('=======', r, c) //查找单元格时须要r+1 //例:单元格A1的地位是{c: 0, r:0} let rowIndex = r + 1 if (!dataSource[r]) { dataSource.splice(r, 0, header.map(col => ({key: `${col}${rowIndex}`}))) } let cell = dataSource[r].find(a => a.key === `${header[c]}${rowIndex}`) cell.rowspan = 0 cell.colspan = 0 } } //合并时保留范畴内左上角的单元格 let start = `${header[item.s.c]}${item.s.r + 1}` // let end = `${header[item.e.c]}${item.e.r + 1}` // console.log(start) let cell = dataSource[item.s.r].find(a => a.key === start) cell.rowspan = item.s.r !== item.e.r ? item.e.r - item.s.r + 1 : 1 //纵向合并 cell.colspan = item.s.c !== item.e.c ? item.e.c - item.s.c + 1 : 1 //横向合并 } } console.log(dataSource) this.dataSource = dataSource }, createBook() { //应用table_to_sheet或table_to_book其中一种办法 //table_to_sheet的用法 let worksheet = XLSX.utils.table_to_sheet(document.getElementById('tableView')) let workbook = { SheetNames: [], Sheets: {} } workbook.SheetNames.push('sheet1') worksheet['!cols'] = [{wch: 20}] //设置第一列的列宽 workbook.Sheets['sheet1'] = worksheet //table_to_book的用法 // let workbook = XLSX.utils.table_to_book(document.getElementById('tableView')); let data = XLSX.write(workbook, { bookType: 'xlsx', // 要生成的文件类型 type: 'array' }) let blobData = new Blob([data], {type: 'application/octet-stream'}) this.downFile(blobData) }, downFile(blobData) { if (typeof window.navigator.msSaveBlob !== 'undefined') { window.navigator.msSaveBlob(new Blob([blobData]), new Date().getTime() + '.xlsx') } else { let url = window.URL.createObjectURL(new Blob([blobData])) let link = document.createElement('a') link.style.display = 'none' link.href = url link.setAttribute('download', new Date().getTime() + '.xlsx') document.body.appendChild(link) link.click() document.body.removeChild(link) window.URL.revokeObjectURL(url) } } }, }</script>
本地文件(款式是我本人加的,读取或写入款式须要将cellStyles设置为true):
页面渲染的table(只实现了表格合并,没有对其余款式进行解决):
导出后的文件: