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

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

При разработке интеграций, обработок загрузки данных или автоматического заполнения справочников в конфигурациях на базе 1С:Библиотеки стандартных подсистем (БСП) (таких как «1С:Розница», «1С:Управление торговлей», «1С:ERP») программисты часто сталкиваются со следующей проблемой. Дополнительные реквизиты заполняются программно в табличную часть объекта, данные успешно записываются в базу данных, однако при открытии формы элемента эти реквизиты остаются пустыми.

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

---

Выясняем причину: несоответствие типов данных

Рассмотрим стандартный сценарий, в котором совершается типичная ошибка. Разработчик пытается добавить значение в табличную часть ДополнительныеРеквизиты справочника ХарактеристикиНоменклатуры напрямую:


ОбъектХарактеристика = СсылкаНаХарактеристику.ПолучитьОбъект();                    
ДопРеквизиты = ОбъектХарактеристика.ДополнительныеРеквизиты;

СтрокаДопРеквизитов = ДопРеквизиты.Добавить();
СтрокаДопРеквизитов.Свойство = ВидСвойства; // Ссылка на ПВХ "ДополнительныеРеквизитыИСведения"
СтрокаДопРеквизитов.Значение = "Пластик"; // Простая текстовая строка
ОбъектХарактеристика.Записать();

В данном коде в качестве значения реквизита записывается обычная строка "Пластик". Однако тип значения дополнительного реквизита в Плане видов характеристик (ПВХ) ДополнительныеРеквизитыИСведения настроен как ссылочный — Дополнительное значение.

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

Правило: Если дополнительный реквизит имеет тип «Дополнительное значение», в табличную часть необходимо записывать исключительно ссылку на элемент справочника ЗначенияСвойствОбъектов (или ЗначенияСвойствОбъектовИерархия), у которого владельцем установлен соответствующий элемент ПВХ.

---

Шаг 1. Правильное программное заполнение с поиском значения

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

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


// Шаг 1. Получаем объект характеристики для изменения
ОбъектХарактеристика = СсылкаНаХарактеристику.ПолучитьОбъект();

// Шаг 2. Находим само свойство в ПВХ (например, по наименованию)
СвойствоМатериал = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Материал");

Если СвойствоМатериал.Пустая() Тогда
    ВызватьИсключение "Не найдено дополнительное свойство 'Материал'!";
КонецЕсли;

// Шаг 3. Ищем или создаем значение "Пластик" для этого свойства
ИскомоеЗначениеТекст = "Пластик";
ЗначениеСвойстваСсылка = Справочники.ЗначенияСвойствОбъектов.НайтиПоНаименованию(ИскомоеЗначениеТекст, Истина, , СвойствоМатериал);

Если ЗначениеСвойстваСсылка.Пустая() Тогда
    // Создаем новое значение, если его еще нет в системе
    НовоеЗначениеОбъект = Справочники.ЗначенияСвойствОбъектов.СоздатьЭлемент();
    НовоеЗначениеОбъект.Наименование = ИскомоеЗначениеТекст;
    НовоеЗначениеОбъект.Владелец     = СвойствоМатериал;
    НовоеЗначениеОбъект.Записать();
    ЗначениеСвойстваСсылка = НовоеЗначениеОбъект.Ссылка;
КонецЕсли;

// Шаг 4. Очищаем старые значения этого свойства из ТЧ характеристики (избегаем дублирования)
ТабличнаяЧастьСвойств = ОбъектХарактеристика.ДополнительныеРеквизиты;
СтрокиДляУдаления = ТабличнаяЧастьСвойств.НайтиСтроки(Новый Структура("Свойство", СвойствоМатериал));
Для Каждого СтрокаУдаления Из СтрокиДляУдаления Цикл
    ТабличнаяЧастьСвойств.Удалить(СтрокаУдаления);
КонецЦикла;

// Шаг 5. Записываем корректное ссылочное значение
НоваяСтрока = ТабличнаяЧастьСвойств.Добавить();
НоваяСтрока.Свойство = СвойствоМатериал;
НоваяСтрока.Значение = ЗначениеСвойстваСсылка;

ОбъектХарактеристика.Записать();

---

Шаг 2. Использование стандартных методов БСП (Рекомендуемый способ)

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

Для записи значений свойств воспользуемся методом УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(). Этот метод самостоятельно перезаписывает значения свойств в транзакции:


// Подготовим таблицу значений для передачи в метод БСП
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство", Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения"));
ТаблицаСвойств.Колонки.Добавить("Значение"); // Тип произвольный

// Заполняем строку параметров
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = СвойствоМатериал;
НоваяСтрока.Значение = ЗначениеСвойстваСсылка;

// Записываем свойства через штатный программный интерфейс БСП
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(СсылкаНаХарактеристику, ТаблицаСвойств);

Этот способ лаконичен, безопасен и гарантирует, что структура данных в базе данных будет абсолютно консистентной.

---

Шаг 3. Взаимодействие с динамическими реквизитами на управляемой форме

Что делать, если вам необходимо заполнять дополнительные реквизиты непосредственно в открытой форме элемента (например, при нажатии кнопки в форме самой характеристики или из внешней обработки, работающей с контекстом формы)?

При попытке напрямую получить объект формы через ПолучитьОбъект() и присвоить его реквизиту формы Объект разработчик сталкивается с системной ошибкой платформы: «Нельзя изменять поле, содержащее объект данных формы». Это связано с тем, что форма управляет своими данными сама.

На управляемой форме дополнительные реквизиты выводятся динамически. БСП не создает элементы формы с простыми именами. Чтобы избежать коллизий, система генерирует имена по шаблону: ДополнительныйРеквизит_Значение_[УникальныйИдентификаторСвойства]. Соответствие реальных свойств элементам формы хранится в служебной таблице Свойства_ОписаниеДополнительныхРеквизитов на форме.

Рассмотрим функцию, которая позволяет корректно установить значение дополнительного реквизита на форме, используя структуру данных БСП:


Функция УстановитьЗначениеДополнительногоРеквизитаВФорме(Форма, Свойство, Значение, Ошибка = "") Экспорт
    
    Попытка
        // Получаем таблицу описания свойств из контекста формы
        ТаблицаОписания = Форма.Свойства_ОписаниеДополнительныхРеквизитов;
    Исключение
        Ошибка = "Для данного типа объектов дополнительные реквизиты не подключены в форме.";
        Возврат Ложь;
    КонецПопытки;
    
    // Ищем строку описания нужного нам свойства
    СтрокиОписанияРеквизита = ТаблицаОписания.НайтиСтроки(Новый Структура("Свойство", Свойство));
    Если СтрокиОписанияРеквизита.Количество() Тогда
        // Получаем уникальное имя динамического элемента на форме
        ИмяЭлементаФормы = СтрокиОписанияРеквизита[0].ИмяРеквизитаЗначение;
        
        Попытка
            // Устанавливаем новое значение непосредственно в реквизит формы
            Форма[ИмяЭлементаФормы] = Значение;
        Исключение
            Ошибка = "Невозможно установить значение для динамического реквизита формы.";
            Возврат Ложь;
        КонецПопытки;
        
        // Обязательно взводим флаг модифицированности формы, чтобы пользователь мог сохранить изменения
        Форма.Модифицированность = Истина;
        
        Возврат Истина;
    Иначе
        Ошибка = "Указанное свойство не подключено для данного объекта.";
        Возврат Ложь;
    КонецЕсли;        
    
КонецФункции

Вызов этой процедуры из модуля управляемой формы будет выглядеть следующим образом:


ОшибкаОписание = "";
Успешно = УстановитьЗначениеДополнительногоРеквизитаВФорме(ЭтаФорма, СвойствоМатериал, ЗначениеСвойстваСсылка, ОшибкаОписание);

Если Не Успешно Тогда
    Сообщить(ОшибкаОписание);КонецЕсли;

Если вы обновили значения дополнительных реквизитов объекта в базе данных программно, а форма элемента в этот момент открыта у пользователя, то форма сама не перерисуется. Чтобы принудительно обновить отображение дополнительных реквизитов на форме, используйте методы БСП:

---

Резюме для разработчика

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

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