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

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

При разработке справочников в системе 1С:Предприятие часто возникает задача адаптировать форму элемента под конкретный контекст. Типичный пример — справочник контрагентов, где логика заполнения данных кардинально зависит от перечисления ЮрФизЛицо. Если выбран контрагент-физлицо, требуется связать его с конкретным физическим лицом (агентом), а если выбрано юридическое лицо — заблокировать выбор агента или настроить автоматическое заполнение.

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

Анализ типичных ошибок: типизация и директивы выполнения

Рассмотрим код, который часто пытаются написать:


&НаСервере
Функция ПолучитьФизЮр(ФизЮр) Экспорт
    Если Объект.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ФизическоеЛицо Тогда
        Объект.Наименование = Объект.Агент;
    ИначеЕсли Объект.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮридическоеЛицо Тогда
        Объект.Агент = Объект.Наименование;
    Иначе 
        Сообщить("Вы ничего не выбрали!!!");
    КонецЕсли;
КонецФункции

&НаКлиенте
Процедура ЮрФизЛицоПриИзменении(Элемент)
    Объект.Агент = ПолучитьФизЮр(Объект.Агент);
КонецПроцедуры

Выясним причину, почему такой подход категорически неверен сразу по нескольким причинам:

  1. Несоответствие типов данных: Реквизит Наименование в платформе 1С всегда имеет тип Строка. Реквизит Агент жестко типизирован ссылкой — СправочникСсылка.ФизическиеЛица. В поле с типом «Строка» нельзя напрямую записать ссылку на справочник, а в ссылочное поле нельзя поместить текстовую строку. Платформа не позволяет изменять типы реквизитов объекта в режиме выполнения (рантайме) — тип строго задается в структуре метаданных конфигуратора.
  2. Ошибки клиент-серверного взаимодействия и синтаксиса: В процедуре ЮрФизЛицоПриИзменении вызывается серверная функция, результат которой присваивается в Объект.Агент. Однако сама функция ПолучитьФизЮр не содержит оператора Возврат и напрямую модифицирует данные объекта на сервере, что делает присваивание на клиенте бессмысленным и ошибочным.
  3. Архитектурное нарушение сущностей: Попытка автоматически создавать элементы справочника «Физические лица» с наименованиями юридических лиц (например, «ООО Вектор») приводит к загрязнению справочника некорректными записями. Справочник физических лиц предназначен исключительно для хранения людей (ФИО, паспортные данные, контактные сведения).

Правильный подход: управление видимостью, доступностью и синхронизация наименования

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

  1. Для Физического лица: поле Агент доступно для выбора. При выборе физического лица его строковое наименование (ФИО) автоматически переносится в реквизит Наименование контрагента. При этом само поле Наименование можно заблокировать от случайного ручного редактирования.
  2. Для Юридического лица: наименование вводится пользователем вручную строкой, а поле Агент блокируется, скрывается или очищается, так как агент у юрлица в данной логике отсутствуют.

Пошаговая реализация логики в управляемой форме

Разберем по шагам создание необходимых процедур на форме справочника.

  1. Настройка доступности и видимости элементов:
    Создадим универсальную серверную процедуру, которая анализирует выбранное значение ЮрФизЛицо и соответствующим образом настраивает свойства элементов формы Элементы.Агент и Элементы.Наименование. Для блокировки редактирования используем свойство ТолькоПросмотр или Доступность.
  2. Событие изменения типа контрагента:
    При изменении реквизита ЮрФизЛицо вызываем процедуру настройки формы, а также очищаем поле Агент при выборе юридического лица, чтобы в базе не оставалось некорректных связей.
  3. Событие изменения агента:
    При интерактивном выборе агента в поле Агент вызываем серверный обработчик, который получает строковое представление физического лица через Объект.Агент.Наименование и записывает его в Объект.Наименование.
  4. Инициализация при открытии:
    Чтобы форма корректно отображала заблокированные и доступные поля для уже сохраненных элементов, ту же серверную логику настройки элементов необходимо вызывать в обработчике ПриСозданииНаСервере или ПриЧтенииНаСервере.

Пример программного кода для управляемой формы

Посмотрим на пример комплексного решения в модуле управляемой формы элемента:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    НастроитьЭлементыФормы();
КонецПроцедуры

&НаКлиенте
Процедура ЮрФизЛицоПриИзменении(Элемент)
    НастроитьЭлементыФормы();
    ОбработатьСменуЮрФизЛицаНаСервере();
КонецПроцедуры

&НаКлиенте
Процедура АгентПриИзменении(Элемент)
    СинхронизироватьНаименованиеНаСервере();
КонецПроцедуры

&НаСервере
Процедура НастроитьЭлементыФормы()
    ЭтоФизЛицо = (Объект.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ФизическоеЛицо);
    
    // Если физлицо — поле Агент доступно, а Наименование формируется автоматически
    Элементы.Агент.Доступность = ЭтоФизЛицо;
    Элементы.Агент.Видимость   = ЭтоФизЛицо;
    
    // Блокируем поле Наименование от прямого ввода, если данные должны браться строго из агента
    Элементы.Наименование.ТолькоПросмотр = ЭтоФизЛицо;
КонецПроцедуры

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

&НаСервере
Процедура СинхронизироватьНаименованиеНаСервере()
    // Обращение через точку к реквизитам ссылки безопасно выполняем на сервере
    Если ЗначениеЗаполнено(Объект.Агент) Тогда
        Объект.Наименование = Объект.Агент.Наименование;
    КонецЕсли;
КонецПроцедуры

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

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

  1. В дереве метаданных конфигуратора для нужного реквизита флажками отмечаются сразу несколько разрешенных типов: Строка и СправочникСсылка.ФизическиеЛица.
  2. На форме у элемента управления устанавливается свойство ВыбиратьТип = Истина.
  3. При необходимости список доступных типов можно программно сужать с помощью объекта ОписаниеТипов и метода ОграничениеТипа.

Важно: К стандартному реквизиту Наименование данный метод неприменим, так как платформа 1С жестко фиксирует его тип как строковый без возможности расширения.

← На главную