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

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

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

В обычных формах (7.7 или 8.2) эта задача решалась через событие ПриПолученииДанных, которое позволяло динамически «подтягивать» значения для видимых строк. В управляемом интерфейсе (УФ) подход изменился. Рассмотрим подробнее, как реализовать этот механизм эффективно и красиво.

Почему нельзя использовать ПриПолученииДанных

Проанализируем ситуацию: в управляемых формах событие ПриПолученииДанных существует только у динамических списков. У табличных частей документов такого события нет. Платформа 8.3 ориентирована на минимизацию серверных вызовов. Если бы мы пытались получать данные для каждой ячейки при отрисовке, это бы катастрофически замедлило работу интерфейса. Поэтому нам необходимо выбрать один из программных методов заполнения данных на клиенте или сервере.

Способ 1. Создание реквизита формы и массовое заполнение

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

  1. Откроем форму документа и перейдем на вкладку «Реквизиты».
  2. Найдем нашу табличную часть (например, Объект.Товары) и добавим в неё новый реквизит (не колонку объекта, а именно реквизит формы внутри ТЧ). Назовем его ДопСвойствоНоменклатуры.
  3. Перетащим этот реквизит в элементы формы, чтобы появилась колонка в таблице.

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

Рассмотрим пример кода для массового заполнения:


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

Эту процедуру необходимо вызывать в следующих событиях:

Способ 2. Обработка изменения конкретной строки

Чтобы данные актуализировались сразу после того, как пользователь выбрал номенклатуру в строке, нам нужно обработать событие ПриИзменении поля Номенклатура.

Посмотрим на пример реализации:


&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
    СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;
    Если СтрокаТаблицы <> Неопределено Тогда
        // Получаем значение свойства с сервера
        СтрокаТаблицы.ДопСвойствоНоменклатуры = ПолучитьСвойствоНаСервере(СтрокаТаблицы.Номенклатура);
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСвойствоНаСервере(Знач СсылкаНоменклатура)
    // Возвращаем значение из регистра сведений
    Возврат РегистрыСведений.ДополнительныеСвойстваНоменклатуры.ПолучитьЗначение(СсылкаНоменклатура);
КонецФункции

Важный момент: использование &НаСервереБезКонтекста критически важно для производительности, так как при вызове такой функции на сервер не передается вся форма (данные объекта), а только один параметр — ссылка на номенклатуру.

Способ 3. Использование механизмов БСП (Библиотека стандартных подсистем)

Если ваша конфигурация разработана на базе БСП (УТ 11, ERP, КА, БП 3.0), то задача вывода свойств значительно упрощается. В БСП существует подсистема «Свойства». Дополнительные реквизиты, созданные через эту подсистему, часто можно вывести на форму без написания кода, используя команду «Изменить форму».

Проанализируем программный вывод через БСП. В модуле УправлениеСвойствами есть функции для работы с дополнительными реквизитами. Если свойство зарегистрировано как «Дополнительный реквизит», Платформа позволяет настроить его отображение в списке через механизм характеристик.

Преимущества использования БСП:

Способ 4. Использование характеристик номенклатуры

Если «дополнительное свойство» логически определяет специфику товара (например, размер или цвет), рассмотрите возможность использования справочника ХарактеристикиНоменклатуры. В управляемых формах для поля Характеристика можно настроить «Связи параметров выбора».

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

Оптимизация и расширения

Если вы работаете в типовой конфигурации и не хотите снимать её с поддержки, используйте Расширения. Вы можете добавить реквизит формы в ТЧ через расширение и прописать логику заполнения в обработчиках &После или &Вместо.

Рассмотрим, как это выглядит в расширении:

  1. Создаем расширение и добавляем в него форму документа.
  2. Добавляем реквизит формы в табличную часть.
  3. Создаем метод &После("ПриСозданииНаСервере"), где вызываем наш запрос для заполнения всех строк.

Резюме по выбору метода:

  1. Если свойство нужно только для чтения и только в одном документе — используйте Способ 1 (Реквизит формы + Запрос).
  2. Если конфигурация типовая и свойство уже заведено как доп. реквизит — используйте механизмы БСП.
  3. Если свойство должно храниться вечно и участвовать в отчетах — лучше добавить его как реальный реквизит в табличную часть объекта, хотя это и увеличит размер базы данных.

Мы проанализировали основные подходы к решению задачи. Главный вывод: в управляемых формах всегда стремитесь к массовой обработке данных на сервере при открытии формы и точечным бесконтекстным вызовам при интерактивном изменении данных пользователем. Это обеспечит высокую скорость работы интерфейса и удобство для конечного пользователя.

← На главную