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 exceljs

3.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 文件了。

9. 参考资源

« 上一篇 docx 中文教程 下一篇 » pdfmake 中文教程