Как создать единую форму для нескольких схожих документов в 1С?

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

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

1. Централизация кода и логики через общие модули и подписки на события

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

Рассмотрим подробнее каждый механизм:

  1. Общие модули:

    Общие модули – это основной инструмент для централизации программного кода в 1С. Мы можем создавать в них экспортные процедуры и функции, которые будут доступны для вызова из модулей различных объектов конфигурации (документов, справочников) и форм. Это позволяет избежать дублирования кода, упрощает его поддержку и модификацию.

    Преимущества:

    • Переиспользование кода: Однажды написанный код можно использовать многократно в разных местах системы.
    • Упрощение поддержки: Изменения в логике достаточно внести в одном месте (в общем модуле), и они автоматически применятся везде, где используется этот код.
    • Повышение надежности: Уменьшение дублирования кода снижает вероятность ошибок.

    Как это применить:

    Если у нас есть общие расчеты (например, расчет суммы по позициям, определение НДС) или проверки (например, проверка заполнения обязательных реквизитов), которые должны выполняться при работе с разными документами, мы выносим их в общие модули. Создадим, например, общий модуль ВызовыОбщие с экспортными процедурами:

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

    Затем, из модулей документов или форм, мы вызываем эти процедуры:

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

    Важно помнить о свойствах общих модулей, таких как выполнение на клиенте/сервере и контекст, чтобы правильно организовать вызовы.

  2. Подписки на события:

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

    Преимущества:

    • Независимость от типовой конфигурации: Мы можем добавлять или изменять поведение объектов, не затрагивая их основные модули, что критически важно при работе с обновляемыми конфигурациями.
    • Централизованное управление: Один обработчик подписки может реагировать на события многих объектов.

    Как это применить:

    Если нам нужно выполнять общую проверку или заполнение для всех документов типа «Вызов», мы можем создать подписку на событие ПриЗаписи или ОбработкаЗаполнения для всех этих документов.

    
    // Создаем подписку на событие:
    // Имя: ОбработкаЗаполненияДокументовВызова
    // Источник: Документ.ВызовРемонтнойБригады, Документ.ВызовМастера, Документ.ВызовПроверяющего (выбираем нужные объекты)
    // Событие: ОбработкаЗаполнения
    // Обработчик: ВызовыОбщие.ОбработкаЗаполненияДокументовВызова
    
    // Общий модуль: ВызовыОбщие
    Процедура ОбработкаЗаполненияДокументовВызова(Объект, ПараметрыЗаполнения, СтандартнаяОбработка) Экспорт
        Если ПараметрыЗаполнения.Свойство("ТипЗаполнения") Тогда
            Если ПараметрыЗаполнения.ТипЗаполнения = "Копирование" Тогда
                // Дополнительная логика при копировании
            КонецЕсли;
        КонецЕсли;
        // Общее заполнение реквизитов, например
        Если Объект.Комментарий = "" Тогда
            Объект.Комментарий = "Документ создан в " + Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy HH:mm");
        КонецЕсли;
        // И так далее для других общих реквизитов
    КонецПроцедуры
    

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

2. Использование единого документа с "видом операции" и динамическим управлением полями

Это одно из наиболее элегантных и часто применяемых решений для унификации схожих документов. Вместо создания нескольких отдельных документов, мы создаем один, но добавляем в него реквизит, определяющий "вид операции" или "подтип" (например, перечисление ВидВызова с элементами "РемонтнаяБригада", "Мастер", "Проверяющий"). Далее, на основе значения этого реквизита, мы динамически управляем видимостью и доступностью элементов на форме.

  1. Механизм "Вид операции":

    В типовых конфигурациях 1С этот механизм активно используется (например, документ "Поступление (акты, накладные, УПД)" может иметь несколько видов операций, таких как "Покупка, комиссия", "Возврат от комиссионера", каждый из которых определяет свой состав полей и логику). Изменение вида операции динамически меняет интерфейс документа, отображая только релевантные реквизиты и табличные части.

    Как это реализовать:

    • Шаг 1: Консолидация документов. Создадим один документ, например, ВызовУниверсальный. В него мы перенесем все реквизиты, которые были у отдельных документов ВызовРемонтнойБригады, ВызовМастера, ВызовПроверяющего. Специфичные реквизиты, например, "СвязанныйДокументРемонтнойБригады" из исходного сообщения, также добавляются в этот единый документ.
    • Шаг 2: Добавление реквизита "ВидВызова". В документ ВызовУниверсальный добавим новый реквизит ВидВызова типа Перечисление.ВидыВызовов. Это перечисление будет содержать значения "ВызовРемонтнойБригады", "ВызовМастера", "ВызовПроверяющего".
    • Шаг 3: Проектирование формы. На форму документа ВызовУниверсальный разместим все реквизиты, которые могут понадобиться для любого из видов вызова. Сгруппируем специфичные поля в отдельные группы. Например, группа "Реквизиты для Мастера", группа "Реквизиты для Проверяющего".
    • Шаг 4: Динамическое управление видимостью/доступностью. Основная логика будет заключаться в изменении свойств Видимость и Доступность элементов формы в зависимости от значения реквизита ВидВызова.
  2. Функциональные опции:

    Функциональные опции – это объекты конфигурации, которые позволяют включать или выключать определенную функциональность (объекты метаданных, их реквизиты, команды) в прикладном решении без изменения кода. Они могут напрямую влиять на видимость реквизитов и команд на форме.

    Применение и ограничения:

    Хотя функциональные опции могут управлять видимостью реквизитов, их основное предназначение – это отключение целых блоков функциональности, а не динамическое изменение формы в зависимости от значения другого поля в текущем документе. На форуме было отмечено, что функциональной опцией нельзя изменить видимость реквизитов объекта в зависимости от другого поля (например, реквизита "ВидВызова" текущего документа) напрямую, без дополнительной программной обработки. Значение функциональной опции обычно хранится в константе или регистре сведений с измерениями (например, для разных организаций) и определяет глобальные или параметризованные настройки. Поэтому для динамической смены полей на форме в зависимости от поля самого документа, мы будем использовать программное управление.

  3. Программное управление видимостью и доступностью элементов формы:

    Это ключевой механизм для реализации динамической формы. В управляемых формах 1С мы можем программно регулировать свойства Видимость и Доступность для любых элементов формы (полей, кнопок, групп, табличных частей).

    Как это сделать:

    Рекомендуется выполнять такие действия на сервере при создании формы (в процедуре ПриСозданииНаСервере), чтобы уменьшить объем данных, передаваемых на клиент. Также логику можно вызывать при изменении значения реквизита ВидВызова (в событии ПриИзменении для поля ВидВызова).

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

    Важные моменты:

    • Краткая запись: Для простых условий можно использовать краткую запись вида Элементы.ИмяЭлемента.Видимость = Условие.
    • Пользовательские настройки: Важно учитывать, что пользователь может изменять форму через стандартные механизмы 1С (Настройка формы), и это может повлиять на программно заданные настройки видимости. Рекомендуется использовать группы элементов для более надежного управления.
    • Сервер/Клиент: Всегда определяйте, на какой стороне должна выполняться логика. Управление элементами формы всегда происходит на клиенте, но данные для принятия решения о видимости могут требоваться с сервера. Поэтому часто используется пара клиентской и серверной процедур.

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

3. Замена форм документов формой обработки

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

Как это работает:

  1. Создание обработки: Создадим новую обработку, например, УниверсальнаяФормаДокументовВызова.

  2. Разработка формы обработки: В этой обработке мы создадим одну форму, которая будет содержать все необходимые реквизиты и логику для работы со всеми типами документов "Вызов". На форме обработки мы разместим все возможные поля, группы и табличные части, аналогично тому, как это было описано для единого документа с "видом операции".

  3. Передача объекта: При открытии формы обработки мы будем передавать ей объект документа, с которым необходимо работать (или его ссылку). Это можно сделать через параметр формы.

  4. Динамическое управление: В форме обработки будет реализована логика для определения типа переданного документа и соответствующего управления видимостью и доступностью элементов формы. Мы можем добавить реквизит формы типа ДокументСсылка.ВызовУниверсальный или ДокументОбъект.ВызовУниверсальный, а затем заполнять его в процедуре ПриСозданииНаСервере.

  5. Изменение стандартного поведения: Чтобы при открытии любого из документов (например, из списка) открывалась именно эта форма обработки, потребуется перехватывать стандартное открытие формы документа. Это можно сделать через подписки на событие ОбработкаПолученияФормы для каждого из типов документов. В обработчике подписки мы будем возвращать имя формы нашей обработки.

    
    // Пример подписки на событие "ОбработкаПолученияФормы"
    // Источник: Документ.ВызовРемонтнойБригады, Документ.ВызовМастера, Документ.ВызовПроверяющего
    // Обработчик: ОбщиеФормы.ПолучитьУниверсальнуюФормуДокумента
    
    // Общий модуль: ОбщиеФормы
    Процедура ПолучитьУниверсальнуюФормуДокумента(ИмяФормы, СтандартнаяОбработка, Источник, ДополнительнаяИнформация) Экспорт
        // Возвращаем имя формы нашей обработки
        ИмяФормы = "Обработка.УниверсальнаяФормаДокументовВызова.Форма.ФормаДокумента"; 
        СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку
    КонецПроцедуры
    

Преимущества и недостатки:

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

4. Несколько форм для одного объекта документа

Хотя этот подход не создает "единую" форму в прямом смысле, он предлагает гибкость в управлении различными представлениями для одного и того же объекта документа, что может быть полезно, если вы не хотите полностью консолидировать документы, но хотите управлять тем, какая форма открывается.

Платформа 1С позволяет иметь несколько форм для одного объекта метаданных (например, для документа ВызовУниверсальный можно создать ФормаДокументаРемонтнойБригады, ФормаДокументаМастера и т.д.). Для того чтобы документ открывался в нужной форме, мы можем реализовать следующую логику:

  1. Добавление реквизита в документ: В основной документ (например, ВызовУниверсальный) можно добавить реквизит, который будет хранить информацию о предпочитаемой форме (например, ИмяПредпочитаемойФормы типа Строка).

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

    
    // Модуль формы документа "ВызовУниверсальный" (основная форма)
    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
        Если Объект.ВидВызова = Перечисления.ВидыВызовов.ВызовМастера Тогда
            Если ИмяФормы <> "Документ.ВызовУниверсальный.Форма.ФормаДокументаМастера" Тогда
                Отказ = Истина; // Отменяем открытие текущей формы
                ОткрытьФорму("Документ.ВызовУниверсальный.Форма.ФормаДокументаМастера", Новый Структура("Ключ", Объект.Ссылка), ЭтаФорма);
            КонецЕсли;
        // Иначе, если ВидВызова = РемонтнаяБригада
        // Если ИмяФормы <> "Документ.ВызовУниверсальный.Форма.ФормаДокументаРемонтнойБригады" Тогда
        //  Отказ = Истина;
        //  ОткрытьФорму("Документ.ВызовУниверсальный.Форма.ФормаДокументаРемонтнойБригады", Новый Структура("Ключ", Объект.Ссылка), ЭтаФорма);
        // КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    

Этот подход позволяет сохранять раздельные формы для разных сценариев, но с единым объектом метаданных, давая более тонкий контроль над пользовательским интерфейсом.

Заключение

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

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

← На главную