import XLSX from "xlsx"; import ajax from '@/utils/ajax' import { Message } from 'element-ui'; const excelHeaderName = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; /** * excel导出默认选项 */ const exportOptionDefault = { url: "",//*必填,导出请求地址 tableRef: undefined,//#1组合必填 导出数据对应列信息,el-table引用 columnMapping: undefined,//#1组合必填 自定义导出列映射 fileName: "export.xlsx",//导出文件名 params: {},//导出请求参数 rowFetcher: res => {//从请求结果中获取导出行的方式,默认取请求结果中的data作为导出数据 return (res || {data: []}).data; }, columnFormatter: [],//需要格式化的列 mergeSetting: { refs: [], //检测需要合并的数据列属性名 columns: [] //检测需要合并后,要合并的列,以第一条数据为准合并 }, dropColumns: [],//导出时需要过滤掉的列 }; let HEADERS = []; for (let i =0;i< 200;i++) { let c = parseInt(i / 26); let m = i % 26; HEADERS.push((c > 0 ? excelHeaderName[c - 1] : "") + excelHeaderName[m]); } let validOption = opt => { let option = Object.assign({}, opt); if (!option.url) { throw new Error("request url is required."); } if (!option.tableRef && !option.columnMapping) { throw new Error("element table ref object or columnMapping is required."); } if (option.rowFetcher != undefined && typeof option.rowFetcher != "function") { throw new Error("rowFetcher must be a function with one param."); } } let getMergeSetting = (data, s, allCols) => { let refCols = s.refs; let mcols = s.columns; let mergeList = []; let refRow = data[0]; let mergeSetting = { s: 0, e: 0 }; for (let i = 0; i < data.length; i++) { let same = refCols.map(c => data[i][c] === refRow[c]).filter(r => !!r).length == refCols.length; if (!same) { mergeSetting.e > mergeSetting.s && (mergeList.push(mergeSetting)); refRow = data[i]; mergeSetting = { s: i, e: i }; } else { i > mergeSetting.e && (mergeSetting.e = i); i == data.length - 1 && (mergeList.push(mergeSetting)); } } let setting = []; mergeList.forEach(e => { mcols.forEach(c => { let ci = allCols.indexOf(c); setting.push({ s: { r: e.s + 1, c: ci }, e: { r: e.e + 1, c: ci } }); }); }); return setting; } let setStyle = (ws, s) => {} let getColSetting = (mapping,dropColums) => { let columns = []; for (let i = 0; i < mapping.length; i++) { let c = mapping[i]; if (dropColums.indexOf(c.columnProp) == -1) { columns.push({ property: c.columnProp || c.property, label: c.columnLabel, type: "default" }); } } return { columns: columns }; } let export2Excel = opt => { validOption(opt); let options = Object.assign({}, exportOptionDefault, opt); let expColSetting = !!options.tableRef ? options.tableRef : getColSetting(options.columnMapping, options.dropColumns); ajax.$post(options.url, options.params, resp => { if (resp.status !== 200) { Message.error({ message: resp.description }); } let rows = !!resp.data.rows?options.rowFetcher(resp).rows:resp.data.page.list; var columns = [ [] ]; var keys = []; let formaters = new Array(); expColSetting.columns.forEach(column => { if (!!column.label && column.type === "default") { columns[0].push(column.label); keys.push(column.property); let formater = options.columnFormatter.find(f => !!f[column.property] && typeof f[column.property] == 'function'); !!formater && (formaters[column.property] = formater[column.property]); } }); rows.forEach(o => { let list = []; keys.forEach(k => { let formater = formaters[k]; if (!!formater) { list.push(formater(o[k])); } else { list.push(o[k]); } }); columns.push(list); }); const ws = XLSX.utils.aoa_to_sheet(columns); if (!!options.mergeSetting && !!options.mergeSetting.refs && options.mergeSetting.refs.length > 0) { let merges = getMergeSetting(rows, options.mergeSetting, keys); ws["!merges"] = merges; setStyle(ws, merges); } // console.log(ws); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, options.fileName.replace(/\.xlsx/, "")); XLSX.writeFile(wb, options.fileName); }); } export default { exportTable: export2Excel }