ExcelJS 是一个用 JavaScript 编写的开源库,专注于在浏览器和 Node.js 环境下读写 Microsoft Excel 文件(.xlsx格式)。它支持创建工作簿、工作表,写入单元格,应用样式,插入图片,处理合并单元格,读写公式等。
官网地址:https://github.com/exceljs/exceljs
适用环境:浏览器、Node.js
文件格式支持:主要是 .xlsx(Excel 2007+ XML格式)
主要功能
-
创建新的Excel工作簿和工作表
-
读取和修改已有Excel文件
-
读写单元格内容(文本、数字、日期、布尔值、公式等)
-
合并/拆分单元格
-
设置单元格样式(字体、边框、颜色、对齐、填充等)
-
插入图片(支持PNG/JPEG)
-
处理数据验证、条件格式
-
读取和写入超链接
-
支持流式读写,适合大文件处理
基本用法
import ExcelJS from ‘exceljs’;
// 创建工作簿
const workbook = new ExcelJS.Workbook();
// 添加工作表
const worksheet = workbook.addWorksheet(‘Sheet1’);
// 设置单元格内容
worksheet.getCell(‘A1’).value = ‘Hello, ExcelJS!’;
// 设置样式
worksheet.getCell(‘A1’).font = { name: ‘Arial’, size: 14, bold: true, color: { argb: ‘FF0000FF’ } };
worksheet.getCell(‘A1’).alignment = { vertical: ‘middle’, horizontal: ‘center’ };
worksheet.getCell(‘A1’).fill = {
type: ‘pattern’,
pattern: ‘solid’,
fgColor: { argb: ‘FFFFFF00’ }
};
worksheet.getCell(‘A1’).border = {
top: { style: ‘thin’ },
left: { style: ‘thin’ },
bottom: { style: ‘thin’ },
right: { style: ‘thin’ }
};
// 合并单元格
worksheet.mergeCells(‘A2:C2’);
worksheet.getCell(‘A2’).value = ‘Merged cells example’;
// 写入文件(Node.js环境)
workbook.xlsx.writeFile(‘example.xlsx’)
.then(() => console.log(‘Excel文件已保存!’))
.catch(console.error);
// 浏览器环境写Buffer然后导出
workbook.xlsx.writeBuffer().then(buffer => {
// 用Blob、FileSaver等导出Excel文件
});
主要对象和API
Workbook(工作簿)
-
addWorksheet(name, options)
– 添加工作表 -
removeWorksheet(idOrName)
– 删除工作表 -
xlsx.readFile(filename)
– 读取本地Excel文件(Node) -
xlsx.writeFile(filename)
– 写入本地Excel文件(Node) -
xlsx.writeBuffer()
– 返回Buffer(浏览器和Node)
Worksheet(工作表)
-
getCell(address)
– 获取单元格,如'A1'
或{row:1,col:1}
-
addRow(values)
– 添加一行数据 -
getRow(number)
– 获取一行 -
mergeCells(range)
– 合并单元格,支持字符串"A1:C1"
或startRow,startCol,endRow,endCol
-
eachRow(callback)
– 遍历所有行 -
columns
– 设置列宽、列标题等
Cell(单元格)
-
.value
– 获取或设置值(文本、数字、日期、公式、富文本等) -
.font
– 设置字体{ name, size, bold, italic, underline, color:{argb} }
-
.alignment
– 对齐{ vertical, horizontal, wrapText, indent }
-
.border
– 边框{ top, left, bottom, right }
每个边框有{style,color}
-
.fill
– 填充{type,pattern,fgColor,bgColor}
-
.numFmt
– 数字格式,如'0.00%'
,'mm-dd-yyyy'
-
.protection
– 保护设置{ locked, hidden }
注意事项
-
在浏览器环境中导出较大文件时,可能会占用较多内存
-
不支持
.xls
(老版本Excel二进制格式) -
读取文件功能主要针对Node环境,浏览器中读取文件需借助FileReader等手段转换
-
异步API需要用Promise或async/await处理
多表导出合并示例
function rgbToARGB (rgb) {
if (!rgb) return “FFFFFFFF”;
const m = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
if (!m) return “FFFFFFFF”;
const r = parseInt(m[1]).toString(16).padStart(2, ‘0’);
const g = parseInt(m[2]).toString(16).padStart(2, ‘0’);
const b = parseInt(m[3]).toString(16).padStart(2, ‘0’);
return “FF” + r + g + b; // FF是不透明度
}
// 导出
function ExportToExcel(self) {
return new Promise(async (resolve, reject) => {
try {
//创建一个新的 Excel 工作簿对象
const workbook = new ExcelJS.Workbook();
//在工作簿中添加一个工作表,命名为“合并表格”。
const worksheet = workbook.addWorksheet(‘合并表格’);
//获取页面中 #bottom-scroll
容器下的所有 <table>
元素
const tables = document.querySelectorAll(‘#bottom-scroll table’);
let currentRow = 1;
for (let table of tables) {
//取当前表格的所有行 <tr>
const rows = table.querySelectorAll(‘tr’);
// 记录 Excel 工作表中已经被合并占用的单元格,防止覆盖
const mergedCellsTracker = {};
//遍历当前表格的每一行。
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
//获取当前行
const row = rows[rowIndex];
//获取该行中所有的单元格(包含表头th
和普通单元格td
)
const cells = row.querySelectorAll(‘th,td’);
let currentCol = 1;
//遍历当前行的每个单元格。
for (let cellIndex = 0; cellIndex < cells.length; cellIndex++) {
//获取当前单元格 DOM 对象
const cell = cells[cellIndex];
// 跳过已经被合并占用的单元格
while (mergedCellsTracker[`${currentRow},${currentCol}`]) {
currentCol++;
}
//获取单元格文本,去除前后空白。
const cellText = cell.textContent.trim();
//通过工作表行列获取 Excel 单元格对象。
const excelCell = worksheet.getCell(currentRow, currentCol);
//设置 Excel 单元格的值。
excelCell.value = cellText;
// 背景色处理(复用之前的函数)
const bgColor = cell.style.backgroundColor;
if (bgColor && bgColor !== ‘transparent’ && bgColor !== ‘rgba(0, 0, 0, 0)’) {
// 转成 Excel 需要的 ARGB
格式。
const argb = rgbToARGB(bgColor);
//给 Excel 单元格设置背景填充颜色
excelCell.fill = {
type: ‘pattern’,
pattern: ‘solid’,
fgColor: { argb }
};
}
// 处理 colspan 和 rowspan
const colspan = parseInt(cell.getAttribute(‘colspan’) || ‘1’, 10);
const rowspan = parseInt(cell.getAttribute(‘rowspan’) || ‘1’, 10);
// HTML 单元格的 colspan
和 rowspan
属性,默认值为 1
if (colspan > 1 || rowspan > 1) {
// 合并单元格,格式:startRow, startCol, endRow, endCol
worksheet.mergeCells(
currentRow,
currentCol,
currentRow + rowspan – 1,
currentCol + colspan – 1
);
// 标记这些被合并的单元格为 true
,以便后续写入时跳过
for (let r = currentRow; r < currentRow + rowspan; r++) {
for (let c = currentCol; c < currentCol + colspan; c++) {
mergedCellsTracker[`${r},${c}`] = true;
}
}
// 当前位置已经占用,下次列索引要跳过合并的单元格宽度
currentCol += colspan;
} else {
currentCol++;
}
}
currentRow++;
}
currentRow++; // 不同表格之间空一行
}
//异步将内存中的工作簿对象写成 Excel 文件的二进制 Buffer
const buffer = await workbook.xlsx.writeBuffer();
//把 Buffer 转成 Blob 对象,方便浏览器下载
const blob = new Blob([buffer], { type: ‘application/octet-stream’ });
//创建文件的临时 URL
const url = URL.createObjectURL(blob);
//创建一个 <a>
标签,设置下载链接
const a = document.createElement(‘a’);
a.href = url;
a.download = “tables.xlsx”;
a.click();
//模拟点击,触发浏览器下载
URL.revokeObjectURL(url);
resolve();
} catch (error) {
reject(error);
}
});
}