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