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