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