parent
3d6f0f1fe0
commit
6f19417e3d
File diff suppressed because one or more lines are too long
@ -1 +1,11 @@ |
|||||||
export {exportExcel, exportExcelByJs, json2workbook} from "./exceljs" |
import {exportExcel, json2workbook, workbook2excel} from "./exceljs" |
||||||
|
|
||||||
|
/** |
||||||
|
* @desc el-table导出excel |
||||||
|
* @param tableInstance el-table实例 |
||||||
|
*/ |
||||||
|
export function elementUiTable2excel(tableInstance) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export {exportExcel, json2workbook, workbook2excel} |
||||||
|
|||||||
@ -1,132 +0,0 @@ |
|||||||
/** |
|
||||||
* @deprecated |
|
||||||
* xlsx问题多多,转向excelJS |
|
||||||
*/ |
|
||||||
|
|
||||||
import {isEmpty} from "@/util" |
|
||||||
import {download} from "@/util/file" |
|
||||||
import {abstractExportExcel, jsonArray2rowArray, mergeExcel} from "./common" |
|
||||||
|
|
||||||
/** |
|
||||||
* @param url |
|
||||||
* @param searchForm |
|
||||||
* @param options |
|
||||||
*/ |
|
||||||
export function exportExcel(url, searchForm, options) { |
|
||||||
abstractExportExcel(url, searchForm, options, json2workbook, exportExcelByJs) |
|
||||||
} |
|
||||||
|
|
||||||
//纯前端导出excel
|
|
||||||
export function exportExcelByJs(workbook, filename) { |
|
||||||
const out = window.XLSX.write(workbook, { |
|
||||||
bookType: 'xlsx', |
|
||||||
bookSST: false, |
|
||||||
type: 'binary' |
|
||||||
}) |
|
||||||
download(new Blob([s2ab(out)], {type: "application/octet-stream"}), filename) |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param data json数组 |
|
||||||
* @param columns 列配置 |
|
||||||
* @param merge 合并配置项 |
|
||||||
* @returns |
|
||||||
*/ |
|
||||||
export function json2workbook(data, columns, merge) { |
|
||||||
const header = [] //表格头部
|
|
||||||
const propMap = {} //表头和字段名的映射表,propMap[字段名]=对应的表头的数组下标
|
|
||||||
const columnSettings = [] //列宽配置,默认20
|
|
||||||
const needMerge = [] //合并行配置,[i]=字段名
|
|
||||||
|
|
||||||
columns.forEach((col, i) => { |
|
||||||
if (!isEmpty(col.header)) header[i] = col.header |
|
||||||
if (!isEmpty(col.prop)) propMap[col.prop] = i |
|
||||||
if (col.merge) needMerge[i] = col.prop |
|
||||||
columnSettings[i] = {wch: col.width || 20} |
|
||||||
}) |
|
||||||
|
|
||||||
const headerRows = header.length > 0 ? 1 : 0 |
|
||||||
|
|
||||||
let bodyMerge = [] |
|
||||||
|
|
||||||
if (merge && needMerge.length > 0) { |
|
||||||
const {primaryKey, orderKey} = merge |
|
||||||
bodyMerge = mergeExcel(needMerge, data, primaryKey, orderKey, headerRows) |
|
||||||
} |
|
||||||
|
|
||||||
const result = jsonArray2rowArray(data, propMap) |
|
||||||
|
|
||||||
headerRows && result.unshift(header) |
|
||||||
|
|
||||||
const sheet = aoa_to_sheet(result, headerRows) |
|
||||||
sheet['!cols'] = columnSettings |
|
||||||
sheet['!merges'] = bodyMerge.map(i => window.XLSX.utils.decode_range(i)) |
|
||||||
return {SheetNames: ['Sheet1'], Sheets: {Sheet1: sheet}} |
|
||||||
} |
|
||||||
|
|
||||||
//默认的excel单元格样式
|
|
||||||
const defaultCellStyle = { |
|
||||||
font: {name: '宋体'}, |
|
||||||
alignment: { |
|
||||||
wrapText: 1,// 自动换行
|
|
||||||
horizontal: "center", |
|
||||||
vertical: "center", |
|
||||||
indent: 0 |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//默认的头部样式
|
|
||||||
const defaultHeaderStyle = { |
|
||||||
...defaultCellStyle, |
|
||||||
fill: {fgColor: {rgb: "C0C0C0"}}, |
|
||||||
font: {name: '宋体', sz: 14, bold: true}, |
|
||||||
border: {top: {style: 'thin'}, left: {style: 'thin'}, bottom: {style: 'thin'}, right: {style: 'thin'}} |
|
||||||
} |
|
||||||
|
|
||||||
function datenum(v, date1904) { |
|
||||||
if (date1904) v += 1462 |
|
||||||
const epoch = Date.parse(v) |
|
||||||
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000) |
|
||||||
} |
|
||||||
|
|
||||||
function aoa_to_sheet(data, headerRows) { |
|
||||||
const ws = {} |
|
||||||
const range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}} |
|
||||||
for (let R = 0; R !== data.length; ++R) { |
|
||||||
for (let C = 0; C !== data[R].length; ++C) { |
|
||||||
if (range.s.r > R) range.s.r = R |
|
||||||
if (range.s.c > C) range.s.c = C |
|
||||||
if (range.e.r < R) range.e.r = R |
|
||||||
if (range.e.c < C) range.e.c = C |
|
||||||
//生成cell的时候,使用默认样式
|
|
||||||
const cell = { |
|
||||||
v: data[R][C], |
|
||||||
s: R === 0 && headerRows > R ? defaultHeaderStyle : defaultCellStyle |
|
||||||
} |
|
||||||
if (cell.v == null) continue |
|
||||||
const cell_ref = window.XLSX.utils.encode_cell({c: C, r: R}) |
|
||||||
|
|
||||||
/* TEST: proper cell types and value handling */ |
|
||||||
if (typeof cell.v === 'number') cell.t = 'n' |
|
||||||
else if (typeof cell.v === 'boolean') cell.t = 'b' |
|
||||||
else if (cell.v instanceof Date) { |
|
||||||
cell.t = 'n' |
|
||||||
cell.z = window.XLSX.SSF._table[14] |
|
||||||
cell.v = datenum(cell.v) |
|
||||||
} |
|
||||||
else cell.t = 's' |
|
||||||
ws[cell_ref] = cell |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* TEST: proper range */ |
|
||||||
if (range.s.c < 10000000) ws['!ref'] = window.XLSX.utils.encode_range(range) |
|
||||||
return ws |
|
||||||
} |
|
||||||
|
|
||||||
function s2ab(s) { |
|
||||||
const buf = new ArrayBuffer(s.length) |
|
||||||
const view = new Uint8Array(buf) |
|
||||||
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF |
|
||||||
return buf |
|
||||||
} |
|
||||||
Loading…
Reference in new issue