Как для одного документа 1С использовать разные формы в зависимости от способа создания?

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

В процессе разработки конфигураций 1С часто возникает задача объединить схожие по своей сути бизнес-процессы в рамках одного объекта. Например, документ «Заявка на ремонт» и создаваемый на его основе «Заказ-наряд» могут иметь общую структуру данных, но должны представляться пользователю по-разному. Разберем, как реализовать механизм, при котором для одного и того же документа будут открываться разные формы в зависимости от контекста: создается ли он "с нуля" или вводом на основании.

Решение 1: Определяем нужную форму при открытии

Основная задача — научить систему понимать, какую из двух форм (например, «ФормаЗаявки» или «ФормаЗаказНаряда») следует открыть. Самый надежный признак, по которому можно их различить, — это способ создания документа.

Проанализируем логику:

Именно наличие или отсутствие заполненного основания и будет служить для нас главным условием для выбора формы. Существует несколько способов реализовать эту логику.

Способ А: Использование обработчика ОбработкаПолученияФормы (рекомендуемый)

Это наиболее правильный и современный подход для управляемых форм. Логика выбора формы размещается в модуле самого объекта документа. Этот обработчик срабатывает каждый раз, когда система пытается получить форму для объекта, и позволяет нам вмешаться в этот процесс.

  1. Перейдите в модуль объекта вашего документа (например, Документ.ЗаказНаряд).
  2. Создайте процедуру-обработчик события ОбработкаПолученияФормы.
  3. Внутри обработчика проанализируем параметр ДанныеЗаполнения, в который платформа передает данные из документа-основания при вводе на основании.

Посмотрим на пример кода:


Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)

    // Проверяем, что форма открывается для нового, еще не записанного документа,
    // и что у него есть данные для заполнения (т.е. он создается на основании)
    Если Параметры.Ключ.Пустая() И Параметры.ЗначениеЗаполнения <> Неопределено Тогда

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

    КонецЕсли;

    // Если документ не новый или создается без основания, платформа сама откроет
    // основную форму документа ("ФормаЗаявки"), указанную в свойствах конфигурации.

КонецПроцедуры

Важно: не забудьте в свойствах самого документа в конфигураторе указать основную форму (в нашем примере это будет «ФормаЗаявки»).

Способ Б: Использование дополнительного реквизита

Этот подход также рабочий и был предложен в обсуждении. Его суть в том, чтобы завести в документе специальный реквизит, например, ВидОперации (тип — перечисление или строка), который будет служить флагом.

Разберем по шагам:

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

Этот способ более гибкий, если у вас может быть больше двух видов операций для одного документа.

Решение 2: Настраиваем заголовок команды «Создать на основании»

После того как мы реализовали основную логику, столкнемся с проблемой в интерфейсе. Когда пользователь откроет «Заявку на ремонт» и нажмет кнопку «Создать на основании», он увидит стандартное название команды, например, «Заказ-наряд». Это может быть неинформативно. Гораздо лучше, если команда будет называться «Создать Заказ-наряд».

Попытка изменить свойство Имя команды, как в примере из обсуждения, приведет к ошибке «Поле объекта недоступно для записи». Это происходит потому, что Имя — это системный идентификатор элемента, и его нельзя менять в режиме исполнения.

Для изменения текста, который видит пользователь, нужно использовать свойство Заголовок. Для интерактивной проверки структуры и свойств элементов формы в пользовательском сеансе подойдёт обработка для редактирования форм в режиме «1С:Предприятие».

Разберем, как это сделать правильно. Код нужно размещать в модуле формы документа-основания (в нашем примере — в форме «Заявки на ремонт»), в обработчике события ПриСозданииНаСервере.

Посмотрим на пример:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // Имя команды "Создать на основании" для конкретного документа обычно формируется
    // платформой как: "Документ" + [ИмяДокумента] + "СоздатьНаОсновании"
    ИмяНужнойКоманды = "ДокументЗаказНарядСоздатьНаОсновании";

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

КонецПроцедуры

Таким образом, мы добиваемся не только корректной работы механизма, но и создаем понятный и удобный для пользователя интерфейс. Объединив эти два решения, вы сможете эффективно использовать один объект документа для нескольких связанных бизнес-задач.

← На главную