UNPKG

cloud-ui.vusion

Version:
143 lines (138 loc) 5.01 kB
import XLSX from 'xlsx-js-style'; export function exportExcel(aoa, sheetName, fileName, sheetTitleData, columns, hasHeader, merges, includeStyles) { // return; // 若有标题,添加标题到第一行 const sheet = XLSX.utils.json_to_sheet([]); aoa.forEach((row) => { // 默认设置为字符串 row.forEach((cell) => { if (cell) cell.t = 's'; }); }); // 设置列宽和行高 if (includeStyles) { const cols = []; const rows = []; aoa.forEach((row, rowIndex) => { // 获取行高 const heights = row.map((v) => v && v.rect && +v.rect.height).filter((v) => v !== undefined); const height = Math.max(...heights); rows[rowIndex] = { hpx: height }; }); if (sheetTitleData.title) { rows.unshift({ hpx: sheetTitleData.rect && sheetTitleData.rect.height }); } // 获取列宽 for (let i = 0; i < aoa[0].length; i++) { let widthResult = 0; for (let j = 0; j < aoa.length; j++) { if (aoa[j][i] && aoa[j][i].rect) { const width = aoa[j][i].rect.width; widthResult = Math.max(widthResult, width); } } cols[i] = { wpx: widthResult }; } sheet['!cols'] = cols; sheet['!rows'] = rows; } if (sheetTitleData.title) { const endCell = XLSX.utils.encode_col(columns - 1) + 1; XLSX.utils.sheet_add_aoa(sheet, [[sheetTitleData.title]], { origin: { r: 0, c: 0 } }); XLSX.utils.sheet_add_aoa(sheet, aoa, { origin: 'A2' }); sheet['!merges'] = [XLSX.utils.decode_range(`A1:${endCell}`), ...merges.map((v) => ({ s: { c: v.col, r: v.row + 1, }, e: { c: v.col + v.colspan - 1, r: v.row + 1 + v.rowspan - 1, }, }))]; // 设置标题样式 sheet.A1.s = sheetTitleData.s; } else { XLSX.utils.sheet_add_aoa(sheet, aoa, { origin: 'A1' }); sheet['!merges'] = merges.map((v) => ({ s: { c: v.col, r: v.row, }, e: { c: v.col + v.colspan - 1, r: v.row + v.rowspan - 1, }, })); } // 将文本格式的内容,转化为日期和数字格式 Object.keys(sheet).forEach((item) => { const cell = sheet[item]; const dateRegx = /^\d{4}-\d{2}-\d{2}$/; const percentRegx = /^\d+(\.\d+)?%$/; const excludeNumberRegx = /^0\d+$/; const value = cell.v; let template; if (cell.t === 's' && value !== '%' && percentRegx.test(value)) { // 根据小数位数转化为'0.00%'格式,比如一位小数就是'0.0%' if (value.indexOf('.') > -1) { const percentLength = value.split('.')[1].length; template = '0.' + new Array(percentLength - 1).fill(0).join('') + '%'; } else { template = '0%'; } cell.z = template; cell.t = 'n'; cell.v = Number(value.substring(0, value.length - 1)) / 100; } else if (!isNaN(Number(value)) && value.length <= 15) { // 0开头的数字字符串,比如'001234',不会被转化为数字 if (excludeNumberRegx.test(value)) return; if (value.indexOf('.') > -1) { const percentLength = value.split('.')[1].length; template = '0.' + new Array(percentLength).fill(0).join(''); } else { template = '0'; } cell.z = template; cell.t = 'n'; } else if (dateRegx.test(value)) { cell.t = 'd'; } }); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, sheet, sheetName); const workbookBlob = workbook2blob(wb); openDownload(workbookBlob, `${fileName}.xlsx`); } function openDownload(blob, fileName) { if (typeof blob === 'object' && blob instanceof Blob) { blob = URL.createObjectURL(blob); } const aLink = document.createElement('a'); aLink.href = blob; aLink.download = fileName || ''; const event = new MouseEvent('click'); aLink.dispatchEvent(event); } function workbook2blob(workbook) { const wopts = { bookType: 'xlsx', bookSST: false, type: 'binary', }; const wbout = XLSX.write(workbook, wopts); // 将字符串转ArrayBuffer 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; } const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream', }); return blob; }