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