fastlion-amis
Version:
一种MIS页面生成工具
100 lines (90 loc) • 4.21 kB
text/typescript
import XLSX, { CellObject } from 'xlsx'
import { IColumn } from '../store/table';
import { getValueBitLength } from './helper';
import { getCellValue } from '../store/utils/commonTableFunction';
interface IHeadCell {
name: string;
label: string;
colspan: number;
rowspan: number;
column: IColumn;
hidden: boolean
}
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');
XLSX.writeFile(workbook, fileName)
}
export const exportXLSX2 = (columns: IColumn[], datas: any[], fileName: string) => {
const labels = columns.map(column => column.label)
const data = datas.map(data => columns.map((column) => getCellValue(data[column.name ?? ''], column)))
// 创建工作簿和工作表
const workbook = XLSX.utils.book_new();
const worksheet = XLSX.utils.aoa_to_sheet([labels, ...data]);
// 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
XLSX.writeFile(workbook, 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' ? getValueBitLength(column.label) * 1.5 : 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, hidden} = cell
const label = cell.rowspan == tableHeadRows.length - startRow ? cell.column.label : cell.label
if (hidden) {
return colspan > 1 ? startCol : startCol + colspan
} else {
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 (const cell of row) {
startCol = fn(i, startCol, cell, result)
}
}
return result
}
const calcBodyCellObjs = (datas: any[], columns: IColumn[], keepFormat: boolean = true) => {
const dataTypeArr = ['number', 'static-number', 'input-number', 'progress', 'static-progress']
return datas.map<CellObject[]>(data => columns.map(column => {
const isNumerical = dataTypeArr.includes(column.type)
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 ?? 2
const place = new Array(precision).fill(0).join('')
const numFormat = precision > 0 ? `0.${place}_ ` : '0_ '
const perFormat = precision > 0 ? `0.${place}%` : '0%'
const perNumFormat = precision > 0 ? `0.${place + '00'}_ ` : '0_ '
const curFormat = `${prefix}#,##0.${place};${prefix}-#,##0.${place}`
const curNumFormat = `#,##0.${place}`
const value = data[name] ?? undefined
return {
v: getCellValue(value, column, true),
t: isNumerical || isPercentage ? 'n' : 's',
z: !keepFormat ?
(isCurrency ? curNumFormat : isPercentage ? perNumFormat : isNumerical ? numFormat : undefined) :
(isCurrency ? curFormat : isPercentage ? perFormat : isNumerical ? numFormat : undefined)
}
}))
}