123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- import ExcelJS from 'exceljs'
- export interface IExcel {
-
- fileName?: string
-
- rows: Array<Array<string | number>>
-
- data: Array<Array<any>>
-
- width?: Array<number>
-
- merge?: Array<any>
- }
- export const useExcel = () => {
-
- const importExcel = (file: File, fileMaxSize: number = 20) => {
- return new Promise((resolve, reject) => {
- if (
- !['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'].includes(
- file.type
- )
- ) {
- reject(new Error('只能选择 excel 文件'))
- return
- }
- if (file.size / 1024 / 1024 > fileMaxSize) {
- reject(new Error('大小不能超过 20MB'))
- return
- }
- const reader = new FileReader()
- reader.onload = e => {
- const workbook = new ExcelJS.Workbook()
- workbook.xlsx.load(e.target?.result as any).then(() => {
- const title: string[] = []
- const list: Record<string, any>[] = []
- workbook.eachSheet(sheet => {
- list.splice(0, list.length)
- sheet.eachRow({ includeEmpty: true }, row => {
- title.splice(0, title.length)
- const item: Record<string, any> = {}
- row.eachCell({ includeEmpty: true }, cell => {
- const key = cell.address.slice(0, -String(cell.row).length)
- title.push(key)
- const isMerged = cell.isMerged && cell.address !== cell.master.address
- item[key] = {
- value: cell.value,
- colspan: isMerged ? 0 : 1,
- rowspan: isMerged ? 0 : 1
- }
- })
- list.push(item)
- })
-
- sheet.eachRow({ includeEmpty: true }, row => {
- row.eachCell({ includeEmpty: true }, cell => {
- const master = cell.master
- if (cell.isMerged && cell.address !== master.address) {
- const mk = master.address.slice(0, -String(master.row).length)
- const mItem = list[Number(master.row) - 1][mk]
- const rs = Math.abs(Number(cell.row) - Number(master.row)) + 1
- rs > mItem.rowspan && (mItem.rowspan = rs)
- const cs = Math.abs(Number(cell.col) - Number(master.col)) + 1
- cs > mItem.colspan && (mItem.colspan = cs)
- }
- })
- })
- })
- resolve({ title, list })
- })
- }
- reader.readAsArrayBuffer(file)
- })
- }
-
- const exportExcel = (options: IExcel) => {
- return new Promise((resolve, reject) => {
- options = Object.assign(
- {
- fileName: options.fileName || Date.now()
- },
- options
- )
- const workbook = new ExcelJS.Workbook()
- const sheet = workbook.addWorksheet('Sheet1')
- if (!(Array.isArray(options.rows) && Array.isArray(options.rows[0]))) {
- reject(new Error('表头数据必须为二维数组'))
- return
- }
- if (!Array.isArray(options.data)) {
- reject(new Error('表格数据必须为数组'))
- return
- }
-
- const widths =
- Array.isArray(options.width) && options.width.length
- ? options.width
- : Array.from(Array(options.rows[0].length).keys()).map(() => 16)
-
- options.rows.forEach(row => {
- sheet.addRow(row)
- })
-
- options.data.forEach(item => {
- sheet.addRow(item)
- })
-
- widths.forEach((width, index) => {
- sheet.getColumn(index + 1).width = width
- })
-
- sheet.eachRow({ includeEmpty: true }, (row, rowIndex) => {
- row.height = 20
- row.eachCell({ includeEmpty: true }, cell => {
- cell.border = {
- top: { style: 'thin' },
- left: { style: 'thin' },
- bottom: { style: 'thin' },
- right: { style: 'thin' }
- }
- cell.alignment = {
- vertical: 'middle',
- horizontal: 'center'
- }
- cell.font = { size: 12, bold: rowIndex < options.rows.length }
- })
- })
-
- if (Array.isArray(options.merge)) {
- options.merge.forEach(item => {
- sheet.mergeCells(item)
- })
- }
-
- workbook.xlsx.writeBuffer().then(data => {
- download(data, `${options.fileName}.xlsx`)
- })
- })
- }
-
- const toTwoArray = (list: Record<string, any>[]) => {
- const arr: Array<Array<string | number | null | undefined>> = []
- list.forEach((item: any) => {
- const brr = Object.values(item).map((ite: any) => ite.value)
- arr.push(brr)
- })
- return arr
- }
-
- const download = (data: Blob | ArrayBuffer | string, name: string, type?: string) => {
- const blob = new Blob([data], { type: type || 'application/octet-stream' })
- const url = window.URL.createObjectURL(blob)
- const a = document.createElement('a')
- a.href = url
- a.download = name
- a.style.display = 'none'
- document.body.appendChild(a)
- a.click()
- document.body.removeChild(a)
- URL.revokeObjectURL(url)
- }
- return { importExcel, toTwoArray, exportExcel }
- }
|