Как заполнить колонку табличной части данными из регистра накопления в 1С?

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

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

Понимание проблемы

Основная сложность заключается в том, что данные в регистрах накопления (особенно в оборотных) требуют корректной агрегации и фильтрации. Попытка перебора строк табличной части и выполнения запроса «в лоб» внутри цикла — это путь к критическому замедлению работы системы, особенно если документов много, а регистр содержит миллионы записей.

Оптимальный подход к решению: использование запросов

Самым эффективным способом является получение всех необходимых данных одним запросом до начала заполнения табличной части. Разберем шаги, которые помогут нам добиться результата.

  1. Подготовка временной таблицы: Сначала нам необходимо передать данные из табличной части в запрос, чтобы ограничить выборку из регистра только теми сделками, которые реально присутствуют в текущем документе.
  2. Соединение с регистром: Используем виртуальные таблицы Обороты регистра накопления. Это позволяет системе автоматически выполнить группировку данных.
  3. Выгрузка и заполнение: Получив результат запроса, мы должны аккуратно перенести его в нашу табличную часть, не затирая существующие данные.

Реализация через запрос с параметрами

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


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

Запрос.УстановитьПараметр(\"ТЗ\", Объект.Проекты.Выгрузить());
Запрос.УстановитьПараметр(\"НачалоПериода\", НачалоГода(ТекущаяДата()));
Запрос.УстановитьПараметр(\"КонецПериода\", ТекущаяДата());

РезультатЗапроса = Запрос.Выполнить().Выгрузить();

Безопасное обновление табличной части

Важно помнить: метод Загрузить() полностью очищает табличную часть. Если у вас в Объект.Проекты уже есть другие заполненные колонки, их данные будут уничтожены. Чтобы этого избежать, мы используем алгоритм поиска по индексу:


// Создаем индекс для быстрого поиска
РезультатЗапроса.Индексы.Добавить(\"Сделка\");

Для Каждого СтрокаТЧ Из Объект.Проекты Цикл
    НайденнаяСтрока = РезультатЗапроса.Найти(СтрокаТЧ.Сделка, \"Сделка\");
    Если НайденнаяСтрока <> Неопределено Тогда
        СтрокаТЧ.РасходыПоСделке = НайденнаяСтрока.Расходы;
    КонецЕсли;
КонецЦикла;

Почему это важно?

Проанализируем преимущества такого подхода:

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

← На главную