При настройке обмена данными между конфигурациями (например, из УПП 1.3 в Бухгалтерию предприятия 3.0) часто возникает задача переноса специфических данных, которых нет в типовой структуре приемника. Оптимальным решением в таких случаях является использование механизма дополнительных реквизитов. Однако разработчики нередко сталкиваются с ситуацией: код успешно выполняется, данные записываются в табличную часть объекта, но при открытии карточки в интерфейсе новые поля попросту отсутствуют. Рассмотрим подробнее, почему это происходит и как правильно настроить программное заполнение свойств в конфигурациях на базе БСП (Библиотеки стандартных подсистем).
Для начала проанализируем, как работают дополнительные реквизиты в современных конфигурациях. В отличие от старых систем, где дополнительные свойства часто выводились на форму жестким кодом, в БП 3.0 форма объекта строится динамически. За это отвечает программный интерфейс БСП.
Данные хранятся в табличной части ДополнительныеРеквизиты самого объекта (например, справочника ОсновныеСредства). Но наличие записи в этой таблице — лишь половина дела. Чтобы форма "поняла", что этот реквизит нужно отрисовать, он должен быть зарегистрирован в справочнике НаборыДополнительныхРеквизитовИСведений.
Выясним причину проблемы автора: в коде происходит поиск свойства в ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения по наименованию. Если свойство найдено, оно добавляется в объект. Но если это свойство не включено в Набор, предназначенный именно для справочника "Основные средства", механизм БСП проигнорирует его при отрисовке формы. Форма считывает список доступных полей не из табличной части объекта, а из состава назначенного ему набора.
Перед тем как приступать к написанию кода в обработчике "После загрузки", необходимо убедиться, что в информационной базе приемнике (БП 3.0) выполнены следующие действия:
Если вы создали реквизиты программно или вручную, но они находятся в "чужом" наборе или вообще не привязаны к набору "Основные средства", они не появятся на форме справочника ОсновныеСредства.
Рассмотрим пример кода, который позволит правильно заполнить данные. Важно не только найти само свойство, но и убедиться, что передаваемое значение соответствует типу этого свойства. Если свойство имеет тип "Дополнительное значение", то в поле Значение должна попасть ссылка на элемент справочника ЗначенияСвойствОбъектов, а не просто строка.
Проанализируем исправленный алгоритм для обработчика ПослеЗагрузки:
Если ПараметрыОбъекта <> Неопределено И ТипЗнч(ПараметрыОбъекта) = Тип("Структура") Тогда
// Очищать ли всю таблицу - зависит от бизнес-логики.
// Если мы обновляем только часть данных, лучше искать существующие строки.
// Объект.ДополнительныеРеквизиты.Очистить();
// Массив соответствий имен параметров и имен свойств в БП
СоответствиеСвойств = Новый Соответствие;
СоответствиеСвойств.Вставить("упп_ВидДвигателя", "Вид двигателя");
СоответствиеСвойств.Вставить("упп_ГабаритныеРазмеры", "Габаритные размеры");
СоответствиеСвойств.Вставить("упп_ГаражныйНомерТС", "Гаражный номер ТС");
Для Каждого КлючЗначение Из СоответствиеСвойств Цикл
ИмяПараметра = КлючЗначение.Ключ;
ИмяСвойства = КлючЗначение.Значение;
Если ПараметрыОбъекта.Свойство(ИмяПараметра) Тогда
ЗначениеИзУПП = ПараметрыОбъекта[ИмяПараметра];
// Ищем ссылку на свойство в ПВХ
СсылкаНаСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ИмяСвойства);
Если Не СсылкаНаСвойство.Пустая() Тогда
// Ищем, нет ли уже такой строки в ТЧ объекта
СтрокаСвойства = Объект.ДополнительныеРеквизиты.Найти(СсылкаНаСвойство, "Свойство");
Если СтрокаСвойства = Неопределено Тогда
СтрокаСвойства = Объект.ДополнительныеРеквизиты.Добавить();
СтрокаСвойства.Свойство = СсылкаНаСвойство;
КонецЕсли;
// Обработка типа значения.
// Если свойство текстовое - пишем напрямую.
// Если свойство имеет тип "Дополнительное значение" (список) -
// нужно найти соответствующую ссылку в справочнике ЗначенияСвойствОбъектов.
ТипСвойства = СсылкаНаСвойство.ТипЗначения;
Если ТипСвойства.СодержитТип(Тип("СправочникСсылка.ЗначенияСвойствОбъектов")) Тогда
// Здесь должна быть логика поиска/создания значения в справочнике-владельце
СтрокаСвойства.Значение = НайтиСоздатьЗначениеСвойства(СсылкаНаСвойство, ЗначениеИзУПП);
Иначе
СтрокаСвойства.Значение = ЗначениеИзУПП;
КонецЕсли;
// Поле ТекстоваяСтрока полезно для кэширования представления
СтрокаСвойства.ТекстоваяСтрока = Строка(ЗначениеИзУПП);
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Не забываем записать объект, если обработчик это подразумевает
// В КД 2.0 в "ПослеЗагрузки" объект обычно записывается автоматически позже,
// но при ручном вызове Записать() нужно быть осторожным.
КонецЕсли;
Одной из скрытых проблем является несоответствие типов. Посмотрим на ситуацию: в УПП реквизит "Год изготовления" может быть числом, а в БП дополнительный реквизит создан с типом "Строка". При загрузке через ПараметрыОбъекта тип может не преобразоваться автоматически.
Важный момент: если свойство в ПВХ настроено как список (тип Значение свойства объектов), то запись в поле Значение обычной строки приведет к тому, что БСП не сможет отобразить это значение на форме, так как оно не проходит валидацию по типу данных. В таком случае в интерфейсе поле будет выглядеть пустым, хотя в базе данных строка таблицы заполнена текстом.
В приведенном коде используется метод НайтиПоНаименованию. Проанализируем риски этого подхода:
Чтобы избежать ошибок ручного заполнения табличной части, в некоторых случаях можно воспользоваться методами программного интерфейса БСП. Например, вызвать процедуры из общего модуля УправлениеСвойствами. Однако при конвертации данных (КД 2.0) мы работаем с объектом напрямую, поэтому ручное заполнение ТЧ остается наиболее прозрачным способом.
После выполнения загрузки и записи объекта рекомендуется проверить его через консоль запросов или обработку "Редактирование реквизитов", чтобы убедиться, что колонки Свойство и Значение заполнены ссылками правильного типа. Если данные на месте, но формы по-прежнему их не показывают — возвращайтесь к проверке справочника Наборы дополнительных реквизитов и сведений. Именно там кроется 90% причин "невидимости" полей.