Почему дополнительный реквизит 1С виден в базе данных, но пропадает на управляемой форме при редактировании?

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

В практике разработки на платформе «1С:Предприятие 8.3» часто возникает загадочная ситуация: программно записанный реквизит ведет себя как «призрак». Консоль запросов без проблем извлекает значение из базы данных, при открытии карточки объекта в режиме просмотра значение может отображаться, но стоит пользователю нажать кнопку «Редактировать» или «Записать», как реквизит бесследно исчезает.

В этой статье мы подробно разберем, почему возникает подобный эффект «в базе есть, а на форме нет», проанализируем влияние режима ОбменДанными.Загрузка = Истина, выявим синтаксические ошибки при работе с дополнительными свойствами и рассмотрим правильный, безопасный шаблон программной записи дополнительных реквизитов с использованием Библиотеки стандартных подсистем (БСП).

---

Анализ проблемы: почему возникает эффект «призрака»?

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


ОбъектСсылки = Ссылка.ПолучитьОбъект();
НовоеСвойство = ОбъектСсылки.ДополнительныеРеквизиты.Добавить();
НовоеСвойство.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("У поставщика");
НовоеСвойство.Значение = "ТекстовоеЗначение"; // Здесь пишется обычная строка!
ОбъектСсылки.ОбменДанными.Загрузка = Истина;
ОбъектСсылки.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов");
ОбъектСсылки.Записать();

Проанализируем по шагам, что происходит в СУБД и на уровне платформы при выполнении этого кода:

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

---

Синтаксическая ошибка в работе со структурой дополнительных свойств

Обратим внимание на следующую строку из приведенного выше примера:


ОбъектСсылки.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов");

В данном вызове содержатся сразу две критические ошибки:

Правильный синтаксис для отключения регистрации изменений выглядит следующим образом:


ОбъектСсылки.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов", Истина);

---

Как правильно записывать дополнительные реквизиты?

Прямое добавление строк в табличную часть ДополнительныеРеквизиты объекта — это архитектурный антипаттерн при работе с конфигурациями на базе БСП. Такой подход лишает вас возможности автоматического контроля типов данных и связей.

Для корректной работы мы должны использовать специализированный программный интерфейс БСП — общий модуль УправлениеСвойствами. Рассмотрим подробный алгоритм правильной записи.

Шаг 1. Поиск или создание элемента в справочнике «Значения свойств объектов»

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

Шаг 2. Использование метода «ЗаписатьСвойстваУОбъекта»

Этот метод общего модуля УправлениеСвойствами берет на себя всю рутину: он открывает транзакцию, сверяет типы данных по метаданным БСП, осуществляет запись свойств и корректно сохраняет сам объект.

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


// Определим ссылку на объект номенклатуры, для которого пишем реквизит
СсылкаНаОбъект = Справочники.Номенклатура.НайтиПоРеквизиту("Код", "00000001");

Если Не СсылкаНаОбъект.Пустая() Тогда

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

КонецЕсли;

---

Резюме

Для того чтобы избежать ошибок "исчезающих" данных при работе с дополнительными реквизитами БСП, всегда придерживайтесь трех золотых правил разработчика 1С:

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