exceljs 中文教程
1. 项目概述
exceljs 是一个功能强大的 JavaScript 库,用于读取、操作和写入 Excel 文件。它提供了丰富的 API,允许开发者在 Node.js 或浏览器环境中处理 Excel 工作簿。
- 官方 GitHub 仓库:https://github.com/exceljs/exceljs
- 适用环境:Node.js、Web 浏览器
- 主要特点:创建和修改 Excel 工作簿、添加工作表、设置单元格格式、处理图表等
2. 核心功能
2.1 基本功能
- 工作簿操作:创建、读取、修改 Excel 工作簿
- 工作表管理:添加、删除、重命名工作表
- 单元格操作:设置单元格值、格式、样式
- 数据类型:支持字符串、数字、日期、布尔值等多种数据类型
- 公式支持:添加和计算 Excel 公式
- 行列操作:设置行高、列宽、隐藏行列
- 合并单元格:合并和取消合并单元格
2.2 高级功能
- 样式管理:定义和应用单元格样式
- 条件格式:添加条件格式化规则
- 数据验证:设置数据验证规则
- 图表创建:添加各种类型的图表
- 图片插入:添加图片到工作表
- 页眉页脚:设置工作表的页眉和页脚
- 数据透视表:创建和配置数据透视表
- 保护工作表:设置工作表密码和权限
3. 安装与设置
3.1 在 Node.js 环境中安装
npm install exceljs3.2 在浏览器中使用
可以通过 CDN 直接引入:
<script src="https://unpkg.com/exceljs@latest/dist/exceljs.min.js"></script>或者使用打包工具如 Webpack、Rollup 等引入。
4. 基本使用示例
4.1 创建简单工作簿
// 导入库(Node.js 环境)
const ExcelJS = require('exceljs');
// 创建新工作簿
const workbook = new ExcelJS.Workbook();
// 设置工作簿属性
workbook.creator = 'Me';
workbook.lastModifiedBy = 'Me';
workbook.created = new Date(2026, 1, 21);
workbook.modified = new Date();
workbook.lastPrinted = new Date(2026, 1, 21);
// 添加工作表
const worksheet = workbook.addWorksheet('Sheet 1');
// 添加表头
worksheet.addRow(['名称', '价格', '数量']);
// 添加数据行
worksheet.addRow(['产品 A', 10.00, 100]);
worksheet.addRow(['产品 B', 20.00, 50]);
worksheet.addRow(['产品 C', 30.00, 75]);
// 设置列宽
worksheet.getColumn('A').width = 15;
worksheet.getColumn('B').width = 10;
worksheet.getColumn('C').width = 10;
// 保存工作簿(Node.js 环境)
workbook.xlsx.writeFile('products.xlsx')
.then(() => {
console.log('工作簿创建成功!');
})
.catch(error => {
console.error('创建工作簿时出错:', error);
});4.2 在浏览器中下载工作簿
// 导入库(浏览器环境)
// 假设已经通过 CDN 引入了 exceljs 库
// 创建新工作簿
const workbook = new ExcelJS.Workbook();
// 添加工作表
const worksheet = workbook.addWorksheet('Sheet 1');
// 添加数据
worksheet.addRow(['名称', '值']);
worksheet.addRow(['项目 1', 100]);
worksheet.addRow(['项目 2', 200]);
worksheet.addRow(['项目 3', 300]);
// 生成并下载工作簿
workbook.xlsx.writeBuffer()
.then(buffer => {
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'data.xlsx';
a.click();
URL.revokeObjectURL(url);
})
.catch(error => {
console.error('生成工作簿时出错:', error);
});4.3 读取现有工作簿
const ExcelJS = require('exceljs');
// 读取工作簿
ExcelJS.Workbook.openFile('products.xlsx')
.then(workbook => {
// 获取第一个工作表
const worksheet = workbook.worksheets[0];
// 遍历所有行
worksheet.eachRow((row, rowNumber) => {
console.log(`行 ${rowNumber}: ${JSON.stringify(row.values)}`);
});
// 获取特定单元格的值
const cellValue = worksheet.getCell('A1').value;
console.log(`A1 单元格的值: ${cellValue}`);
})
.catch(error => {
console.error('读取工作簿时出错:', error);
});4.4 设置单元格样式
const ExcelJS = require('exceljs');
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet 1');
// 添加表头
const headerRow = worksheet.addRow(['名称', '价格', '数量', '总计']);
// 设置表头样式
headerRow.eachCell(cell => {
cell.font = {
bold: true,
color: {
argb: 'FFFFFFFF'
}
};
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'FF4472C4'
}
};
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
cell.alignment = {
horizontal: 'center',
vertical: 'middle'
};
});
// 添加数据行
const row1 = worksheet.addRow(['产品 A', 10.00, 100, 1000.00]);
const row2 = worksheet.addRow(['产品 B', 20.00, 50, 1000.00]);
const row3 = worksheet.addRow(['产品 C', 30.00, 75, 2250.00]);
// 设置数据行样式
[row1, row2, row3].forEach(row => {
row.eachCell((cell, colNumber) => {
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
// 对价格和数量列设置右对齐
if (colNumber >= 2 && colNumber <= 4) {
cell.alignment = {
horizontal: 'right'
};
}
});
});
// 设置列宽
worksheet.getColumn('A').width = 15;
worksheet.getColumn('B').width = 10;
worksheet.getColumn('C').width = 10;
worksheet.getColumn('D').width = 15;
// 保存工作簿
workbook.xlsx.writeFile('styled-products.xlsx')
.then(() => {
console.log('带样式的工作簿创建成功!');
})
.catch(error => {
console.error('创建工作簿时出错:', error);
});5. 高级用法
5.1 使用公式
const ExcelJS = require('exceljs');
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet 1');
// 添加数据
worksheet.addRow(['名称', '价格', '数量', '总计']);
worksheet.addRow(['产品 A', 10.00, 100, { formula: 'B2*C2' }]);
worksheet.addRow(['产品 B', 20.00, 50, { formula: 'B3*C3' }]);
worksheet.addRow(['产品 C', 30.00, 75, { formula: 'B4*C4' }]);
worksheet.addRow(['总计', { formula: 'SUM(B2:B4)' }, { formula: 'SUM(C2:C4)' }, { formula: 'SUM(D2:D4)' }]);
// 设置列宽
worksheet.getColumn('A').width = 15;
worksheet.getColumn('B').width = 10;
worksheet.getColumn('C').width = 10;
worksheet.getColumn('D').width = 15;
// 保存工作簿
workbook.xlsx.writeFile('formula-example.xlsx')
.then(() => {
console.log('带公式的工作簿创建成功!');
})
.catch(error => {
console.error('创建工作簿时出错:', error);
});5.2 创建图表
const ExcelJS = require('exceljs');
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet 1');
// 添加数据
worksheet.addRow(['月份', '销售额', '利润']);
worksheet.addRow(['一月', 1000, 300]);
worksheet.addRow(['二月', 1500, 450]);
worksheet.addRow(['三月', 1200, 360]);
worksheet.addRow(['四月', 1800, 540]);
worksheet.addRow(['五月', 2000, 600]);
// 设置列宽
worksheet.getColumn('A').width = 10;
worksheet.getColumn('B').width = 10;
worksheet.getColumn('C').width = 10;
// 创建图表
const chart = worksheet.addChart({
type: 'bar',
title: '月度销售数据',
xAxis: {
type: 'category',
values: 'A2:A6'
},
yAxis: {
type: 'value'
},
series: [
{
name: '销售额',
values: 'B2:B6'
},
{
name: '利润',
values: 'C2:C6'
}
],
position: {
type: 'absolute',
x: 1000000,
y: 100000
},
size: {
width: 6000000,
height: 3000000
}
});
// 保存工作簿
workbook.xlsx.writeFile('chart-example.xlsx')
.then(() => {
console.log('带图表的工作簿创建成功!');
})
.catch(error => {
console.error('创建工作簿时出错:', error);
});5.3 使用条件格式
const ExcelJS = require('exceljs');
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet 1');
// 添加数据
worksheet.addRow(['名称', '分数']);
worksheet.addRow(['学生 1', 85]);
worksheet.addRow(['学生 2', 92]);
worksheet.addRow(['学生 3', 78]);
worksheet.addRow(['学生 4', 95]);
worksheet.addRow(['学生 5', 65]);
worksheet.addRow(['学生 6', 88]);
// 设置列宽
worksheet.getColumn('A').width = 15;
worksheet.getColumn('B').width = 10;
// 添加条件格式 - 分数大于等于 90 显示绿色
worksheet.addConditionalFormattingRule({
ref: 'B2:B7',
rule: {
type: 'cellIs',
operator: 'greaterThanOrEqual',
formula1: 90,
style: {
fill: {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'FFC6EFCE'
}
}
}
}
});
// 添加条件格式 - 分数小于 70 显示红色
worksheet.addConditionalFormattingRule({
ref: 'B2:B7',
rule: {
type: 'cellIs',
operator: 'lessThan',
formula1: 70,
style: {
fill: {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'FFC00000'
}
},
font: {
color: {
argb: 'FFFFFFFF'
}
}
}
}
});
// 保存工作簿
workbook.xlsx.writeFile('conditional-formatting-example.xlsx')
.then(() => {
console.log('带条件格式的工作簿创建成功!');
})
.catch(error => {
console.error('创建工作簿时出错:', error);
});5.4 合并单元格
const ExcelJS = require('exceljs');
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet 1');
// 合并单元格
worksheet.mergeCells('A1:C1');
// 设置合并单元格的值
worksheet.getCell('A1').value = '销售报告';
worksheet.getCell('A1').font = {
bold: true,
size: 16
};
worksheet.getCell('A1').alignment = {
horizontal: 'center',
vertical: 'middle'
};
// 添加数据
worksheet.addRow(['产品', '销售额', '占比']);
worksheet.addRow(['产品 A', 1000, 0.33]);
worksheet.addRow(['产品 B', 1500, 0.5]);
worksheet.addRow(['产品 C', 500, 0.17]);
// 设置列宽
worksheet.getColumn('A').width = 15;
worksheet.getColumn('B').width = 15;
worksheet.getColumn('C').width = 15;
// 保存工作簿
workbook.xlsx.writeFile('merged-cells-example.xlsx')
.then(() => {
console.log('带合并单元格的工作簿创建成功!');
})
.catch(error => {
console.error('创建工作簿时出错:', error);
});6. 实际应用场景
6.1 生成数据报告
使用 exceljs 库从数据库或 API 获取数据,生成包含图表、条件格式和公式的专业数据报告。
6.2 数据导入导出
创建数据导入导出功能,允许用户上传 Excel 文件导入数据,或导出系统数据为 Excel 文件。
6.3 财务报表生成
生成财务报表,如利润表、资产负债表、现金流量表等,包含复杂的公式和格式。
6.4 库存管理
创建库存管理系统,使用 Excel 文件作为数据存储和报表生成工具。
6.5 学生成绩管理
生成学生成绩单,包含成绩计算、排名、条件格式等功能。
7. 代码优化建议
7.1 模块化设计
将 Excel 操作逻辑拆分为多个模块,提高代码可维护性:
// Excel 工具模块
class ExcelUtils {
static createWorkbook() {
const workbook = new ExcelJS.Workbook();
workbook.creator = 'System';
workbook.lastModifiedBy = 'System';
workbook.created = new Date();
workbook.modified = new Date();
return workbook;
}
static addHeader(worksheet, headers) {
const headerRow = worksheet.addRow(headers);
headerRow.eachCell(cell => {
cell.font = {
bold: true
};
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'FFE0E0E0'
}
};
});
return headerRow;
}
static async saveWorkbook(workbook, filename) {
try {
await workbook.xlsx.writeFile(filename);
console.log(`工作簿已保存为 ${filename}`);
return true;
} catch (error) {
console.error('保存工作簿时出错:', error);
return false;
}
}
}
// 使用示例
const workbook = ExcelUtils.createWorkbook();
const worksheet = workbook.addWorksheet('Sheet 1');
ExcelUtils.addHeader(worksheet, ['名称', '值']);
worksheet.addRow(['项目 1', 100]);
worksheet.addRow(['项目 2', 200]);
ExcelUtils.saveWorkbook(workbook, 'data.xlsx');7.2 错误处理
添加适当的错误处理,提高代码健壮性:
try {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet 1');
// 操作
await workbook.xlsx.writeFile('document.xlsx');
console.log('工作簿创建成功!');
} catch (error) {
console.error('生成工作簿时出错:', error);
// 处理错误
}7.3 性能优化
对于大型 Excel 文件,使用流式处理和分批操作:
async function processLargeExcelFile(inputFile, outputFile) {
try {
// 读取工作簿
const workbook = await ExcelJS.Workbook.openFile(inputFile);
const worksheet = workbook.worksheets[0];
// 分批处理行
const batchSize = 1000;
let currentBatch = [];
worksheet.eachRow((row, rowNumber) => {
// 跳过表头
if (rowNumber === 1) return;
// 处理当前行
// ...
// 添加到批次
currentBatch.push(row);
// 当批次达到指定大小时处理
if (currentBatch.length >= batchSize) {
processBatch(currentBatch);
currentBatch = [];
}
});
// 处理剩余的行
if (currentBatch.length > 0) {
processBatch(currentBatch);
}
// 保存结果
await workbook.xlsx.writeFile(outputFile);
console.log('处理完成!');
} catch (error) {
console.error('处理 Excel 文件时出错:', error);
}
}
function processBatch(batch) {
// 处理批次数据
console.log(`处理批次,包含 ${batch.length} 行`);
// ...
}7.4 内存管理
对于大型工作簿,注意内存使用:
// 避免一次性加载所有行到内存
worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
// 处理当前行
// ...
});
// 处理完后释放资源
workbook = null;8. 总结
exceljs 是一个功能强大、灵活易用的 JavaScript 库,为开发者提供了在各种环境中处理 Excel 文件的能力。它的主要优势包括:
- 跨平台兼容:可在 Node.js、浏览器等多种环境中使用
- 功能丰富:支持从基本单元格操作到复杂图表、公式的各种功能
- 易于集成:简单的 API 设计,易于与现有项目集成
- 高度可定制:支持自定义样式、格式、图表等
- 活跃维护:持续更新和改进
通过本教程的学习,您应该已经掌握了 exceljs 的基本用法和一些高级技巧,可以开始在实际项目中应用它来处理 Excel 文件了。