Как обработать выбор типа в поле составного типа данных и установить отбор по владельцу в 1С?

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

В процессе разработки прикладных решений на платформе «1С:Предприятие 8» программисты часто сталкиваются с необходимостью организации удобного интерфейса для ввода данных составного типа. Типичный пример: на форме присутствует поле ввода, которое может принимать значения нескольких типов (например, СправочникСсылка.Контрагенты и СправочникСсылка.ФизическиеЛица), и нам требуется реализовать динамический отбор при выборе значения в зависимости от других реквизитов формы (например, организации или головной компании).

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

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

  1. ВладелецОтбора (тип данных может быть, например, СправочникСсылка.Контрагенты).
  2. СоставноеПолеВвода (составной тип данных, включающий СправочникСсылка.ДоговорыКонтрагентов и СправочникСсылка.КонтактныеЛица).

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

Ниже мы подробно проанализируем три практических метода решения этой задачи: от простого декларативного до гибкого программного.


Способ 1. Декларативная настройка через «Связи параметров выбора» (Без кода)

Платформа «1С:Предприятие 8» обладает мощным встроенным механизмом декларативной настройки связей между элементами формы. Если логика отбора достаточно стандартная (например, нам нужно просто отфильтровать элементы подчиненного справочника по его владельцу), мы можем настроить это в конфигураторе вообще без написания программного кода.

Рассмотрим по шагам, как это сделать:

  1. Откроем нужную управляемую форму в конфигураторе.
  2. Найдем в списке элементов формы наше поле ввода (например, СоставноеПолеВвода) и откроем его свойства (клавиша F4).
  3. В палитре свойств найдем строку Связи параметров выбора (Choice parameter links) и нажмем кнопку открытия диалогового окна настройки.
  4. В открывшемся окне добавим новую строку:
    • В колонке Имя параметра редактирования укажем стандартное имя параметра отбора для подчиненных справочников: Отбор.Владелец.
    • В колонке Путь к данным выберем реквизит нашей формы, который содержит владельца, то есть Объект.ВладелецОтбора.
  5. Нажмем «ОК» для сохранения настроек и запустим режим «1С:Предприятие» для проверки.

Как это работает на практике? Платформа 1С достаточно интеллектуальна. Когда пользователь нажимает кнопку выбора «...», система сначала стандартно открывает диалог выбора типа. Как только пользователь выбирает, например, СправочникСсылка.ДоговорыКонтрагентов, платформа анализирует связи параметров выбора. Она «понимает», что для выбранного типа существует реквизит Владелец, и автоматически подставляет в открывающуюся форму выбора отбор по значению из реквизита ВладелецОтбора. Если же пользователь выберет тип данных, у которого нет связи по владельцу, форма выбора откроется без ошибок, просто проигнорировав эту связь.


Способ 2. Элегантный перехват через событие «ОбработкаВыбора»

Если вам требуется более сложная логика (например, динамическое определение владельца в зависимости от выбранного типа или наложение дополнительных условий отбора, которые нельзя задать декларативно), нам потребуется использовать программный код. Но как перехватить момент, когда выбор типа уже совершен, а форма выбора еще не открылась?

Для этого мы можем использовать малоизвестную, но очень удобную особенность платформы: когда поле ввода имеет составной тип и оно пустое, при нажатии кнопки «...» сначала отрабатывает системное окно выбора типа. После того как пользователь кликает на нужный тип, платформа генерирует событие ОбработкаВыбора, передавая в качестве выбранного значения не ссылку на элемент, а сам объект метаданных типа — объект с типом Тип.

Проанализируем пример реализации такого перехвата:


&НаКлиенте
Процедура СоставноеПолеВводаОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    
    // Шаг 1: Выясняем, что именно выбрал пользователь. 
    // Если выбран именно ТИП данных, значит, это был первый этап выбора в пустом поле.
    Если ТипЗнч(ВыбранноеЗначение) = Тип("Тип") Тогда
        
        // Отменяем стандартное открытие формы выбора платформой, так как мы откроем её вручную
        СтандартнаяОбработка = Ложь; 
        
        // Шаг 2: Приводим значение реквизита к выбранному типу (создаем пустую ссылку этого типа)
        МассивТипов = Новый Массив;
        МассивТипов.Добавить(ВыбранноеЗначение);
        ОписаниеТипов = Новый ОписаниеТипов(МассивТипов);
        
        // Приведение значения установит в реквизит пустую ссылку нужного типа,
        // благодаря чему при следующем открытии платформа сразу поймет, форму какого справочника открывать.
        Объект.СоставноеПолеВвода = ОписаниеТипов.ПривестиЗначение(); 
        
        // Шаг 3: Готовим параметры и отборы для формы выбора
        ПараметрыФормы = Новый Структура;
        Отбор = Новый Структура;
        
        // Здесь мы можем реализовать любую сложную логику отборов в зависимости от выбранного типа
        Если ВыбранноеЗначение = Тип("СправочникСсылка.ДоговорыКонтрагентов") Тогда
            Отбор.Вставить("Владелец", Объект.ВладелецОтбора); 
        ИначеЕсли ВыбранноеЗначение = Тип("СправочникСсылка.КонтактныеЛица") Тогда
            // Например, для контактных лиц отбор тоже идет по контрагенту-владельцу
            Отбор.Вставить("Владелец", Объект.ВладелецОтбора);
        КонецЕсли;
        
        ПараметрыФормы.Вставить("Отбор", Отбор);
        
        // Шаг 4: Получаем имя формы выбора для выбранного типа на сервере
        ИмяФормыВыбора = ПолучитьИмяФормыВыбораНаСервере(ВыбранноеЗначение);
        
        // Шаг 5: Открываем форму выбора программно
        ОткрытьФорму(ИмяФормыВыбора, ПараметрыФормы, Элемент);
        
    КонецЕсли;
    
КонецПроцедуры

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

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


Способ 3. Полностью ручной выбор типа через «НачалоВыбора» (Максимальный контроль)

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

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

Разберем по шагам этот программный метод:


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

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

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


Важные нюансы и подводные камни

При работе с составными типами данных в управляемых формах 1С крайне важно учитывать несколько особенностей поведения платформы:

Таким образом, мы детально разобрали три различных подхода к обработке выбора типа данных в составных полях. Выбор конкретного метода зависит от сложности ваших бизнес-требований: для простых задач идеально подойдет декларативный Способ 1, для гибкого контроля без изменения стандартного UI — Способ 2, а для полной кастомизации поведения формы — Способ 3.

← На главную