扫一扫分享
在现代Web应用中,处理Excel文件已经成为常见需求。无论是生成数据导入模板、导出统计报表,还是进行批量数据处理,Excel都比CSV格式更适合处理复杂结构、格式控制、多工作表等场景。
ExcelJS是一个基于Node.js的Excel文件读写库,具有以下特点:
创建和修改.xlsx文件
支持单元格格式设置(字体、颜色、对齐等)
支持数据验证、下拉菜单、合并单元格
支持读取现有Excel文件
支持流式写入,适合处理大文件
不依赖Excel软件,跨平台运行
npm install exceljsconst ExcelJS = require('exceljs');
// 创建新的工作簿
const workbook = new ExcelJS.Workbook();
// 添加工作表
const worksheet = workbook.addWorksheet('员工信息');// 定义列结构
worksheet.columns = [
{ header: '员工编号', key: 'id', width: 15 },
{ header: '姓名', key: 'name', width: 20 },
{ header: '部门', key: 'department', width: 20 },
{ header: '工资', key: 'salary', width: 15 },
{ header: '入职日期', key: 'hireDate', width: 15 }
];
// 添加数据行
worksheet.addRow({ id: 'EMP001', name: '张三', department: '技术部', salary: 15000, hireDate: '2023-01-15' });
worksheet.addRow({ id: 'EMP002', name: '李四', department: '市场部', salary: 12000, hireDate: '2023-02-20' });
worksheet.addRow({ id: 'EMP003', name: '王五', department: '技术部', salary: 18000, hireDate: '2022-11-10' });
// 设置表头样式
const headerRow = worksheet.getRow(1);
headerRow.font = {
bold: true,
color: { argb: 'FFFFFFFF' }
};
headerRow.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF2E75B6' }
};
headerRow.alignment = { vertical: 'middle', horizontal: 'center' };
// 保存文件
await workbook.xlsx.writeFile('员工信息表.xlsx');
console.log('Excel文件创建成功');const ExcelJS = require('exceljs');
async function readExcelFile() {
const workbook = new ExcelJS.Workbook();
try {
// 读取Excel文件
await workbook.xlsx.readFile('员工信息表.xlsx');
// 获取工作表
const worksheet = workbook.getWorksheet('员工信息');
console.log('=== 读取Excel文件内容 ===');
// 遍历每一行
worksheet.eachRow((row, rowNumber) => {
if (rowNumber === 1) {
console.log('表头:', row.values);
} else {
console.log(`第${rowNumber}行数据:`, row.values);
}
});
} catch (error) {
console.error('读取文件失败:', error);
}
}
readExcelFile();async function createImportTemplate() {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('用户导入模板');
// 设置列
worksheet.columns = [
{ header: '姓名', key: 'name', width: 20 },
{ header: '身份证号', key: 'idCard', width: 25 },
{ header: '手机号', key: 'mobile', width: 20 },
{ header: '邮箱', key: 'email', width: 25 },
{ header: '部门', key: 'department', width: 20 }
];
// 将所有列设置为文本格式,避免自动格式化
worksheet.columns.forEach(column => {
column.numFmt = '@';
});
// 设置表头样式
const headerRow = worksheet.getRow(1);
headerRow.font = { bold: true, color: { argb: 'FFFFFFFF' } };
headerRow.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF0070C0' }
};
// 添加说明行
worksheet.addRow(['*姓名:必填', '*身份证:18位', '*手机号:11位', '邮箱:选填', '部门:选填']);
// 设置数据验证(下拉菜单)
worksheet.getCell('E3').dataValidation = {
type: 'list',
allowBlank: true,
formulae: ['"技术部,市场部,人事部,财务部,运营部"']
};
await workbook.xlsx.writeFile('用户导入模板.xlsx');
console.log('导入模板创建完成');
}
createImportTemplate();async function createSalesReport() {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('销售报表');
// 合并单元格创建标题
worksheet.mergeCells('A1:F1');
const titleCell = worksheet.getCell('A1');
titleCell.value = '2024年第一季度销售报表';
titleCell.font = { size: 16, bold: true };
titleCell.alignment = { horizontal: 'center', vertical: 'middle' };
// 设置列
worksheet.columns = [
{ header: '销售员', key: 'salesman', width: 15 },
{ header: '产品', key: 'product', width: 20 },
{ header: '一月', key: 'january', width: 12 },
{ header: '二月', key: 'february', width: 12 },
{ header: '三月', key: 'march', width: 12 },
{ header: '季度总计', key: 'total', width: 15 }
];
// 添加数据
const salesData = [
{ salesman: '张三', product: '笔记本电脑', january: 150000, february: 180000, march: 220000 },
{ salesman: '李四', product: '智能手机', january: 120000, february: 150000, march: 190000 },
{ salesman: '王五', product: '平板电脑', january: 80000, february: 110000, march: 130000 }
];
salesData.forEach(data => {
const total = data.january + data.february + data.march;
worksheet.addRow({
...data,
total: total
});
});
// 设置表头样式
const headerRow = worksheet.getRow(2);
headerRow.font = { bold: true };
headerRow.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFF2F2F2' }
};
// 设置数字格式
for (let i = 3; i <= 5; i++) {
const row = worksheet.getRow(i);
for (let j = 3; j <= 6; j++) {
const cell = row.getCell(j);
cell.numFmt = '#,##0';
}
}
// 添加汇总行
const totalRow = worksheet.addRow(['总计', '', 350000, 440000, 540000, 1330000]);
totalRow.font = { bold: true, color: { argb: 'FFFF0000' } };
// 冻结表头
worksheet.views = [
{ state: 'frozen', ySplit: 2 }
];
await workbook.xlsx.writeFile('销售报表.xlsx');
console.log('销售报表创建完成');
}
createSalesReport();const ExcelJS = require('exceljs');
async function createLargeExcelFile() {
// 使用流式写入处理大数据量
const workbook = new ExcelJS.stream.xlsx.WorkbookWriter({
filename: '大数据文件.xlsx'
});
const worksheet = workbook.addWorksheet('数据');
// 设置列
worksheet.columns = [
{ header: '序号', key: 'index', width: 10 },
{ header: '订单号', key: 'orderId', width: 20 },
{ header: '金额', key: 'amount', width: 15 },
{ header: '创建时间', key: 'createTime', width: 20 }
];
// 添加表头样式
const headerRow = worksheet.getRow(1);
headerRow.font = { bold: true };
headerRow.commit();
// 批量添加数据(10万行)
for (let i = 1; i <= 100000; i++) {
const row = worksheet.addRow({
index: i,
orderId: `ORDER${i.toString().padStart(8, '0')}`,
amount: Math.random() * 1000,
createTime: new Date().toISOString()
});
// 每1000行提交一次,平衡内存使用和性能
if (i % 1000 === 0) {
row.commit();
}
}
await workbook.commit();
console.log('大数据文件创建完成');
}
createLargeExcelFile();async function createReportWithConditionalFormatting() {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('业绩报表');
worksheet.columns = [
{ header: '员工', key: 'employee', width: 15 },
{ header: '完成率', key: 'completionRate', width: 15 },
{ header: '销售额', key: 'sales', width: 15 }
];
const performanceData = [
{ employee: '张三', completionRate: 0.85, sales: 150000 },
{ employee: '李四', completionRate: 1.2, sales: 220000 },
{ employee: '王五', completionRate: 0.65, sales: 80000 },
{ employee: '赵六', completionRate: 0.95, sales: 180000 }
];
performanceData.forEach(data => {
worksheet.addRow(data);
});
// 模拟条件格式:根据完成率设置颜色
worksheet.eachRow((row, rowNumber) => {
if (rowNumber > 1) { // 跳过表头
const completionRate = row.getCell(2).value;
const salesCell = row.getCell(3);
if (completionRate >= 1) {
// 超额完成 - 绿色
salesCell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF00FF00' }
};
} else if (completionRate >= 0.8) {
// 基本完成 - 黄色
salesCell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFFFF00' }
};
} else {
// 未完成 - 红色
salesCell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFF0000' }
};
}
}
});
await workbook.xlsx.writeFile('业绩报表.xlsx');
console.log('带条件格式的报表创建完成');
}
createReportWithConditionalFormatting();const ExcelJS = require('exceljs');
const express = require('express');
const app = express();
app.get('/export/users', async (req, res) => {
try {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('用户列表');
worksheet.columns = [
{ header: 'ID', key: 'id', width: 10 },
{ header: '用户名', key: 'username', width: 20 },
{ header: '邮箱', key: 'email', width: 25 },
{ header: '注册时间', key: 'createdAt', width: 20 }
];
// 模拟从数据库获取数据
const users = [
{ id: 1, username: 'user1', email: 'user1@example.com', createdAt: '2024-01-15' },
{ id: 2, username: 'user2', email: 'user2@example.com', createdAt: '2024-01-20' },
{ id: 3, username: 'user3', email: 'user3@example.com', createdAt: '2024-02-01' }
];
users.forEach(user => worksheet.addRow(user));
// 设置响应头
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', 'attachment; filename=users.xlsx');
// 将Excel文件写入响应
await workbook.xlsx.write(res);
} catch (error) {
console.error('导出失败:', error);
res.status(500).send('导出失败');
}
});
app.listen(3000, () => {
console.log('服务器运行在端口3000');
});数据格式处理
对于身份证号、手机号等数字字符串,设置numFmt: '@'避免科学计数法
日期字段使用明确的格式
性能优化
处理超过1万行数据时使用流式写入
批量操作时适当使用commit()减少内存占用
错误处理
使用try-catch包装文件操作
验证输入数据格式
样式统一
封装样式设置函数,保持整个文档风格一致
使用主题色保持专业外观
ExcelJS为Node.js环境下的Excel文件处理提供了强大而灵活的功能。无论是简单的数据导出还是复杂的报表生成,都能满足各种业务需求。掌握这些技巧将大大提升你在Web应用中处理Excel文件的能力。
仅供个人学习参考/导航指引使用,具体请以第三方网站说明为准,本站不提供任何专业建议。如果地址失效或描述有误,请联系站长反馈~感谢您的理解与支持!
手机预览