Как разбить большую таблицу значений на части по 500 строк и сохранить в разные файлы

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

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

Рассмотрим, как правильно реализовать алгоритм разделения таблицы значений на части (например, по 500 строк) и сохранения каждой части в отдельный файл. Разберем несколько подходов: от простого счетчика до продвинутых методов работы с памятью.

Способ 1: Использование универсального счетчика (Классический подход)

Этот метод является наиболее понятным и универсальным. Мы будем использовать цикл Для Каждого для обхода строк таблицы и переменную-счетчик, которая будет отслеживать количество добавленных в текущий файл строк. Проанализируем основные шаги этого алгоритма.

При достижении лимита (шага) в 500 строк мы должны закрыть текущий файл, обнулить счетчик и подготовить новый файл для записи. Важно также не забыть обработать "хвост" — те строки, которые остались в последнем пакете и не достигли ровно 500 единиц.

Рассмотрим пример кода, реализующий эту логику:


// Предположим, ТЗ_Данные - наша исходная таблица со 100500 строками
Счетчик = 0;
НомерФайла = 1;
Шаг = 500;

// Инициализируем первый файл
ТекФайл = ОткрытьФайлДляЗаписи(ПутьККаталогу + "Выгрузка_" + НомерФайла + ".txt");

Для Каждого Стр Из ТЗ_Данные Цикл
    
    Счетчик = Счетчик + 1;
    
    // Записываем данные строки в файл (логика записи зависит от формата: TXT, CSV, JSON)
    ЗаписатьСтрокуВФайл(ТекФайл, Стр.Номенклатура);
    
    Если Счетчик >= Шаг Тогда
        // Лимит достигнут: закрываем текущий файл и создаем новый
        ЗакрытьФайл(ТекФайл);
        
        НомерФайла = НомерФайла + 1;
        Счетчик = 0;
        
        // Открываем новый файл для следующей порции данных
        ТекФайл = ОткрытьФайлДляЗаписи(ПутьККаталогу + "Выгрузка_" + НомерФайла + ".txt");
    КонецЕсли;
    
КонецЦикла;

// Обязательная проверка: если в последнем файле были данные, его нужно закрыть
Если Счетчик > 0 Тогда
    ЗакрытьФайл(ТекФайл);
Иначе
    // Если последняя итерация закрыла файл, а новых данных нет - удаляем пустой созданный файл
    УдалитьФайл(ТекФайл);
КонецЕсли;

Важный нюанс: Обратите внимание на условие после завершения цикла. Если общее количество строк кратно 500, то последняя итерация внутри цикла закроет файл и тут же откроет новый (пустой). Чтобы не плодить пустые файлы, мы добавили проверку Если Счетчик > 0.

Способ 2: Метод частичного копирования таблицы

Если задача состоит не просто в записи строк в текстовый файл, а в формировании нескольких новых ТаблицЗначений (например, для передачи их в разные фоновые задания или записи через XML-сериализатор), эффективнее использовать метод Скопировать(). Это встроенная функция объекта ТаблицаЗначений, которая работает значительно быстрее, чем ручной перебор.

Выясним, как это работает: мы можем передать в метод массив строк, которые нужно скопировать. Это позволяет "нарезать" таблицу на части программно.


ВсегоСтрок = ТЗ_ВсеТовары.Количество();
Шаг = 500;
ТекущийИндекс = 0;

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

Этот способ удобен тем, что ЧастьТЗ сохраняет структуру колонок и типы данных исходной таблицы. Метод Скопировать() оптимизирован на уровне платформы 1С и работает крайне быстро.

Способ 3: Использование временных таблиц в запросах

Если ваша исходная таблица значений очень велика, работа с ней в оперативной памяти может замедлить систему. В таких случаях проанализируем возможность использования механизма запросов. Мы можем поместить ТаблицуЗначений во временную таблицу и "нарезать" её при помощи конструкции ВЫБРАТЬ ПЕРВЫЕ....

Разберем алгоритм по шагам:

  1. Добавляем в исходную ТЗ колонку НомерСтроки и заполняем её по порядку.
  2. Помещаем ТЗ во временную таблицу (МенеджерВременныхТаблиц).
  3. В цикле выполняем запрос, который выбирает строки, где НомерСтроки находится в диапазоне от N до M.

// Добавляем индекс для удобства выборки
ТЗ_Данные.Колонки.Добавить("ИндексГруппы", Новый ОписаниеТипов("Число"));
Для Каждого Стр Из ТЗ_Данные Цикл
    Стр.ИндексГруппы = ТЗ_Данные.Индекс(Стр);
КонецЦикла;

Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ";
Запрос.УстановитьПараметр("ТЗ", ТЗ_Данные);
Запрос.Выполнить();

Шаг = 500;
ВсегоСтрок = ТЗ_Данные.Количество();

Для НачИндекс = 0 По Цел(ВсегоСтрок / Шаг) Цикл
    Запрос.Текст = 
    "ВЫБРАТЬ * ИЗ ВТ_Данные 
    |ГДЕ ИндексГруппы МЕЖДУ &От И &До";
    
    Запрос.УстановитьПараметр("От", НачИндекс * Шаг);
    Запрос.УстановитьПараметр("До", (НачИндекс + 1) * Шаг - 1);
    
    Результат = Запрос.Выполнить().Выгрузить();
    
    Если Результат.Количество() > 0 Тогда
        // Сохраняем результат запроса в файл
        СохранитьПакет(Результат);
    КонецЕсли;
КонецЦикла;

Преимущество этого метода: Вы можете использовать мощь языка запросов 1С для дополнительной фильтрации или сортировки данных прямо в процессе разбиения на файлы.

Советы по оптимизации и безопасности

При работе с большим количеством файлов (например, если 100 000 строк делятся на 200 файлов), следует учитывать следующие моменты:

Таким образом, мы рассмотрели три различных подхода к решению задачи. Выбор конкретного метода зависит от ваших целей: для простой текстовой выгрузки достаточно обычного счетчика, а для сложной обработки данных лучше подойдут методы копирования или запросы к временным таблицам.

← На главную