UNPKG

fastlion-amis

Version:

一种MIS页面生成工具

116 lines (105 loc) 4.75 kB
import XLSX, { CellObject } from 'xlsx' import { IColumn } from '../store/table'; interface IHeadCell { name: string; label: string; colspan: number; rowspan: number; column: IColumn; } export const exportXLSX = (columns: any[], data: any[], fileName: string) => { // 创建工作簿和工作表 const workbook = XLSX.utils.book_new(); const worksheet = XLSX.utils.aoa_to_sheet([columns, ...data]); // 将工作表添加到工作簿 XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); // 将工作簿导出为二进制 Blob 对象 const wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }); // 创建隐藏的可下载链接 const blob = new Blob([wbout], { type: 'application/octet-stream' }); download(blob, fileName) } export const exportXLSXFromCross = (tableHeadRows: IHeadCell[][], columns: IColumn[], datas: any[], fileName: string, keepFormat: boolean = true) => { const headCellObjs = calcHeadCellObjs(tableHeadRows) const bodyCellObjs = calcBodyCellObjs(datas, columns, keepFormat) const workbook = XLSX.utils.book_new() const worksheet = XLSX.utils.aoa_to_sheet([]) for (const cellObj of headCellObjs) { XLSX.utils.sheet_add_aoa(worksheet, [[cellObj]], { origin: cellObj.s }) } XLSX.utils.sheet_add_aoa(worksheet, bodyCellObjs, { origin: { r: tableHeadRows.length, c: 0 } }) worksheet['!merges'] = headCellObjs worksheet['!cols'] = columns.map(column => ({ width: typeof column.label == 'string' ? column.label.length * 3 : 20 })) XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') XLSX.writeFile(workbook, fileName) } const calcHeadCellObjs = (tableHeadRows: IHeadCell[][]) => { const fn = (startRow: number, startCol: number, cell: IHeadCell, array: (XLSX.Range & CellObject)[]) => { const { rowspan, colspan } = cell const label = cell.rowspan == tableHeadRows.length - startRow ? cell.column.label : cell.label if (rowspan > 1 && colspan > 1) { array.push({ s: { r: startRow, c: startCol }, e: { r: startRow + rowspan - 1, c: startCol + colspan - 1 }, v: label, t: 's' }) return startCol + colspan } if (rowspan > 1) { array.push({ s: { r: startRow, c: startCol }, e: { r: startRow + rowspan - 1, c: startCol }, v: label, t: 's' }) return startCol + colspan } if (colspan > 1) { array.push({ s: { r: startRow, c: startCol }, e: { r: startRow, c: startCol + colspan - 1 }, v: label, t: 's' }) return startCol + colspan } array.push({ s: { r: startRow, c: startCol }, e: { r: startRow + rowspan - 1, c: startCol + colspan - 1 }, v: label, t: 's' }) return startCol + colspan } const result: (XLSX.Range & CellObject)[] = [] for (let i = 0; i < tableHeadRows.length; i++) { const row = tableHeadRows[i] let startCol = 0 for (let j = 0; j < i; j++) { const preRow = tableHeadRows[j].filter(item => item.name != 'SF_COUNT') for (const item of preRow) { if (item.rowspan > i) { startCol += item.colspan } } } for (const cell of row) { startCol = fn(i, startCol, cell, result) } } return result } const calcBodyCellObjs = (datas: any[], columns: IColumn[], keepFormat: boolean = true) => { return datas.map<CellObject[]>(data => columns.map(column => { const dataTypeArr = ['number', 'static-number', 'input-number', 'progress', 'static-progress'] const isNumerical = dataTypeArr.includes(column.type) const isMapping = column.type == 'mapping' const isPercentage = column.pristine.isPercentage const prefix = column.pristine.prefix const name = column.name! const isCurrency = Boolean(prefix) && column.type == 'number' const precision = column.pristine.precision ?? 0 const place = new Array(precision).fill(0).join('') const numFormat = precision > 0 ? `0.${place}_ ` : '0_ ' const perFormat = precision > 0 ? `0.${place}%` : '0%' const curFormat = `${prefix}#,##0.${place};${prefix}-#,##0.${place}` const value = data[name] ?? undefined return { v: isPercentage && !isNaN(+value) ? +(value) / 100 : isMapping ? column.map?.[value]?.replace?.(/\n|\r|<[^>]*>/g, '') ?? value : value ?? '', t: isNumerical || isPercentage ? 'n' : 's', z: !keepFormat ? undefined : (isCurrency ? curFormat : isPercentage ? perFormat : isNumerical ? numFormat : undefined) } })) } const download = (blob: Blob, fileName: string) => { const url = URL.createObjectURL(blob); // 提供下载链接给用户 const link = document.createElement('a'); link.href = url; link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); }