Создаем Excel в C# без Microsoft Office: магия под капотом

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему "без Office" и что внутри?

Если вы когда-нибудь искали, как сгенерировать Excel-файл на C#, вы наверняка натыкались на культовый вопрос на Stack Overflow с десятками тысяч просмотров. И главная боль там — фраза "without installing Microsoft Office". Почему? Потому что тянуть за собой COM-объекты, зависеть от версии Excel на сервере и ловить ошибки вроде "Retrieving the COM class factory for component... failed" — это путь в ад для разработчика.

Но как же тогда создавать .XLSX и .XLS файлы? Ответ кроется в том, как устроен сам формат. Современный Excel (начиная с 2007 года) — это обычный ZIP-архив с XML-файлами внутри. Да-да, вы не ослышались: возьмите любой .xlsx, переименуйте в .zip, откройте — и увидите папки xl, _rels, docProps и кучу XML-документов. Каждый лист, каждая ячейка, каждый стиль — это аккуратно структурированный XML. А старый формат .XLS — это бинарный формат (BIFF), но для него тоже есть open-source решения.

В этой статье мы заглянем под капот этого процесса: разберём популярные библиотеки, напишем живой код и поймём, что на самом деле происходит, когда мы вызываем Save(). Поехали!

1. Три кита C# для работы с Excel без Office

На сегодняшний день есть три главных претендента, которые решают задачу "из коробки". Каждый из них работает с форматом напрямую, минуя установленный Office.

1.1. EPPlus (лицензия LGPL / Proprietary)

Самая популярная библиотека для .NET. Изначально была бесплатной, но с версии 5.0 перешла на платную лицензию для коммерческого использования. Однако для образовательных целей и небольших проектов её всё ещё можно использовать (версия 4.5.3.3 — последняя свободная). EPPlus работает только с .XLSX.

Как это работает под капотом: EPPlus использует System.IO.Packaging (тот самый ZIP-архив) и генерирует XML-файлы в соответствии со спецификацией Office Open XML (OOXML). Она умеет создавать стили, формулы, диаграммы — всё, что вы видите в Excel.

1.2. ClosedXML

Бесплатная, open-source (лицензия MIT). Тоже работает только с .XLSX. Отличается очень дружелюбным API, который напоминает работу с самим Excel: вы работаете с Workbook, Worksheet, Cell. Под капотом — тот же Open XML, но ClosedXML берёт на себя всю рутину по созданию XML-структуры.

1.3. NPOI

Порт знаменитой Java-библиотеки Apache POI. Главное преимущество — умеет работать как с .XLSX (через XSSFWorkbook), так и со старым .XLS (через HSSFWorkbook). Бесплатно, open-source (Apache 2.0). Идеально, если вам нужна поддержка legacy-форматов.

Под капотом для .XLS: NPOI напрямую пишет бинарные данные в формате BIFF8. Это сложнее, чем XML, но зато не требует сжатия.

2. Пишем код: создаём Excel-файл тремя способами

Давайте создадим простой отчёт с заголовками и данными. Ниже — примеры для каждой библиотеки.

2.1. Пример с ClosedXML (проще всего)

using ClosedXML.Excel;

// Создаём книгу
using (var workbook = new XLWorkbook())
{
    // Добавляем лист
    var worksheet = workbook.Worksheets.Add("Отчёт");

    // Заголовки
    worksheet.Cell(1, 1).Value = "Имя";
    worksheet.Cell(1, 2).Value = "Возраст";
    worksheet.Cell(1, 3).Value = "Город";

    // Данные
    worksheet.Cell(2, 1).Value = "Анна";
    worksheet.Cell(2, 2).Value = 28;
    worksheet.Cell(2, 3).Value = "Москва";

    worksheet.Cell(3, 1).Value = "Иван";
    worksheet.Cell(3, 2).Value = 35;
    worksheet.Cell(3, 3).Value = "Санкт-Петербург";

    // Стиль для заголовков
    var headerRange = worksheet.Range("A1:C1");
    headerRange.Style.Font.Bold = true;
    headerRange.Style.Fill.BackgroundColor = XLColor.LightGray;

    // Автоширина колонок
    worksheet.Columns().AdjustToContents();

    // Сохраняем
    workbook.SaveAs("report.xlsx");
}

Что происходит под капотом? XLWorkbook создаёт в памяти структуру, которая при вызове SaveAs сериализуется в ZIP-архив с XML. Загляните в папку xl/worksheets/ — там будет sheet1.xml с вашими данными.

2.2. Пример с EPPlus (версия 4.5.3.3)

using OfficeOpenXml;

// Лицензия для EPPlus 4.5 (не требуется для старых версий)
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

using (var package = new ExcelPackage())
{
    var sheet = package.Workbook.Worksheets.Add("Данные");

    // Заголовки
    sheet.Cells[1, 1].Value = "Продукт";
    sheet.Cells[1, 2].Value = "Цена";
    sheet.Cells[1, 3].Value = "Количество";

    // Данные
    sheet.Cells[2, 1].Value = "Ноутбук";
    sheet.Cells[2, 2].Value = 75000;
    sheet.Cells[2, 3].Value = 10;

    sheet.Cells[3, 1].Value = "Мышь";
    sheet.Cells[3, 2].Value = 1500;
    sheet.Cells[3, 3].Value = 50;

    // Формула суммы
    sheet.Cells[4, 2].Formula = "SUM(B2:B3)";

    // Стили
    using (var range = sheet.Cells[1, 1, 1, 3])
    {
        range.Style.Font.Bold = true;
        range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
        range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightBlue);
    }

    sheet.Cells.AutoFitColumns();
    package.SaveAs(new FileInfo("inventory.xlsx"));
}

Под капотом EPPlus: Он создаёт объектную модель документа (Workbook → Worksheets → Cells), а затем записывает всё в OOXML-пакет. Интересно, что EPPlus не использует LINQ to XML напрямую — у него свой движок для генерации XML, оптимизированный под скорость.

2.3. Пример с NPOI (для старого .XLS)

using NPOI.HSSF.UserModel; // для .XLS
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel; // для .XLSX

// Создаём книгу для .XLS
IWorkbook workbook = new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Лист1");

// Создаём стиль заголовка
IC                

Блоги

Рекомендаций по книгам