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