При программном заполнении дополнительных реквизитов (подсистема «Свойства» БСП) разработчики нередко сталкиваются с ситуацией: синтаксических ошибок платформа не выдает, код выполняется, однако при открытии карточки элемента новые значения отсутствуют. Разберем типичную ошибку и рассмотрим правильные варианты заполнения табличной части ДополнительныеРеквизиты.
Посмотрим на исходный пример некорректного кода:
Площадь = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Площадь (м2)");
НовыйРеквизит = НовНоменклатура.Ссылка.ПолучитьОбъект().ДополнительныеРеквизиты.Добавить();
НовыйРеквизит.Свойство = Площадь;
НовыйРеквизит.Значение = Чтение.Значение;
Проанализируем ситуацию и выясним причину такого поведения. Метод ПолучитьОбъект() считывает данные из базы и создает в оперативной памяти отдельный экземпляр объекта. Конструкция вида НовНоменклатура.Ссылка.ПолучитьОбъект().ДополнительныеРеквизиты.Добавить() создает объект «в воздухе», добавляет строку в его табличную часть и тут же теряет ссылку на сам объект.
В итоге модифицированный объект уничтожается сборщиком мусора платформы 1С, так как ссылка на него не была сохранена в переменной, а метод Записать() так и не был вызван для сохранения данных в базу.
Разберем базовый способ исправления. Для успешного сохранения необходимо поместить объект в переменную, добавить и заполнить строку, после чего явно вызвать метод Записать().
// 1. Находим необходимое свойство
Площадь = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Площадь (м2)");
Если ЗначениеЗаполнено(Площадь) Тогда
// 2. Получаем объект номенклатуры в переменную
Товар = НовНоменклатура.Ссылка.ПолучитьОбъект();
// 3. Добавляем новую строку в табличную часть
НовыйРеквизит = Товар.ДополнительныеРеквизиты.Добавить();
НовыйРеквизит.Свойство = Площадь;
НовыйРеквизит.Значение = Число(Чтение.Значение); // приводим тип к числу, если реквизит числовой
// 4. Фиксируем изменения в базе данных
Товар.Записать();
КонецЕсли;
Если код выполняется в цикле или при повторной загрузке данных, прямой вызов метода Добавить() приведет к дублированию строк в табличной части ДополнительныеРеквизиты. Посмотрим, как корректно выполнить поиск существующего значения перед добавлением нового:
Товар = НовНоменклатура.Ссылка.ПолучитьОбъект();
СвойствоПлощадь = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Площадь (м2)");
Если ЗначениеЗаполнено(СвойствоПлощадь) Тогда
// Ищем строку с этим свойством в объекте
СтрокаРеквизита = Товар.ДополнительныеРеквизиты.Найти(СвойствоПлощадь, "Свойство");
// Если строка не найдена - создаем новую
Если СтрокаРеквизита = Неопределено Тогда
СтрокаРеквизита = Товар.ДополнительныеРеквизиты.Добавить();
СтрокаРеквизита.Свойство = СвойствоПлощадь;
КонецЕсли;
// Заполняем значение
СтрокаРеквизита.Значение = Чтение.Значение;
Товар.Записать();
КонецЕсли;
В типовых конфигурациях (ERP, КА, УТ, УНФ, БП 3.0) прямое редактирование табличной части часто не требуется. Для этого существует специальный общий модуль УправлениеСвойствами. Использование API Библиотеки стандартных подсистем позволяет избежать ошибок валидации и автоматически поддерживает логику типовой конфигурации:
СвойствоПлощадь = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Площадь (м2)");
Если ЗначениеЗаполнено(СвойствоПлощадь) Тогда
// Записываем свойство напрямую через БСП (можно передавать как ссылку, так и объект)
УправлениеСвойствами.ЗаписатьСвойствоОбъекта(НовНоменклатура.Ссылка, СвойствоПлощадь, Число(Чтение.Значение));
КонецЕсли;
Рассмотрим ключевые моменты, которые необходимо учитывать при программном заполнении реквизитов:
Число или Дата, обязательна явная типизация через Число(...) или Дата(...).Дополнительное значение, в поле Значение нельзя передавать строку. Необходимо передавать ссылку на элемент справочника ЗначенияСвойствОбъектов, где реквизит Владелец совпадает с используемым свойством.НаборыДополнительныхРеквизитовИСведений (например, для конкретного вида номенклатуры).НайтиПоНаименованию() находит первый попавшийся элемент. Если в базе присутствуют одноименные свойства, безопаснее использовать поиск по коду, уникальному идентификатору или производить отбор по владельцу.