Как вывести дополнительные данные в табличную часть обработки «Обеспечение потребностей»?

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

В типовых конфигурациях, таких как 1С:Управление торговлей 11, ERP 2 или Комплексная автоматизация, обработка «Обеспечение потребностей» является одним из самых сложных инструментов. Часто возникает задача дополнить ее таблицу Запасы новыми расчетными данными, например, показателями рентабельности или актуальным страховым запасом из регистров. Разберем, как правильно реализовать заполнение этих данных, какие ошибки могут возникнуть при выводе на форму и как оптимизировать производительность кода.

Анализ проблемы: почему данные могут не отображаться

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

  1. Неверная привязка данных (Path to Data): Если путь к данным элемента формы не совпадает с реквизитом, который вы заполняете (например, на форму выведена не основная табличная часть объекта, а вспомогательная коллекция значений или динамический список).
  2. Специфика отображения нулевых значений: В свойствах колонки может быть установлен формат ЧЗ= (скрывать нулевые значения). Если расчет выдает 0, ячейка будет выглядеть пустой.
  3. Особенности многошаговых обработок: В обработке «Обеспечение потребностей» данные могут пересчитываться или кэшироваться на каждом шаге мастера. Если заполнение происходит в неподходящий момент жизненного цикла формы, типовые механизмы могут «затереть» ваши изменения.
  4. Отсутствие данных в тестовой базе: При работе с небольшими объемами данных результат запроса может быть пустым для большинства строк, что создает иллюзию неработающего кода.

Реализация заполнения данных через цикл

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


Для Каждого Строка Из Объект.Запасы Цикл
    // Получение страхового запаса из регистра сведений
    ЗапросСЗ = Новый Запрос;
    ЗапросСЗ.Текст = 
    "ВЫБРАТЬ
    |	ТоварныеОграничения.СтраховоеКоличествоЗапаса КАК СтраховоеКоличествоЗапаса
    |ИЗ
    |	РегистрСведений.ТоварныеОграничения КАК ТоварныеОграничения
    |ГДЕ
    |	ТоварныеОграничения.Номенклатура = &Номенклатура
    |	И ТоварныеОграничения.Характеристика = &Характеристика";
    
    ЗапросСЗ.УстановитьПараметр("Номенклатура", Строка.Номенклатура);
    ЗапросСЗ.УстановитьПараметр("Характеристика", Строка.Характеристика);
    
    ВыборкаСЗ = ЗапросСЗ.Выполнить().Выбрать();
    Пока ВыборкаСЗ.Следующий() Цикл
        Строка.СтраховойЗапас = ВыборкаСЗ.СтраховоеКоличествоЗапаса;
    КонецЦикла;

    // Расчет рентабельности по продажам
    ЗапросРент = Новый Запрос;
    ЗапросРент.Текст = "..."; // Весь текст запроса к Выручке и Себестоимости
    ЗапросРент.УстановитьПараметр("Номенклатура", Строка.Номенклатура);
    ЗапросРент.УстановитьПараметр("Характеристика", Строка.Характеристика);
    
    ВыборкаРент = ЗапросРент.Выполнить().Выбрать();
    Пока ВыборкаРент.Следующий() Цикл
        Строка.Рентабельность = ВыборкаРент.Рентабельность;
    КонецЦикла;
КонецЦикла;

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

Оптимизация: использование временных таблиц и одного запроса

Чтобы избежать «подвисания» системы, выясним, как собрать все данные одним пакетом. Правильный алгоритм действий выглядит так:

  1. Выгружаем ключевые поля (Номенклатура, Характеристика) из Объект.Запасы в таблицу значений.
  2. Передаем эту таблицу в запрос как параметр и помещаем во временную таблицу (ВТ).
  3. Соединяем ВТ с регистрами ТоварныеОграничения и ВыручкаИСебестоимостьПродаж.
  4. Выполняем запрос один раз и обходим результат, сопоставляя данные со строками объекта.

Для сопоставления данных удобно использовать метод НайтиСледующий или предварительно создать Соответствие, где ключом будет структура с номенклатурой и характеристикой. Посмотрим на пример создания структуры поиска:


// Пример создания структуры для поиска по нескольким полям
ПараметрыПоиска = Новый Структура("Номенклатура, Характеристика", ТекущаяНоменклатура, ТекущаяХарактеристика);

Методы принудительного обновления формы

Если данные в реквизитах объекта изменились, но форма их «не видит», попробуем применить следующие инструменты:

1. Метод Обновить(): Применяется к элементам формы (таблицам), чтобы перерисовать их содержимое. Однако, если данные связаны напрямую с реквизитом Объект, система обычно делает это автоматически.

2. ЗначениеВРеквизитФормы: Если расчеты производились в серверной процедуре над прикладным объектом, необходимо явно передать данные обратно в форму командой ЗначениеВРеквизитФормы(Объект).

3. Оповещение об изменении: В некоторых случаях помогает вызов ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура")), если таблица завязана на динамические данные.

Поиск точки входа в типовой механизм

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

  1. Запустим конфигуратор и включим Замер производительности.
  2. В режиме предприятия нажмем кнопку перехода на шаг, где заполняется таблица Запасы.
  3. Остановим замер и проанализируем дерево вызовов. Ищем процедуры с названиями типа РассчитатьРекомендации, ЗаполнитьТаблицуЗапасов или обращения к общему модулю ЗапасыСервер.
  4. Именно в этих процедурах (лучше всего использовать расширение с аннотацией &После) следует внедрять свой код заполнения дополнительных реквизитов.

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

← На главную