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