ExcelJS для JavaScript (Node.js): Полное руководство по созданию и парсингу Excel-файлов
1. Что такое ExcelJS и зачем она нужна?
ExcelJS — это мощная и гибкая библиотека для языка JavaScript, предназначенная для работы с электронными таблицами в форматах Excel (XLSX, XLSM, CSV и другие). Она работает как в среде Node.js, так и в браузере (через сборщики модулей, такие как Webpack или Browserify). ExcelJS позволяет разработчикам программно создавать, читать, изменять и парсить файлы Excel без необходимости использования самого приложения Microsoft Excel.
Зачем нужна ExcelJS? В современной веб-разработке и автоматизации бизнес-процессов Excel остаётся одним из самых популярных форматов для обмена данными. Отчёты, выгрузки из баз данных, финансовые документы, прайс-листы, статистика — всё это часто требуется экспортировать в Excel. Библиотека ExcelJS предоставляет полный набор инструментов для решения этих задач: от создания простой таблицы с данными до сложных отчётов с объединёнными ячейками, стилями, формулами, диаграммами и условным форматированием. Кроме того, она умеет парсить (читать) существующие Excel-файлы, что позволяет автоматизировать импорт данных из таблиц.
Ключевые преимущества ExcelJS перед аналогами (например, xlsx от SheetJS):
- Поддержка стилей: цвета, шрифты, границы, выравнивание, заливка.
- Работа с формулами: чтение и запись формул.
- Условное форматирование: изменение внешнего вида ячеек на основе их значений.
- Диаграммы: создание графиков и диаграмм.
- Изображения: вставка изображений в листы.
- Потоковая обработка: работа с большими файлами без загрузки всего файла в память.
- Активная поддержка: библиотека регулярно обновляется и имеет большое сообщество.
2. Установка
Установка ExcelJS в проект Node.js выполняется с помощью менеджера пакетов npm. Откройте терминал в корневой папке вашего проекта и выполните команду:
npm install exceljs
После завершения установки вы сможете импортировать библиотеку в свой код:
const ExcelJS = require('exceljs');
Если вы используете ES-модули (современный синтаксис import/export), убедитесь, что в вашем package.json установлен флаг "type": "module", или используйте расширение файла .mjs:
import ExcelJS from 'exceljs';
3. Быстрый старт — минимальный рабочий пример
Давайте создадим простой Excel-файл с одной таблицей и сохраним его на диск. Этот пример демонстрирует основные шаги: создание рабочей книги, добавление листа, запись данных и сохранение.
const ExcelJS = require('exceljs');
async function createSimpleExcel() {
// 1. Создаём новую рабочую книгу
const workbook = new ExcelJS.Workbook();
// 2. Добавляем лист с именем "Мои данные"
const worksheet = workbook.addWorksheet('Мои данные');
// 3. Определяем колонки (заголовки)
worksheet.columns = [
{ header: 'ID', key: 'id', width: 10 },
{ header: 'Имя', key: 'name', width: 30 },
{ header: 'Возраст', key: 'age', width: 10 },
{ header: 'Город', key: 'city', width: 20 }
];
// 4. Добавляем строки с данными
worksheet.addRow({ id: 1, name: 'Анна Иванова', age: 28, city: 'Москва' });
worksheet.addRow({ id: 2, name: 'Пётр Петров', age: 35, city: 'Санкт-Петербург' });
worksheet.addRow({ id: 3, name: 'Елена Сидорова', age: 22, city: 'Новосибирск' });
// 5. Сохраняем книгу в файл
await workbook.xlsx.writeFile('output.xlsx');
console.log('Файл output.xlsx успешно создан!');
}
createSimpleExcel().catch(console.error);
После запуска этого скрипта в папке проекта появится файл output.xlsx, который можно открыть в Excel.
4. Основные методы, функции и классы
Рассмотрим ключевые компоненты ExcelJS. Каждый пункт содержит сигнатуру метода, краткое описание и рабочий пример.
4.1. new ExcelJS.Workbook()
Сигнатура: new ExcelJS.Workbook()
Описание: Создаёт новый экземпляр рабочей книги (Workbook). Это корневой объект, который содержит все листы, стили и настройки документа.
const workbook = new ExcelJS.Workbook();
console.log('Рабочая книга создана');
4.2. workbook.addWorksheet(name)
Сигнатура: workbook.addWorksheet(name, options?)
Описание: Добавляет новый лист (Worksheet) в рабочую книгу с указанным именем. Возвращает объект листа для дальнейшей работы.
const worksheet = workbook.addWorksheet('Продажи', {
properties: { tabColor: { argb: 'FF00FF00' } }, // Зелёный цвет вкладки
pageSetup: { orientation: 'landscape' } // Альбомная ориентация
});
console.log('Лист "Продажи" добавлен');
4.3. worksheet.columns
Сигнатура: worksheet.columns = arrayOfColumnDefinitions
Описание: Определяет структуру колонок листа. Каждый элемент массива — объект с полями header (заголовок), key (ключ для доступа к данным) и width (ширина колонки).
worksheet.columns = [
{ header: 'Товар', key: 'product', width: 25 },
{ header: 'Цена', key: 'price', width: 12 },
{ header: 'Количество', key: 'quantity', width: 15 }
];
4.4. worksheet.addRow(data)
Сигнатура: worksheet.addRow(data)
Описание: Добавляет новую строку в конец листа. data может быть массивом значений или объектом, ключи которого соответствуют key из определения колонок.
// Добавление строки как объекта
worksheet.addRow({ product: 'Ноутбук', price: 75000, quantity: 10 });
// Добавление строки как массива
worksheet.addRow(['Мышь', 1500, 50]);
4.5. worksheet.getRow(rowNumber)
Сигнатура: worksheet.getRow(rowNumber)
Описание: Возвращает объект строки по её номеру (нумерация начинается с 1). Позволяет читать или изменять данные в конкретной строке.
const row = worksheet.getRow(2); // Получаем вторую строку
console.log('Значение в колонке A:', row.getCell('A').value);
row.getCell('C').value = 100; // Изменяем значение в колонке C
row.commit(); // Сохраняем изменения
4.6. worksheet.getCell(address)
Сигнатура: worksheet.getCell(address)
Описание: Возвращает объект ячейки по её адресу (например, 'A1', 'B2') или по номеру строки и колонки. Позволяет читать/записывать значение, применять стили.
const cell = worksheet.getCell('A1');
cell.value = 'Новый заголовок';
cell.font = { name: 'Arial', size: 14, bold: true };
cell.alignment = { vertical: 'middle', horizontal: 'center' };
4.7. cell.value и работа с формулами
Сигнатура: cell.value = value | formula
Описание: Устанавливает значение ячейки. Можно задать как простое значение (число, строка, дата), так и формулу Excel.
// Простое значение
worksheet.getCell('A1').value = 42;
// Формула
worksheet.getCell('C1').value = { formula: 'A1+B1', result: 100 }; // result — опционально
// Дата
worksheet.getCell('D1').value = new Date(2024, 0, 1); // 1 января 2024
4.8. workbook.xlsx.writeFile(path)
Сигнатура: workbook.xlsx.writeFile(path)
Описание: Сохраняет рабочую книгу в файл формата XLSX по указанному пути. Возвращает Promise.
await workbook.xlsx.writeFile('./reports/sales_report.xlsx');
console.log('Файл сохранён');
4.9. workbook.xlsx.readFile(path)
Сигнатура: workbook.xlsx.readFile(path)
Описание: Загружает существующий Excel-файл из файловой системы для чтения или редактирования.
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.readFile('./template.xlsx');
const worksheet = workbook.getWorksheet('Лист1');
console.log('Значение A1:', worksheet.getCell('A1').value);
4.10. worksheet.eachRow(callback)
Сигнатура: worksheet.eachRow(callback, options?)
Описание: Итерирует по всем строкам листа, вызывая callback-функцию для каждой строки. Полезно для парсинга данных.
worksheet.eachRow((row, rowNumber) => {
console.log(`Строка ${rowNumber}:`, row.values);
});
5. Реальный практический пример (150+ строк кода)
Создадим полноценный скрипт, который генерирует отчёт о продажах с форматированием, формулами и итогами. Этот пример объединяет большинство рассмотренных методов.
const ExcelJS = require('exceljs');
async function generateSalesReport() {
// Создаём рабочую книгу
const workbook = new ExcelJS.Workbook();
workbook.creator = 'PythonLib';
workbook.created = new Date();
// Добавляем лист
const worksheet = workbook.addWorksheet('Продажи 2024', {
pageSetup: { paperSize: 9, orientation: 'landscape' } // A4, альбомная
});
// Определяем колонки
worksheet.columns = [
{ header: 'Дата', key: 'date', width: 15 },
{ header: 'Товар', key: 'product', width: 25 },
{ header: 'Категория', key: 'category', width: 15 },
{ header: 'Количество', key: 'quantity', width: 12 },
{ header: 'Цена за ед.', key: 'unitPrice', width: 15 },
{ header: 'Сумма', key: 'total', width: 15 }
];
// Стиль для заголовков
const headerStyle = {
font: { bold: true, color: { argb: 'FFFFFFFF' }, size: 12 },
fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF4472C4' } },
alignment: { vertical: 'middle', horizontal: 'center' },
border: {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
}
};
// Применяем стиль к заголовкам
const headerRow = worksheet.getRow(1);
headerRow.height = 30;
headerRow.eachCell((cell) => {
cell.style = headerStyle;
});
// Данные для отчёта
const salesData = [
{ date: new Date(2024, 0, 15), product: 'Ноутбук', category: 'Электроника', quantity: 5, unitPrice: 75000 },
{ date: new Date(2024, 1, 10), product: 'Смартфон', category: 'Электроника', quantity: 12, unitPrice: 45000 },
{ date: new Date(2024, 2, 5), product: 'Книга', category: 'Книги', quantity: 30, unitPrice: 800 },
{ date: new Date(2024, 3, 20), product: 'Наушники', category: 'Электроника', quantity: 8, unitPrice: 3500 },
{ date: new Date(2024, 4, 12), product: 'Футболка', category: 'Одежда', quantity: 20, unitPrice: 1500 },
{ date: new Date(2024, 5, 1), product: 'Планшет', category: 'Электроника', quantity: 3, unitPrice: 30000 }
];
// Добавляем данные и формулы
salesData.forEach((item, index) => {
const rowNumber = index + 2; // Начинаем со второй строки
const row = worksheet.getRow(rowNumber);
row.getCell('A').value = item.date;
row.getCell('B').value = item.product;
row.getCell('C').value = item.category;
row.getCell('D').value = item.quantity;
row.getCell('E').value = item.unitPrice;
// Формула: