Как прочитать большой файл CSV в 1С без ограничения по количеству строк

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При попытке загрузить в 1С объемный файл выгрузки (например, базу недействительных паспортов весом более 1 ГБ) разработчики нередко сталкиваются с ситуацией, когда данные считываются лишь частично. Попытка открыть такой файл через COM-объект Microsoft Excel упирается ровно в 1 048 576 строк, а использование Microsoft ADO с драйвером Excel нередко ограничивает выборку 65 536 строками. Разберем по шагам, почему возникают эти ограничения и как правильно организовать быстрое и стабильное чтение файлов огромного объема средствами платформы 1С:Предприятие.

Выясним причину: почему Excel и ADO обрезают строки

Проанализируем природу исходного файла. Несмотря на то что операционная система Windows может по умолчанию сопоставлять файлы с расширением CSV приложению Microsoft Excel, файл CSV не является рабочей книгой Excel. Это обычный текстовый документ с разделителями.

Когда мы пытаемся прочитать файл через COM-объект Excel.Application или настраиваем строку подключения ADO с указанием драйвера электронной таблицы (Extended Properties="Excel 12.0..."), вступают в силу жесткие внутренние лимиты форматов Microsoft Excel:

  1. 65 536 строк — системное ограничение старого формата XLS (Excel 97–2003). Если драйвер или подключение работают в режиме обратной совместимости, файл усекается на этой границе.
  2. 1 048 576 строк — максимальное количество строк на одном листе в современных версиях формата XLSX (Excel 2007 и выше). Ни один лист Excel физически не может содержать больше строк.

Кроме того, драйверы семейства Microsoft Jet / ACE OLEDB имеют собственное ограничение на размер обрабатываемой базы в 2 ГБ, а в 32-разрядной среде они быстро вызывают ошибки нехватки оперативной памяти. Следовательно, использование COM-объекта Excel или драйвера Excel для чтения текстовых файлов размером в гигабайты является архитектурной ошибкой.

Решение 1. Потоковое чтение с помощью специализированного объекта ЧтениеCSV

Рассмотрим основной штатный механизм платформы, предназначенный именно для таких задач — объект ЧтениеCSV. Главное преимущество этого объекта заключается в потоковой обработке: он не загружает весь многогигабайтный файл в оперативную память целиком, а считывает его порциями. При этом он корректно обрабатывает экранированные кавычки, многострочные поля и спецсимволы.

Посмотрим на пример организации чтения файла с пакетной записью в базу данных:


ПараметрыЧтения = Новый ПараметрыЧтенияCSV();
ПараметрыЧтения.РазделительПолей = ";";
ПараметрыЧтения.РазделительСтрок = Символы.ПС;

ФайлДляЧтения = Новый ЧтениеCSV;
ФайлДляЧтения.Открыть(ПутьКФайлу, ПараметрыЧтения);

СчетчикСтрок = 0;
РазмерПакета = 10000;

НачатьТранзакцию();
Попытка
    Пока ФайлДляЧтения.Прочитать() Цикл
        МассивДанныхСтроки = ФайлДляЧтения.ПолучитьСтроку();
        
        // Обработка полученных колонок строки
        Серия = МассивДанныхСтроки[0];
        Номер = МассивДанныхСтроки[1];
        
        // Логика добавления данных в коллекцию или набор записей
        СчетчикСтрок = СчетчикСтрок + 1;
        
        Если СчетчикСтрок % РазмерПакета = 0 Тогда
            ЗафиксироватьТранзакцию();
            НачатьТранзакцию();
        КонецЕсли;
    КонецЦикла;
    
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ФайлДляЧтения.Закрыть();
    ВызватьИсключение;
КонецПопытки;

ФайлДляЧтения.Закрыть();

Решение 2. Использование объекта ЧтениеТекста

Если структура файла предельно проста (например, две колонки чисел без переносов строк внутри ячеек) или требуется максимальная гибкость в разборе, разберем работу с объектом ЧтениеТекста. Здесь критически важно считывать данные исключительно методом ПрочитатьСтроку() внутри цикла.

Важно: никогда не используйте методы Прочитать() без параметров или загрузку в ДвоичныеДанные для гигабайтных файлов — это гарантированно приведет к критической ошибке платформы Недостаточно памяти, особенно на 32-разрядных рабочих процессах сервера или клиентах.

Посмотрим, как выглядит реализация потокового чтения:


ТекстовыйФайл = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.ANSI);

Счетчик = 0;
СтрокаФайла = ТекстовыйФайл.ПрочитатьСтроку();

Пока СтрокаФайла <> Неопределено Цикл
    // Пропускаем пустые строки при необходимости
    Если Не ПустаяСтрока(СтрокаФайла) Тогда
        ЗначенияКолонок = СтрРазделить(СтрокаФайла, ",;");
        
        // Выполняем полезную работу с массивом ЗначенияКолонок
        Счетчик = Счетчик + 1;
    КонецЕсли;
    
    СтрокаФайла = ТекстовыйФайл.ПрочитатьСтроку();
КонецЦикла;

ТекстовыйФайл.Закрыть();

Решение 3. Настройка текстового драйвера в ADO

Если архитектура решения строго требует применения Microsoft ADO (например, при выборке с фильтрацией по SQL), проанализируем настройку правильного драйвера. Вместо драйвера Excel необходимо указать драйвер для текстовых файлов (Microsoft Text Driver или провайдер ACE с типом Text). В параметре Data Source при этом указывается путь к папке, а имя файла выступает в роли таблицы в SQL-запросе:


КаталогФайла = "C:\Files\";
ИмяФайла = "list_of_expired_passports.csv";

СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + КаталогФайла + ";Extended Properties=""Text;HDR=Yes;FMT=Delimited"";";

Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.Open(СтрокаПодключения);

Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;
Команда.CommandText = "SELECT * FROM [" + ИмяФайла + "]";

Выборка = Команда.Execute();
Пока Не Выборка.EOF Цикл
    // Чтение колонок через Выборка.Fields
    Выборка.MoveNext();
КонецЦикла;

Выборка.Close();
Соединение.Close();

Однако помните, что штатные механизмы ЧтениеCSV и ЧтениеТекста в современной платформе 1С работают быстрее внешних COM-библиотек, не требуют установки дополнительных драйверов Microsoft Access Database Engine на сервер и не зависят от разрядности операционной системы.

Рекомендации по оптимизации записи в базу

Рассмотрим практические советы при обработке многомиллионных массивов данных:

  1. Пакетная фиксация транзакций. Никогда не записывайте миллионы строк по одной записи вне явной транзакции и не помещайте всю процедуру в одну гигантскую транзакцию. Фиксируйте данные порциями по 10 000 – 50 000 записей через НачатьТранзакцию() и ЗафиксироватьТранзакцию(), чтобы не переполнять журнал транзакций СУБД.
  2. Многопоточная обработка. Большой файл можно предварительно разделить на несколько частей по строкам или считывать смещениями байтов, запустив обработку в несколько параллельных фоновых заданий платформы.
  3. Прямой импорт средствами СУБД. Для задач регулярного обновления списков паспортов (десятки миллионов записей) наиболее производительный путь — загрузка файла утилитами массового импорта СУБД (например, COPY в PostgreSQL или утилита bcp в MS SQL Server) во внешнюю таблицу с последующим подключением через объект ВнешниеИсточникиДанных.
  4. Хранение вне базы 1С. Включение реестра недействительных паспортов в состав конфигурации 1С раздувает основную базу на десятки гигабайт. Рассмотрите хранение этих данных в отдельной внешней базе (PostgreSQL, ClickHouse или SQLite), выполняя из 1С точечные запросы на проверку конкретного паспорта.
← На главную