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