Как заполнить и отобразить реквизит подчиненного справочника «Единицы измерения» из формы номенклатуры?

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

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

Анализ структуры данных и особенностей конфигурации

Прежде чем переходить к написанию кода, проанализируем взаимосвязь объектов:

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

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

Шаг 1. Запись веса в подчиненный справочник при сохранении номенклатуры

Рассмотрим порядок действий при сохранении формы элемента справочника Номенклатура. В обработчик события ПриЗаписи (или ПередЗаписи) формы добавляем код, который находит подчиненный элемент ЕдиницыИзмерения и обновляет в нем реквизит Вес.

Выполним запрос для поиска подчиненного элемента и перезапишем объект:


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

Запрос.УстановитьПараметр("ЕдиницаПоКлассификатору", БазоваяЕдиницаИзмерения);
Запрос.УстановитьПараметр("Номенклатура", Ссылка);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    ЕдиницаИзмеренияОбъект = Выборка.Ссылка.ПолучитьОбъект();
    ЕдиницаИзмеренияОбъект.Вес = ЭлементыФормы.ВесБазовойЕдиницыИзмерения.Значение;
    
    Попытка
        ЕдиницаИзмеренияОбъект.Записать();
    Исключение
        Сообщить("Ошибка при записи единицы измерения: " + ОписаниеОшибки());
    КонецПопытки;
КонецЦикла;

Важный совет: Подобную логику рекомендуется выносить в модуль объекта СправочникОбъект.Номенклатура в событие ПриЗаписи. Это обеспечит корректное обновление данных не только при интерактивной работе пользователя через форму, но и при программной загрузке или проведении документов.

Шаг 2. Заполнение реквизита формы при открытии элемента номенклатуры

Если вес хранится непосредственно в подчиненной единице измерения, а на форме номенклатуры размещен не связанный с объектом реквизит формы ВесБазовойЕдиницыИзмерения, его необходимо восстанавливать при открытии карточки номенклатуры.

Разберем, как считывать сохраненное значение в событии ПриОткрытии или ПослеЧтенияНаСервере (для обычных форм — в процедуре ПриОткрытии):


Если НЕ ЭтоНовый() Тогда
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ Первые 1
        |	ЕдиницыИзмерения.Вес КАК Вес
        |ИЗ
        |	Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
        |ГДЕ
        |	ЕдиницыИзмерения.Владелец = &Номенклатура
        |	И НЕ ЕдиницыИзмерения.ПометкаУдаления
        |	И ЕдиницыИзмерения.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору";

    Запрос.УстановитьПараметр("ЕдиницаПоКлассификатору", БазоваяЕдиницаИзмерения);
    Запрос.УстановитьПараметр("Номенклатура", Ссылка);

    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        ЭлементыФормы.ВесБазовойЕдиницыИзмерения.Значение = Выборка.Вес;
    КонецЕсли;
КонецЕсли;

Альтернативный вариант: динамический вывод веса в форме списка

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

Проанализируем пример динамического заполнения колонки в форме списка:


Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
    Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
        ДанныеСтроки = ОформлениеСтроки.ДанныеСтроки;
        Если ДанныеСтроки <> Неопределено Тогда
            // Извлекаем вес непосредственно из владельца (Номенклатуры)
            ОформлениеСтроки.Ячейки.Вес.УстановитьТекст(ДанныеСтроки.Ссылка.Владелец.Вес);
        КонецЕсли;
    КонецЦикла;	
КонецПроцедуры

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

← На главную