Как ускорить загрузку 120 000 строк из Excel в 1С: проверенные методы и оптимизация кода

Программист IT и автоматизация бизнеса
← На главную

Загрузка больших объемов данных из внешних файлов — это классическая задача для разработчика 1С. Ситуация, когда файл из 120 тысяч строк обрабатывается 30 минут, является сигналом о наличии серьезных «узких мест» в алгоритме. Проанализируем, почему это происходит и как сократить время обработки с получаса до нескольких секунд.

Разбор причин низкой производительности

Выясним причину, по которой стандартные методы могут работать медленно. Чаще всего проблема кроется в двух аспектах:

  1. Способ чтения файла: Использование COMОбъект("Excel.Application") требует запуска полноценного приложения Excel в фоновом режиме. Обращение к каждой ячейке через COM-соединение — это крайне ресурсоемкая операция.
  2. Поиск данных в цикле: Выполнение методов НайтиПоКоду() или НайтиПоНаименованию() внутри цикла по 120 000 итераций порождает 120 000 отдельных запросов к базе данных. Это создает колоссальную нагрузку на СУБД.

Рассмотрим пошагово способы оптимизации каждого этапа загрузки.

Способ 1: Использование нативного чтения через ТабличныйДокумент

Начиная с современных версий платформы 8.3, объект ТабличныйДокумент научился читать файлы форматов .xlsx и .xls напрямую, без установленного Microsoft Excel. Это работает значительно быстрее, чем COM.

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


ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу);

// Определяем область данных
ОбластьЯчеек = ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, ТабДок.ШиринаТаблицы);

// Используем ПостроительОтчета для максимально быстрой конвертации в ТЗ
ИсточникДанных = Новый ОписаниеИсточникаДанных(ОбластьЯчеек);
ПостроительОтчета = Новый ПостроительОтчета; 
ПостроительОтчета.ИсточникДанных = ИсточникДанных;
ПостроительОтчета.Выполнить();
ТЗ_Данные = ПостроительОтчета.Результат.Выгрузить();

Этот метод позволяет прочитать 100-120 тысяч строк всего за 10–15 секунд, так как платформа считывает данные бинарно, минуя тяжелые интерфейсы автоматизации.

Способ 2: Оптимизация поиска ссылок через запросы

После того как данные попали в таблицу значений ТЗ_Данные, нам необходимо найти соответствия в справочниках (например, «Номенклатура»). Никогда не делайте это в цикле! Правильный подход — использование временных таблиц в запросе.

Проанализируем алгоритм:

  1. Загружаем таблицу значений в запрос как параметр.
  2. Помещаем её во временную таблицу.
  3. Левым соединением сопоставляем данные с реальной таблицей справочника по уникальному идентификатору (артикулу, коду).

Посмотрим на пример такого запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ВТ_Данные.Артикул КАК Артикул,
    |    ВТ_Данные.Цена КАК Цена
    |ПОМЕСТИТЬ ВТ_Исходник
    |ИЗ
    |    &ТЗ_Данные КАК ВТ_Данные
    |;
    |
    |ВЫБРАТЬ
    |    ВТ_Исходник.Артикул,
    |    ВТ_Исходник.Цена,
    |    Номенклатура.Ссылка КАК НоменклатураСсылка
    |ИЗ
    |    ВТ_Исходник КАК ВТ_Исходник
    |        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
    |        ПО ВТ_Исходник.Артикул = Номенклатура.Артикул";

Запрос.УстановитьПараметр("ТЗ_Данные", ТЗ_Данные);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

Вместо 120 000 запросов мы выполняем один. Это сокращает время поиска с минут до долей секунды.

Способ 3: Пакетная запись в базу данных

Запись объектов в базу также требует оптимизации. Если вы записываете данные в регистр сведений, используйте наборы записей. Если создаете новые элементы справочников, обязательно отключайте лишние проверки.

Рассмотрим важный механизм — использование свойства ОбменДанными.Загрузка. Установка этого флага в значение Истина сообщает системе, что данные загружаются извне, и большинство подписок на события и проверок в модулях объекта (например, проверка заполнения, контроль уникальности) будут пропущены. Это ускоряет запись в разы.


Для Каждого Строка Из РезультатЗапроса Цикл
    // Если объект найден — обновляем, если нет — создаем
    ОбъектНоменклатура = Строка.НоменклатураСсылка.ПолучитьОбъект();
    Если ОбъектНоменклатура = Неопределено Тогда
        ОбъектНоменклатура = Справочники.Номенклатура.СоздатьЭлемент();
    КонецЕсли;
    
    // Заполняем данные
    ОбъектНоменклатура.Наименование = Строка.Артикул;
    
    // ВАЖНО: Ускоряем запись
    ОбъектНоменклатура.ОбменДанными.Загрузка = Истина;
    ОбъектНоменклатура.Записать();
КонецЦикла;

Альтернатива: Использование формата CSV

Как отмечают эксперты, формат Excel (особенно современный .xlsx) — это сложная XML-структура внутри ZIP-архива. Если у вас есть возможность влиять на формат выгрузки из сторонней системы, всегда выбирайте CSV.

Разберем, почему это быстрее. Объект ЧтениеТекста в 1С работает с потоком данных. Ему не нужно строить модель документа в памяти или парсить сложные XML-схемы форматирования. Чтение 120 000 строк из текстового файла занимает считанные секунды даже на слабом железе.

Рекомендации по «железу» и среде выполнения

Проанализируем влияние аппаратной части. Загрузка больших файлов — это однопоточная операция в 1С. Это означает, что 1С задействует только одно ядро процессора. Поэтому для быстрой обработки критически важна высокая частота ядра (от 3.5 ГГц и выше), а не общее количество ядер сервера.

Также помните:

Итоги

Мы рассмотрели несколько стратегий оптимизации. Подведем итог: нормальное время загрузки 120 000 строк при использовании ТабличногоДокумента и пакетных запросов должно составлять от 1 до 3 минут (включая запись в базу), но никак не 30 минут. Использование метода ПостроительОтчета для выгрузки ТабличногоДокумента в ТаблицуЗначений на сегодняшний день является одним из самых быстрых способов получения данных из Excel внутри платформы 1С.

← На главную