В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача ограничить пользователю возможность выбора элементов из справочника (поможет инструмент настройки контроля ввода и скрытия элементов списков без программирования). Типичный пример: в конкретном документе должны быть доступны только договоры с определенным типом (например, только «С поставщиком»), при этом структура данных может быть сложной — когда нужный признак находится не в самом справочнике ДоговорыКонтрагентов, а в связанном справочнике ВидыДоговоров.
Рассмотрим подробнее несколько способов решения этой задачи: от простых настроек в метаданных до продвинутого программного управления процессом выбора — есть готовая обработка для настройки условий и отборов в формах выбора 1С. Проанализируем плюсы и минусы каждого подхода, чтобы обеспечить надежность и удобство работы пользователя.
Самый простой и быстрый способ, не требующий написания кода — это настройка свойств реквизита непосредственно в дереве метаданных. Разберем этот механизм. У каждого реквизита документа (в нашем случае ДоговорКонтрагента) есть свойство Параметры выбора.
Если бы тип договора был прямым реквизитом справочника ДоговорыКонтрагентов, мы могли бы просто добавить новый параметр, указать путь к данным и зафиксировать значение. Однако в нашей задаче «Тип договора» — это реквизит справочника ВидыДоговоров. Платформа 8.3 позволяет прописывать путь через точку в параметрах выбора, но это работает не всегда стабильно в сложных иерархиях. Если структура позволяет, мы указываем отбор Отбор.ВидДоговора.ТипДоговора(Перечисление.ТипыДоговоров.СПоставщиком).
Преимущества: скорость настройки и отсутствие кода.
Недостатки: невозможность реализовать сложную логику (например, если условие зависит от даты документа или других динамических параметров).
Если условие фильтрации должно определяться в момент открытия формы или при изменении других реквизитов, мы используем программную установку. Для этого удобно применять функции программного изменения форм. Разберем, как это сделать в обработчике ПриСозданииНаСервере или ПриИзменении связанного поля.
Проанализируем пример кода, который устанавливает жесткий фильтр для элемента формы. Для быстрой проверки свойств можно редактировать свойства элементов прямо в режиме предприятия:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Формируем массив параметров выбора
НовыйПараметр = Новый ПараметрВыбора("Отбор.ВидДоговора.ТипДоговора", Перечисления.ТипыДоговоров.СПоставщиком);
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(НовыйПараметр);
// Назначаем параметры элементу формы
Элементы.ДоговорКонтрагента.ПараметрыВыбора = Новый ФиксированныйМассив(МассивПараметров);
КонецПроцедуры
Этот метод гораздо надежнее, так как он программно ограничивает список выбора именно для конкретного элемента управления в текущей форме.
Иногда разработчики решают задачу путем модификации самой формы выбора справочника ДоговорыКонтрагентов. В этом случае в динамическом списке формы устанавливается произвольный запрос с условием ГДЕ или настраивается отбор в настройках компоновки данных. Существуют различные методы доработки динамических списков для таких задач.
Рассмотрим ситуацию: мы создаем отдельную форму выбора специально для поставщиков. В настройках динамического списка (свойство НастройкиКомпоновкиДанных) мы добавляем элемент отбора. Однако, как правильно заметили участники обсуждения, у этого метода есть существенный недостаток: ввод по строке. Если пользователь начнет набирать название договора прямо в поле ввода документа, платформа может подставить договор, не открывая форму выбора, и фильтр динамического списка будет проигнорирован.
Чтобы этого избежать, при использовании кастомных форм выбора необходимо также назначать эту форму в свойство реквизита Форма выбора или программно через Событие НачалоВыбора.
Выясним причину, по которой это решение считается наиболее профессиональным. Чтобы фильтрация работала всегда (и при нажатии кнопки «Выбрать», и при «Вводе по строке»), лучше всего использовать обработчик ОбработкаПолученияДанныхВыбора в модуле менеджера справочника ДоговорыКонтрагентов.
Разберем алгоритм работы этого метода:
Пример кода в модуле менеджера:
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
// Если в параметрах передано специальное условие
Если Параметры.Свойство("ТолькоСПоставщиками") Тогда
СтандартнаяОбработка = Ложь;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Договоры.Ссылка КАК Ссылка
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК Договоры
|ГДЕ
| Договоры.ВидДоговора.ТипДоговора = &ТипДоговора
| И Договоры.Наименование ПОДОБНО &СтрокаПоиска";
Запрос.УстановитьПараметр("ТипДоговора", Перечисления.ТипыДоговоров.СПоставщиком);
Запрос.УстановитьПараметр("СтрокаПоиска", "%" + Параметры.СтрокаПоиска + "%");
ДанныеВыбора = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецЕсли;
КонецПроцедуры
Важно помнить, что любые интерфейсные ограничения (в формах) можно обойти с помощью внешних обработок или обменов данными. Поэтому для обеспечения 100% целостности базы данных мы обязательно должны добавить проверку в модуле объекта документа.
Проанализируем ситуацию: документ записывается. Нам нужно убедиться, что выбранный договор соответствует правилам, независимо от того, как он попал в документ. Используем обработчик ОбработкаПроверкиЗаполнения или ПередЗаписью.
&НаСервере
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЗначениеЗаполнено(ДоговорКонтрагента) И
ДоговорКонтрагента.ВидДоговора.ТипДоговора <> Перечисления.ТипыДоговоров.СПоставщиком Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Выбран недопустимый тип договора! Допускаются только договоры с поставщиками.";
Сообщение.Поле = "ДоговорКонтрагента";
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
В современных конфигурациях (таких как УТ 11, ERP или БП 3.0) задача фильтрации часто решается через функции Библиотеки стандартных подсистем (БСП). Вместо того чтобы изобретать велосипед, проанализируем типовые механизмы. В БСП часто используются общие модули для настройки отборов, которые вызываются в событии НачалоВыбора.
Это позволяет централизованно управлять логикой фильтрации. Например, если завтра тип договора должен будет зависеть не только от константы, но и от организации, вам придется менять код только в одном месте, а не во всех документах.
Подведем итог: для решения задачи «на скорую руку» подойдут Параметры выбора в свойствах элемента формы. Для создания надежного и качественного решения используйте связку из ОбработкиПолученияДанныхВыбора (для удобства пользователя) и проверки в модуле объекта ПередЗаписью (для гарантии корректности данных). Для этой задачи есть расширение для автоматического выбора основного договора в документах 1С.