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