如何将现有月度统计JSON数据导出为指定样式Excel?
月度统计数据导出Excel实现方案
方案一:Node.js后端生成Excel(推荐)
利用Node.js的exceljs库直接在接口中处理数据并生成带样式的Excel文件,通过流返回给前端下载,适合大数据量和复杂样式需求。
步骤:
- 安装依赖
npm install exceljs
- 修改
export-to-csv/route.ts接口逻辑
import { NextResponse } from 'next/server'; import ExcelJS from 'exceljs'; import { getMonthZoomData } from './your-data-service'; // 替换为你的数据服务路径 export async function GET(request: Request) { // 获取请求参数:年、月 const { searchParams } = new URL(request.url); const year = parseInt(searchParams.get('year') || new Date().getFullYear().toString()); const month = parseInt(searchParams.get('month') || (new Date().getMonth() + 1).toString()); // 从数据库获取原始聚合数据 const rawData = await getMonthZoomData(year, month); // 预处理数据:按UNIT和日期分组 const unitCountMap = new Map<string, Map<number, number>>(); const allUnits = new Set<string>(); const maxDay = new Date(year, month, 0).getDate(); // 获取当月最大天数 rawData.forEach(item => { const { unit, day, counts } = item; // 假设原始数据包含unit字段 allUnits.add(unit); if (!unitCountMap.has(unit)) { unitCountMap.set(unit, new Map()); } unitCountMap.get(unit)!.set(day, counts); }); const sortedUnits = Array.from(allUnits).sort(); const days = Array.from({ length: maxDay }, (_, i) => i + 1); // 生成1到当月最大天数的数组 // 创建Excel工作簿和工作表 const workbook = new ExcelJS.Workbook(); const worksheet = workbook.addWorksheet('月度统计'); // 设置标题行(合并单元格) const title = `${year}年${month}月统计数据`; const titleEndCol = String.fromCharCode(65 + sortedUnits.length); // 计算标题合并的结束列 worksheet.mergeCells(`A1:${titleEndCol}1`); const titleCell = worksheet.getCell('A1'); titleCell.value = title; titleCell.font = { size: 16, bold: true }; titleCell.alignment = { horizontal: 'center', vertical: 'middle' }; // 设置表头行 const headerRow = worksheet.addRow(['日期', ...sortedUnits]); headerRow.eachCell(cell => { cell.font = { bold: true }; cell.alignment = { horizontal: 'center', vertical: 'middle' }; cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFD9EAD3' } }; }); // 填充数据行 days.forEach(day => { const rowData = [day]; sortedUnits.forEach(unit => { rowData.push(unitCountMap.get(unit)?.get(day) || 0); // 无数据时填0 }); const dataRow = worksheet.addRow(rowData); dataRow.eachCell(cell => { cell.alignment = { horizontal: 'center' }; }); }); // 自动调整列宽 worksheet.columns.forEach(col => { col.width = col.header?.length > 10 ? col.header.length : 10; }); // 生成Excel文件缓冲区并返回 const buffer = await workbook.xlsx.writeBuffer(); return new NextResponse(buffer, { headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Content-Disposition': `attachment; filename="${year}年${month}月统计数据.xlsx"` } }); }
方案二:前端生成Excel
通过xlsx库在前端接收接口数据后处理并生成Excel,适合小数据量场景,样式控制相对有限。
步骤:
- 安装依赖
npm install xlsx
- 前端导出函数示例
import XLSX from 'xlsx'; // 调用接口并导出Excel async function exportMonthlyExcel(year, month) { const response = await fetch(`/api/export-to-csv?year=${year}&month=${month}`); const rawData = await response.json(); // 预处理数据 const unitMap = new Map(); const allUnits = new Set(); const maxDay = new Date(year, month, 0).getDate(); rawData.forEach(item => { const { unit, day, counts } = item; allUnits.add(unit); if (!unitMap.has(unit)) unitMap.set(unit, new Map()); unitMap.get(unit).set(day, counts); }); const sortedUnits = Array.from(allUnits).sort(); const days = Array.from({ length: maxDay }, (_, i) => i + 1); // 构建Excel表格数据 const sheetData = []; // 标题行(合并单元格需单独设置) sheetData.push([`${year}年${month}月统计数据`, ...Array(sortedUnits.length).fill('')]); // 表头行 sheetData.push(['日期', ...sortedUnits]); // 数据行 days.forEach(day => { const row = [day]; sortedUnits.forEach(unit => { row.push(unitMap.get(unit)?.get(day) || 0); }); sheetData.push(row); }); // 创建工作簿和工作表 const workbook = XLSX.utils.book_new(); const worksheet = XLSX.utils.aoa_to_sheet(sheetData); // 设置标题单元格合并 XLSX.utils.sheet_set_merge(worksheet, [{ s: { r: 0, c: 0 }, e: { r: 0, c: sortedUnits.length } }]); // 添加工作表到工作簿并下载 XLSX.utils.book_append_sheet(workbook, worksheet, '月度统计'); XLSX.writeFile(workbook, `${year}年${month}月统计数据.xlsx`); }
方案对比
- 后端生成:处理大数据效率更高,样式定制灵活(如单元格背景、字体、对齐方式),前端只需发起下载请求即可。
- 前端生成:无需后端额外处理,前端自主控制导出流程,但复杂样式实现成本高,大数据量下可能导致浏览器卡顿。
内容的提问来源于stack exchange,提问作者Stykgwar
相关产品推荐
相关产品推荐

