Excel и CSV: импорт и экспорт больших данных
↑ 5.6 Генерация документов и отчётов · ← Предыдущая
Зачем это на собесе
Частая практическая задача: выгрузка на 1 млн строк и импорт пользовательских файлов без OOM.
Объяснение
| Библиотека | Особенности |
|---|---|
| ClosedXML | удобный API, тяжело по памяти на больших файлах |
| EPPlus | богатый функционал, коммерческая лицензия |
| MiniExcel | потоковое чтение/запись, малая память |
OpenXML SDK (SAX-режим) | низкоуровневый потоковый доступ |
| CsvHelper | стандарт для CSV |
Принцип: потоковая обработка — читаем и пишем строки по одной/пачками, не держим весь файл в памяти.
// Экспорт: поток из БД → поток в файл
await using var output = File.Create(path);
await MiniExcel.SaveAsAsync(output, GetRowsAsync(ct), cancellationToken: ct); // IAsyncEnumerable/IEnumerable
async IAsyncEnumerable<object> GetRowsAsync([EnumeratorCancellation] CancellationToken ct)
{
await foreach (var o in db.Orders.AsNoTracking().AsAsyncEnumerable().WithCancellation(ct))
yield return new { o.Number, o.Customer, o.Total };
}// Импорт CSV с валидацией и пакетной вставкой
using var reader = new StreamReader(stream);
using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
var batch = new List<Row>(1000);
await foreach (var row in csv.GetRecordsAsync<Row>(ct))
{
if (!Validate(row, out var error)) { errors.Add((csv.Parser.Row, error)); continue; }
batch.Add(row);
if (batch.Count == 1000) { await SaveBatchAsync(batch, ct); batch.Clear(); }
}Практики импорта: загрузка файла → валидация → отчёт об ошибках по строкам (номер, поле, причина) → применение в одной транзакции или частично с отчётом.
Нюансы и подводные камни
- Excel ограничен 1 048 576 строками на лист; для больших выгрузок — CSV или несколько листов.
- Кодировка и разделители CSV (
;в русской локали, UTF-8 с BOM для Excel). - Формулы и внедрение: значения, начинающиеся с
=,+,@,-, экранируйте (CSV/formula injection). - Форматы дат/чисел зависят от культуры: используйте инвариантную культуру.
- Большие импорты выполняйте асинхронно с прогрессом и возможностью отмены.
Практика
- Экспортируйте 1 млн строк в CSV и в XLSX потоково и сравните память.
- Реализуйте импорт с отчётом об ошибках по строкам.
- Защитите экспорт от CSV-инъекций.
Вопросы с ответами
Как выгрузить миллион строк без OOM?
Потоково читать из БД и писать в файл/ответ, не материализуя всё в память.
Что такое CSV injection?
Ячейки, начинающиеся с
=/+/@, воспринимаются Excel как формулы; их нужно экранировать.
Как вести импорт пользовательских файлов?
Валидировать построчно, накапливать ошибки с номерами строк, применять пачками, выполнять асинхронно.