Как обрабатывать Excel файлы: вручную или с помощью компонентов
Что проверяют
Понимаете ли вы, как устроен xlsx и какие есть способы работать с ним в .NET, с их ограничениями по лицензиям, памяти и платформе. Следом обычно спрашивают, как вы выгрузите отчёт на сотни тысяч строк и почему не стоит трогать Excel на сервере через Interop.
Как отвечать
Сначала разведите, что значит «вручную». Это либо самостоятельный разбор формата (xlsx это ZIP-архив с XML по стандарту Office Open XML), либо автоматизация установленного Excel через Microsoft.Office.Interop.Excel. Второй путь работает только на Windows с установленным Office, идёт через COM, а серверная автоматизация Office официально не поддерживается. Для веб-сервиса и Linux-контейнера он отпадает сразу.
Реальный выбор среди библиотек:
- Open XML SDK (
DocumentFormat.OpenXml): низкоуровневый доступ к формату, лицензия MIT. Кода много, зато есть потоковая запись черезOpenXmlWriterдля больших файлов; - ClosedXML: удобный API поверх Open XML SDK, MIT. Держит всю книгу в памяти, поэтому на больших выгрузках прожорлив;
- EPPlus: богатые возможности, но начиная с пятой версии распространяется под Polyform Noncommercial, и для коммерческого проекта нужна платная лицензия;
- NPOI: Apache 2.0, умеет и старый бинарный
.xls, и.xlsx; - ExcelDataReader и MiniExcel: быстрое чтение, а MiniExcel ещё и потоковая запись с небольшим расходом памяти.
Вывод: ручной разбор XML оправдан, если нужен узкий кусок формата и нельзя тянуть зависимость, в остальных случаях берут библиотеку. На большие выгрузки выбирайте потоковую запись или CSV, если заказчику не нужны форматирование и формулы.
Где спотыкаются
Предлагают Interop на сервере. Он требует Office на машине, плохо переносит параллельные запросы и оставляет висящие процессы EXCEL.EXE, если не освободить COM-объекты.
Берут EPPlus в коммерческий проект, не заглянув в лицензию. Это юридический риск, который всплывает на аудите зависимостей.
Забывают про даты и культуру. В xlsx дата хранится числом, его переводят через DateTime.FromOADate, а разбор чисел без CultureInfo.InvariantCulture ломается на запятой в дробной части.