UNPKG

xlsx-style-downloadt

Version:

xlsx-style-plugin

342 lines (320 loc) 10.6 kB
import _ from 'lodash'; import XLSX from 'xlsx'; // import XLSXStyle from 'xlsx-style' import XLSXStyle from './xlsx-style' const COL_PARAMS = ['hidden', 'wpx', 'width', 'wch', 'MDW'] const STYLE_PARAMS = ['fill', 'font', 'alignment', 'border'] const cellColumn = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'] function XlsxDownload({columns, data, header, headerStyle, filename, cellStyle={}, lineStyle = [], rowHeight = 27}) { // 列的映射 this.columns = columns || {}; // 行高 this.rowHeight = rowHeight || 27 // 数据源 this.data = data || []; // 头部 this.header = header; // 头部样式 this.headerStyle = headerStyle || {} // 文件名 this.filename = filename || '工作簿' // 过滤要导出的数据 this.initData() // 其他行的样式 this.lineStyle = lineStyle // 单元格样式 this.cellStyle = cellStyle } XlsxDownload.prototype.initData = function() { // 获取键值 this.keys = _.keys(this.columns); // 过滤数据 this.data = this.data.map(item => { return _.pick(item, this.keys); }) } XlsxDownload.prototype.createExcelBook = function() { // 获取列中文名名称(列头) let colNames = _.mapValues(this.columns, o => { if (_.isPlainObject(o)) { return o.name; } else { return o; } }); let cellStyleMap = this.cellStyleMake() // 创建工作簿 let workbook = XLSX.utils.book_new(); // 添加表头 let worksheet = XLSX.utils.json_to_sheet([ colNames ], { header: this.keys, skipHeader: true }); // 追加数据 XLSX.utils.sheet_add_json(worksheet, this.data, { header: this.keys, skipHeader: true, origin: 'A2' }); // 设置样式 for (const key in worksheet) { // 第一行,表头 if (key.replace(/[^0-9]/ig, '') === '1') { worksheet[key].s = this.headerStyle; } else { let lineNo = key.replace(/[^0-9]/ig, ''); let selfLine = this.lineStyle.find(line => { return line.no == lineNo }) if(selfLine) { worksheet[key].s = selfLine.style } else { let str = key.replace(/[^A-Za-z]+$/ig, '') let colIndex = this.stringToNum(str) - 1; if (this.keys[colIndex] && _.isPlainObject(this.columns[this.keys[colIndex]])) { const a = _.pick(this.columns[this.keys[colIndex]], STYLE_PARAMS); if(cellStyleMap[key]) { worksheet[key].s = _.assign(worksheet[key].s, cellStyleMap[key]); } else { worksheet[key].s = _.assign(worksheet[key].s, a); } } } } } // 设置列宽 const colsP = [] _.mapValues(this.columns, o => { colsP.push(_.pick(o, COL_PARAMS)) }) worksheet['!cols'] = colsP; worksheet['!rows'] = Array.from({length:this.data.length + 1}, (v,k) => k).map(item => { return { hpx: this.rowHeight } }); // worksheet['!pageSetup'] = {scale: '100', orientation: 'portrait'} workbook.SheetNames.push('sheet1'); workbook.Sheets['sheet1'] = worksheet; return workbook; } XlsxDownload.prototype.cellStyleMake = function() { let cellMap = {} Object.keys(this.cellStyle).forEach(key => { let index = this.keys.indexOf(key) this.cellStyle[key].line.forEach(item => { if(index > -1) { let cellKey = cellColumn[index] + item.no; cellMap[cellKey] = this.cellStyle[key].style } }) }) return cellMap } XlsxDownload.prototype.download = function() { const workbook = this.createExcelBook(); const downloadObject = new Blob([this.changeData(XLSXStyle.write(workbook, { bookType: 'xlsx', bookSST: false, type: 'binary' }))], {type: 'application/octet-stream'}); var tmpa = document.createElement("a"); tmpa.download = `${this.filename}.xlsx`; tmpa.href = URL.createObjectURL(downloadObject); tmpa.click(); } XlsxDownload.prototype.stringToNum = function(str) { let temp = str.toLowerCase().split('') let len = temp.length let getCharNumber = function(charx) { return charx.charCodeAt() - 96 } let numout = 0 let charnum = 0 for (let i = 0; i < len; i++) { charnum = getCharNumber(temp[i]) numout += charnum * Math.pow(26, len - i - 1) } return numout } XlsxDownload.prototype.changeData = function(s) { //1、创建一个字节长度为s.length的内存区域 let buf = new ArrayBuffer(s.length); //如果存在ArrayBuffer对象(es6) 最好采用该对象 if (typeof ArrayBuffer !== 'undefined') { //2、创建一个指向buf的Unit8视图,开始于字节0,直到缓冲区的末尾 var view = new Uint8Array(buf); //3、返回指定位置的字符的Unicode编码 for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; return buf; } else { for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF; return buf; } } window.XlsxDownload = XlsxDownload window.XlsxDownload.bind(XlsxDownload) export default XlsxDownload // export default class XlsxDownload { // /** 列的映射关系 */ // columns = null; // /** 数据源 */ // data = []; // /** 头部 */ // header = null; // /** 列头键值 */ // keys = null; // /** 首行样式 */ // headerStyle = null; // /** 文件名 */ // filename = ''; // // 其他行的样式 // lineStyle = [] // // 行高 // rowHeight = 27 // // 指定单元格样式 // cellStyle = {} // constructor({columns, data, header, headerStyle, filename, cellStyle={}, lineStyle = [], rowHeight = 27}) { // // 列的映射 // this.columns = columns; // // 行高 // this.rowHeight = rowHeight // // 数据源 // this.data = data; // // 头部 // this.header = header; // // 头部样式 // this.headerStyle = headerStyle || {} // // 文件名 // this.filename = filename || '工作簿' // // 过滤要导出的数据 // this.initData() // // 其他行的样式 // this.lineStyle = lineStyle // // 单元格样式 // this.cellStyle = cellStyle // } // /** 过滤映射列中有的数据 */ // initData() { // // 获取键值 // this.keys = _.keys(this.columns); // // 过滤数据 // this.data = this.data.map(item => { // return _.pick(item, this.keys); // }) // } // /** 创建工作簿和工作表并追加表头和样式 */ // createExcelBook() { // // 获取列中文名名称(列头) // let colNames = _.mapValues(this.columns, o => { // if (_.isPlainObject(o)) { // return o.name; // } else { // return o; // } // }); // let cellStyleMap = this.cellStyleMake() // // 创建工作簿 // let workbook = XLSXStyle.utils.book_new(); // // 添加表头 // let worksheet = XLSXStyle.utils.json_to_sheet([ // colNames // ], { header: this.keys, skipHeader: true }); // // 追加数据 // XLSXStyle.utils.sheet_add_json(worksheet, this.data, { header: this.keys, skipHeader: true, origin: 'A2' }); // // 设置样式 // for (const key in worksheet) { // // 第一行,表头 // if (key.replace(/[^0-9]/ig, '') === '1') { // worksheet[key].s = this.headerStyle; // } else { // let lineNo = key.replace(/[^0-9]/ig, ''); // let selfLine = this.lineStyle.find(line => { // return line.no == lineNo // }) // if(selfLine) { // worksheet[key].s = selfLine.style // } else { // let str = key.replace(/[^A-Za-z]+$/ig, '') // let colIndex = this.stringToNum(str) - 1; // if (this.keys[colIndex] && _.isPlainObject(this.columns[this.keys[colIndex]])) { // const a = _.pick(this.columns[this.keys[colIndex]], STYLE_PARAMS); // if(cellStyleMap[key]) { // worksheet[key].s = _.assign(worksheet[key].s, cellStyleMap[key]); // } else { // worksheet[key].s = _.assign(worksheet[key].s, a); // } // } // } // } // } // // 设置列宽 // const colsP = [] // _.mapValues(this.columns, o => { // colsP.push(_.pick(o, COL_PARAMS)) // }) // worksheet['!cols'] = colsP; // worksheet['!rows'] = Array.from({length:this.data.length + 1}, (v,k) => k).map(item => { // return { // hpx: this.rowHeight // } // }); // // worksheet['!pageSetup'] = {scale: '100', orientation: 'portrait'} // workbook.SheetNames.push('sheet1'); // workbook.Sheets['sheet1'] = worksheet; // return workbook; // } // /** 处理自定义单元格样式 */ // cellStyleMake() { // let cellMap = {} // Object.keys(this.cellStyle).forEach(key => { // let index = this.keys.indexOf(key) // this.cellStyle[key].line.forEach(item => { // if(index > -1) { // let cellKey = cellColumn[index] + item.no; // cellMap[cellKey] = this.cellStyle[key].style // } // }) // }) // return cellMap // } // /** 下载表格 */ // download() { // const workbook = this.createExcelBook(); // const downloadObject = new Blob([this.changeData(XLSXStyle.write(workbook, { // bookType: 'xlsx', // bookSST: false, // type: 'binary' // }))], {type: 'application/octet-stream'}); // var tmpa = document.createElement("a"); // tmpa.download = `${this.filename}.xlsx`; // tmpa.href = URL.createObjectURL(downloadObject); // tmpa.click(); // } // /** 表头字母转成数字 */ // stringToNum(str) { // let temp = str.toLowerCase().split('') // let len = temp.length // let getCharNumber = function(charx) { // return charx.charCodeAt() - 96 // } // let numout = 0 // let charnum = 0 // for (let i = 0; i < len; i++) { // charnum = getCharNumber(temp[i]) // numout += charnum * Math.pow(26, len - i - 1) // } // return numout // } // /** 文件转码 */ // changeData(s) { // //1、创建一个字节长度为s.length的内存区域 // let buf = new ArrayBuffer(s.length); // //如果存在ArrayBuffer对象(es6) 最好采用该对象 // if (typeof ArrayBuffer !== 'undefined') { // //2、创建一个指向buf的Unit8视图,开始于字节0,直到缓冲区的末尾 // var view = new Uint8Array(buf); // //3、返回指定位置的字符的Unicode编码 // for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; // return buf; // } else { // for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF; // return buf; // } // } // }