Как заменить стандартную форму документа промежуточной формой и вернуть данные в стандартную

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача: при создании документа на основании другого объекта необходимо сначала показать пользователю вспомогательное окно для ввода уточняющих данных, а уже затем открыть основную форму нового документа с учетом этих данных. Рассмотрим, как правильно реализовать этот механизм, избежав типичных ошибок вроде бесконечной рекурсии или потери данных заполнения.

Механизм подмены формы через ОбработкаПолученияФормы

Для того чтобы система вместо стандартной формы открыла нашу вспомогательную, мы будем использовать обработчик события ОбработкаПолученияФормы в модуле менеджера документа. Проанализируем ситуацию: когда платформа пытается открыть форму, вызывается это событие, где мы можем вмешаться и подменить путь к форме.

Однако здесь кроется главная ловушка — рекурсия. Если мы просто укажем свою форму, а затем из своей формы попытаемся снова вызвать ОткрытьФорму для этого же документа, система снова попадет в этот же обработчик и снова откроет нашу вспомогательную форму. Чтобы этого избежать, нам необходимо использовать специальный флаг-маркер.

Разберем пример кода в модуле менеджера документа:


Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
    
    // Нас интересует только основная форма объекта
    Если ВидФормы = "ФормаОбъекта" Тогда
        
        // Проверяем, нет ли в параметрах нашего секретного флага
        Если Параметры.Свойство("ПропуститьПодмену") И Параметры.ПропуститьПодмену = Истина Тогда
            // Если флаг есть, значит мы вызываем форму программно из нашей промежуточной формы
            // Ничего не меняем, даем платформе открыть стандартную форму
            Возврат;
        КонецЕсли;
        
        // Если флага нет и это создание нового документа (например, ЗначениеЗаполнения заполнено)
        Если Параметры.Свойство("ЗначениеЗаполнения") Тогда
            ВыбраннаяФорма = "Документ.НашДокумент.Форма.ВспомогательнаяФорма";
            СтандартнаяОбработка = Ложь;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Передача данных из вспомогательной формы в основную

Когда пользователь заполнил необходимые данные в нашей вспомогательной форме и нажал кнопку "Ок" (или "Продолжить"), нам нужно программно открыть стандартную форму. Основная сложность здесь заключается в сохранении контекста ЗначениеЗаполнения, который платформа подготовила для ввода на основании.

В процедуре ПриСозданииНаСервере нашей вспомогательной формы параметры, переданные платформой, доступны в свойстве Параметры. Важно понимать, что тип этих данных — ДанныеФормыСтруктура, и они "живут" только в момент создания формы. Чтобы использовать их позже, мы должны либо объявить ключевые параметры в метаданных формы, либо сохранить их в реквизиты формы.

Рассмотрим, как выглядит процедура открытия основной формы из вспомогательной:


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

Как гарантировать передачу всех системных параметров

Иногда параметров в ОбработкаПолученияФормы очень много (ключи уникальности, навигационные ссылки и т.д.), и перечислять их вручную неудобно. Выясним причину, по которой обычное копирование может не сработать: Параметры — это не обычная структура, а системный объект. Для "чистого" копирования данных можно использовать сериализацию, хотя в простых случаях достаточно метода ЗаполнитьЗначенияСвойств.

Проанализируем продвинутый способ получения структуры данных формы, если нам нужно передать абсолютно всё, что пришло в форму:


&НаСервереБезКонтекста
Функция ПолучитьСтруктуруИзДанныхФормы(ДанныеФормы)
    Результат = Новый Структура;
    // Используем СериализаторXDTO или перебор свойств, если ключи известны
    // Для параметров формы часто подходит простой перебор, если это коллекция
    Для Каждого Элемент Из ДанныеФормы Цикл
        Результат.Вставить(Элемент.Ключ, Элемент.Значение);
    КонецЦикла;
    Возврат Результат;
КонецФункции

Альтернативный подход: Использование команд

Если задача стоит именно в "Вводе на основании", рассмотрим более изящное решение, которое предлагает современная архитектура 1С. Вместо перехвата системных событий получения формы, мы можем создать свою Команду.

  1. Создаем общую команду или команду документа и включаем её в группу Ввод на основании.
  2. В коде команды открываем нашу вспомогательную форму.
  3. В этой форме собираем данные и открываем форму нового документа стандартным способом.

Этот путь гораздо стабильнее, так как мы не вмешиваемся в работу ОбработкаПолученияФормы, которая вызывается при каждом открытии любой карточки документа (что может давать лишнюю нагрузку на сервер). Мы работаем только в конкретном сценарии нажатия кнопки пользователем.

Важные нюансы управления окнами

При закрытии вспомогательной формы и открытии основной важно следить за свойством ВладелецФормы. Если вспомогательная форма открывалась из списка документов, то ЭтаФорма.ВладелецФормы будет содержать ссылку на этот список. Передавая его в ОткрытьФорму, мы гарантируем, что после записи нового документа список обновится, а фокус управления вернется в нужное место.

Также помните про КлючУникальности. Если ваша вспомогательная форма открывается несколько раз, убедитесь, что вы правильно управляете уникальностью окон, чтобы не возникло конфликтов при попытке открыть несколько документов одновременно.

Резюмируем: для успешной подмены формы используйте флаг ПропуститьПодмену в параметрах, корректно передавайте ЗначениеЗаполнения для запуска стандартного механизма ОбработкаЗаполнения в модуле объекта и старайтесь отдавать предпочтение явным командам расширения, если это позволяет бизнес-логика задачи.

← На главную