import ExcelJS from 'exceljs' function normalizeCellValue(value) { if (value == null) { return value } if (typeof value === 'object') { if (value instanceof Date) { return value } if ('result' in value) { return value.result } if ('text' in value) { return value.text } if ('richText' in value && Array.isArray(value.richText)) { return value.richText.map((part) => part.text).join('') } } return value } function downloadBuffer(buffer, filename) { const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) const url = URL.createObjectURL(blob) const anchor = document.createElement('a') anchor.href = url anchor.download = filename anchor.click() URL.revokeObjectURL(url) } /** * 读取 Excel 首个工作表,返回与 sheet_to_json 等价的对象数组 * @param {ArrayBuffer} arrayBuffer * @returns {Promise<{ rows: Array>, columns: string[] }>} */ export async function readExcelAsJson(arrayBuffer) { const workbook = new ExcelJS.Workbook() await workbook.xlsx.load(arrayBuffer) const worksheet = workbook.worksheets[0] if (!worksheet || worksheet.rowCount === 0) { return { rows: [], columns: [] } } const headerRow = worksheet.getRow(1) const headers = [] headerRow.eachCell({ includeEmpty: true }, (cell, colNumber) => { const header = normalizeCellValue(cell.value) headers[colNumber - 1] = header != null && header !== '' ? String(header) : `Column${colNumber}` }) const rows = [] worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => { if (rowNumber === 1) { return } const record = {} row.eachCell({ includeEmpty: true }, (cell, colNumber) => { const header = headers[colNumber - 1] if (header) { record[header] = normalizeCellValue(cell.value) } }) rows.push(record) }) return { rows, columns: rows.length > 0 ? Object.keys(rows[0]) : headers.filter(Boolean) } } /** * 将对象数组导出为 Excel 文件 * @param {Array>} rows * @param {string} filename * @param {string} sheetName */ export async function writeJsonToExcel(rows, filename, sheetName = 'Sheet1') { const workbook = new ExcelJS.Workbook() const worksheet = workbook.addWorksheet(sheetName) if (rows.length === 0) { const buffer = await workbook.xlsx.writeBuffer() downloadBuffer(buffer, filename) return } const columns = Object.keys(rows[0]) worksheet.columns = columns.map((key) => ({ header: key, key })) rows.forEach((row) => worksheet.addRow(row)) const buffer = await workbook.xlsx.writeBuffer() downloadBuffer(buffer, filename) } /** * 将二维数组导出为 Excel 文件 * @param {Array>} data * @param {string} filename * @param {string} sheetName */ export async function writeAoaToExcel(data, filename, sheetName = 'Sheet1') { const workbook = new ExcelJS.Workbook() const worksheet = workbook.addWorksheet(sheetName) data.forEach((row) => worksheet.addRow(row)) const buffer = await workbook.xlsx.writeBuffer() downloadBuffer(buffer, filename) }