javascript实现前端表格内容导出

import {deepClone} from 'lodash'

// 配置文件类型
const wopts = {
	bookType: 'xlsx',
	bookSST: true,
	type: 'binary',
	cellStyles: true
};

const minColWidth = 8
const borderStyle = {
	top: {
		style: 'thin'
	},
	bottom: {
		style: 'thin'
	},
	left: {
		style: 'thin'
	},
	right: {
		style: 'thin'
	}
}

export function exportExcel(table, fileName) {
	console.log(table)
	fileName = (fileName || '数据列表') + '_' + moment().format('YYYY-MM-DD')
	// 如果勾选,只导出勾选的数据,否则导出全部数据
	let data = deepClone(table.selection.length ? table.selection : table.data)
	data.unshift({});
	let cols = [] // 列属性
	table.columns.forEach(col => {
		let field = col.property
		if (field) {
			cols.push({
				field: field,
				align: col.align ? col.align.split('-')[1] : 'left',
				formatter: col.formatter
			})
			data[0][field] = col.label
		} else {
			// 补充序号列
			if (col.label === '序号') {
				field = 'index'
				cols.push({
					field: field,
				})
				data[0][field] = col.label
			}
		}
	})
	// 补充序号数据
	data.forEach((item, i) => {
		if (i > 0) {
			item['index'] = i
		}
	})
	// 设置列宽
	let wchs = []
	cols.forEach((col, i) => {
		let field = col.field
		wchs[i] = {
			wch: minColWidth
		}
		data.forEach((item, j) => {
			// 处理"."连接的属性
			if (field.indexOf('.') !== -1) {
				try {
					item[field] = eval('item["' + field.split('.').join('"]["') + '"]')
				} catch (err) {}
			}
			// 设置为空字符串
			item[field] = (item[field] === undefined || item[field] === null) ? '' : item[field]
			if (col.formatter !== undefined && j > 0) {
				// 页面设置了formatter函数
				item[field] = col.formatter(item, col, item[field])
			}
			wchs[i].wch = Math.max(wchs[i].wch, getWch(item[field]))
			// 设置单元格样式
			if (j === 0) {
				// 表头
				item[field + '_s'] = {
					border: borderStyle,
					font: {
						sz: 13,
						bold: true
					},
					alignment: {
						vertical: 'center',
						horizontal: 'center'
					},
					fill: {
						bgColor: {
							indexed: 64
						},
						fgColor: {
							rgb: 'FFD9D9D9'
						}
					}
				}
			} else {
				// 数据
				item[field + '_s'] = {
					border: borderStyle,
					alignment: {
						vertical: 'center',
						horizontal: col.align
					},
				}
			}
		})
	})

	var tmpdata = []; //用来保存转换好的json
	data.map((v, i) => cols.map((col, j) => Object.assign({}, {
		v: v[col.field],
		v_s: v[col.field + '_s'],// 存放样式
		position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
	}))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {
		v: v.v,
		s: v.v_s
	});
	var outputPos = Object.keys(tmpdata); //设置区域,比如表格从A1到D10
	// 设置样式
	// tmpdata["B1"].s = {
	// 	font: {
	// 		sz: 14,
	// 		bold: true,
	// 		color: {
	// 			rgb: "FFAA00"
	// 		}
	// 	},
	// 	fill: {
	// 		bgColor: {
	// 			indexed: 64
	// 		},
	// 		fgColor: {
	// 			rgb: "FFFF00"
	// 		}
	// 	}
	// }

	// 合并单元格
	/* tmpdata["!merges"] = [{
		s: {
			c: 1,
			r: 0
		},
		e: {
			c: 4,
			r: 0
		}
	}] */
	var tmpWB = {
		SheetNames: ['数据清单'], //保存的表标题
		Sheets: {
			'数据清单': Object.assign({},
				tmpdata, //内容
				{
					'!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1], //设置填充区域
					'!cols': wchs
				})
		}
	};
	var tmpDown = new Blob([s2ab(XLSX.write(tmpWB, {
			bookType: 'xlsx',
			bookSST: false,
			type: 'binary'
		} //这里的数据是用来定义导出的格式类型
	))], {
		type: ""
	});
	saveAs(tmpDown, fileName + '.' + (wopts.bookType == "biff2" ? "xls" : wopts.bookType));
}

function getWch(val) {
	if (val == null) {
		return minColWidth
	} else if (val.toString().charCodeAt(0) > 255) {
		// 中文
		return val.toString().length * 2 + 1
	} else {
		return val.toString().length
	}
}

// 下载功能
function saveAs(obj, fileName) {
	var tmpa = document.createElement("a");
	tmpa.download = fileName || "未命名";
	// 兼容ie
	if ("msSaveOrOpenBlob" in navigator) {
		window.navigator.msSaveOrOpenBlob(obj, fileName + ".xlsx");
	} else {
		tmpa.href = URL.createObjectURL(obj);
	}
	tmpa.click();
	setTimeout(function() {
		URL.revokeObjectURL(obj);
	}, 100);
}

// 获取26个英文字母用来表示excel的列
function getCharCol(n) {
	let temCol = '',
		s = '',
		m = 0
	while (n > 0) {
		m = n % 26 + 1
		s = String.fromCharCode(m + 64) + s
		n = (n - m) / 26
	}
	return s
}

function s2ab(s) {
	if (typeof ArrayBuffer !== 'undefined') {
		var buf = new ArrayBuffer(s.length);
		var view = new Uint8Array(buf);
		for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
		return buf;
	} else {
		var buf = new Array(s.length);
		for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
		return buf;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值