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