xlsx-style-downloadt
Version:
xlsx-style-plugin
342 lines (320 loc) • 10.6 kB
JavaScript
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;
// }
// }
// }