文/ 天机阁首席数据导出大师
(云海之巅,紫袍道人手持乾坤玉简,玉简中流淌着万千数据洪流)
"今日传授尔等大数据Excel导出大法。须知数据导出,如同百川归海,需因势利导方能化繁为简。且看这数据玉简——"
第一章:Excel导出境界
凝气期(基础导出)
// 简单JSON数据导出
function exportSimpleJSON(data) {
const ws = XLSX.utils.json_to_sheet(data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "data.xlsx");
}
筑基期(大数据分页导出)
// 分页获取数据并导出
async function exportLargeData(total, pageSize = 10000) {
const wb = XLSX.utils.book_new();
let page = 1;
while ((page - 1) * pageSize < total) {
const data = await fetchData(page, pageSize);
const ws = XLSX.utils.json_to_sheet(data);
XLSX.utils.book_append_sheet(wb, ws, `Page${page}`);
page++;
}
XLSX.writeFile(wb, "large_data.xlsx");
}
元婴期(流式导出)
// 使用Stream API处理百万级数据
async function streamExport(total) {
const writer = new ExcelJS.stream.xlsx.WorkbookWriter({
filename: 'huge_data.xlsx'
});
const sheet = writer.addWorksheet('Data');
let count = 0;
const batchSize = 10000;
while (count < total) {
const data = await fetchBatchData(count, batchSize);
data.forEach(row => sheet.addRow(row));
count += batchSize;
}
await writer.commit();
}
第二章:导出七式
第一式:开天辟地(初始化工程)
# 安装核心库
npm install xlsx exceljs file-saver --save
第二式:刻录道纹(表头配置)
// 复杂表头定义
const headers = [
{ header: "ID", key: "id", width: 10 },
{ header: "姓名", key: "name", width: 20 },
{ header: "销售额", key: "sales", width: 15 }
];
// 使用ExcelJS创建带样式的表头
const worksheet = workbook.addWorksheet("销售数据");
worksheet.columns = headers;
worksheet.getRow(1).font = { bold: true };
第三式:注入灵力(数据格式化)
// 数据预处理
function formatData(rawData) {
return rawData.map(item => ({
id: item.id,
name: item.user.name,
sales: `¥${(item.amount / 100).toFixed(2)}`,
date: new Date(item.createdAt).toLocaleDateString()
}));
}
第四式:时空穿梭(分页处理)
// 分页获取数据
async function fetchPaginatedData(url, total) {
const results = [];
const pageSize = 5000;
let page = 1;
while ((page - 1) * pageSize < total) {
const res = await axios.get(url, {
params: { page, size: pageSize }
});
results.push(...res.data);
page++;
}
return results;
}
第五式:天眼通(进度监控)
// 导出进度显示
const progress = {
total: 0,
processed: 0,
update() {
const percent = (this.processed / this.total * 100).toFixed(1);
console.log(`导出进度: ${percent}%`);
}
};
// 在数据处理循环中
progress.total = totalCount;
data.forEach(item => {
// 处理数据...
progress.processed++;
progress.update();
});
第六式:自定义道纹(样式定制)
// 使用ExcelJS设置复杂样式
const style = {
font: { name: '微软雅黑', size: 11 },
border: {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
}
};
worksheet.eachRow(row => {
row.eachCell(cell => {
cell.style = style;
if (cell.value > 10000) {
cell.font = { color: { argb: 'FFFF0000' }, bold: true };
}
});
});
第七式:渡劫飞升(Web Worker优化)
// 在Worker中处理大数据
const worker = new Worker('export.worker.js');
worker.postMessage({ action: 'export', data: hugeData });
worker.onmessage = (e) => {
if (e.data.type === 'progress') {
updateProgress(e.data.value);
} else if (e.data.type === 'done') {
saveAs(e.data.blob, 'data.xlsx');
}
};
第三章:导出心法
"导出五要:
1️⃣ 分而治之(大数据分页处理)
2️⃣ 流式处理(避免内存溢出)
3️⃣ 样式美观(专业表格呈现)
4️⃣ 进度反馈(用户体验优化)
5️⃣ 异常处理(网络中断恢复)"
第四章:实战演练
基础导出
// 正确示例:使用SheetJS导出
function exportWithSheetJS(data) {
const ws = XLSX.utils.json_to_sheet(data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "export.xlsx");
}
// 错误示例:直接导出百万条数据
function exportHugeData(data) {
// 可能导致浏览器崩溃
exportWithSheetJS(data);
}
高级导出
// 多Sheet分页导出
async function exportMultiSheet(total) {
const wb = new ExcelJS.Workbook();
const pageSize = 50000;
let page = 1;
while ((page - 1) * pageSize < total) {
const data = await fetchPage(page, pageSize);
const ws = wb.addWorksheet(`Page ${page}`);
ws.columns = headers;
data.forEach(item => ws.addRow(item));
page++;
}
const buffer = await wb.xlsx.writeBuffer();
saveAs(new Blob([buffer]), "multi_sheet.xlsx");
}
第五章:导出禁忌
魔道案例
// 错误:同步处理大数据
function syncExport(data) {
// 阻塞主线程
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.json_to_sheet(data); // 百万数据直接处理
XLSX.utils.book_append_sheet(wb, ws, "Data");
XLSX.writeFile(wb, "blocking_export.xlsx");
}
// 错误:内存泄漏
let cache = [];
async function leakyExport() {
cache = []; // 未释放旧数据
cache = await fetchAllData(); // 加载全部数据
exportWithSheetJS(cache);
}
正道解法
// 正确:流式处理大数据
async function streamExport(total) {
const writer = new ExcelJS.stream.xlsx.WorkbookWriter({
filename: 'stream_export.xlsx'
});
const sheet = writer.addWorksheet('Data');
let offset = 0;
const batchSize = 10000;
while (offset < total) {
const data = await fetchBatch(offset, batchSize);
data.forEach(row => sheet.addRow(row));
offset += batchSize;
}
await writer.commit();
}
(突然,玉简剧烈震动,导出进程卡死)
弟子:"师尊!导出百万数据时浏览器崩溃了!"
道人:"痴儿!定是未做分页处理。且看这招——"
道人掐诀念咒,虚空中浮现优化代码:
// 分块处理大数据
async function chunkedExport(total, chunkSize = 50000) {
const wb = new ExcelJS.Workbook();
const sheet = wb.addWorksheet('Data');
for (let start = 0; start < total; start += chunkSize) {
const end = Math.min(start + chunkSize, total);
const data = await fetchRangeData(start, end);
data.forEach(row => sheet.addRow(row));
await new Promise(resolve => setTimeout(resolve, 0)); // 释放事件循环
}
const buffer = await wb.xlsx.writeBuffer();
saveAs(new Blob([buffer]), "chunked_export.xlsx");
}
飞升天象:
当数据导出修炼至大乘期,可:
- 导出千万级数据不卡顿
- 生成专业级报表样式
- 实现服务端直接流式导出
- 支持复杂公式和图表
(道人化作数据流光,融入玉简之中,浮现最后箴言)
"记住,导出之道在于'化整为零'。如同庖丁解牛,既要掌控全局,也需专注细节......"
(玉简展开,化作《大数据导出真经》)
<真经展开,显现完整导出知识图谱> <第二元神显化:关注天机阁,解锁更多数据秘法>
核心难点解析
- 整体架构设计
graph TD
A[后端] -->|分页数据| B[前端处理]
B -->|流式写入| C[Excel文件]
C --> D[(本地下载)]
- 性能优化方案
// 内存优化配置
const workbook = new ExcelJS.Workbook({
useSharedStrings: true, // 共享字符串节省内存
useStyles: true // 启用样式支持
});
- 服务端配合要点
// 分页API设计
router.get('/api/large-data', async (ctx) => {
const { page = 1, size = 10000 } = ctx.query;
const data = await Model.find()
.skip((page - 1) * size)
.limit(size);
ctx.body = {
data,
total: await Model.countDocuments()
};
});
- 异常处理机制
// 断点续导实现
let exportedCount = 0;
try {
while (exportedCount < total) {
const data = await fetchBatch(exportedCount, batchSize);
// 处理数据...
exportedCount += data.length;
saveProgress(exportedCount); // 保存进度
}
} catch (err) {
console.error(`导出中断,已导出${exportedCount}条`);
// 恢复时可从exportedCount继续
}
- 格式兼容方案
// 多格式导出适配
function exportAs(format, data) {
switch (format) {
case 'xlsx':
return exportXLSX(data);
case 'csv':
return exportCSV(data);
case 'pdf':
return exportPDF(data);
default:
throw new Error('不支持的格式');
}
}