Как правильно открыть форму списка с отбором и передать в нее параметры в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При изучении материалов на ИТС или просмотре чужого кода начинающие разработчики часто сталкиваются с конструкциями, которые кажутся "магическими" или нарушающими привычную логику объектной модели. Один из таких примеров — прямое обращение к свойствам формы, которых нет в стандартном синтакс-помощнике. Давайте разберем, как это работает, почему это вызывает вопросы у опытных программистов и как реализовать передачу отборов максимально грамотно с точки зрения архитектуры платформы 1С:Предприятие 8.3.

Разбор ситуации: Прямое обращение к реквизиту формы

Рассмотрим пример кода, который часто вызывает недоумение:


&НаКлиенте
Процедура ПриходныеНакладные(Команда)
    ФормаСписка = ПолучитьФорму("Документ.ПриходнаяНакладная.ФормаСписка");
    ФормаСписка.ФильтрПоТовару = Элементы.Список.ТекущаяСтрока;
    ФормаСписка.Открыть();
КонецПроцедуры

Здесь ФормаСписка.ФильтрПоТовару — это не предопределенное свойство платформы. На самом деле, это реквизит формы, который разработчик создал вручную в редакторе управляемой формы ПриходнаяНакладная.ФормаСписка. В управляемом приложении платформа позволяет обращаться к реквизитам формы через точку от объекта формы. Проанализируем, почему это решение часто подвергается критике. Основная проблема заключается в смешивании пространств имен. Когда мы пишем Форма.Имя, платформа ищет это имя среди:

  1. Стандартных свойств самой формы (например, ТолькоПросмотр, Заголовок).
  2. Реквизитов, добавленных разработчиком.
  3. Экспортных переменных модуля формы.

Если вы случайно назовете свой реквизит так же, как называется новое свойство, которое 1С добавит в платформу в будущем, ваш код может перестать работать или начать вести себя непредсказуемо. Поэтому рассмотрим более надежные способы реализации этой задачи.

Способ 1. Использование стандартного параметра Отбор

Платформа 1С предоставляет встроенный механизм для наложения простых фильтров при открытии формы. Для этого используется параметр Отбор, который представляет собой структуру. Ключ этой структуры — имя поля в динамическом списке, а значение — то, что мы хотим найти.

Рассмотрим, как это выглядит на практике. Вместо использования функции ПолучитьФорму() и ручного присвоения реквизитов, мы воспользуемся методом ОткрытьФорму():


&НаКлиенте
Процедура ОткрытьСписокСОтбором(Команда)
    ПараметрыОтбора = Новый Структура("Товар", Элементы.Список.ТекущаяСтрока);
    ПараметрыФормы = Новый Структура("Отбор", ПараметрыОтбора);
    
    ОткрытьФорму("Документ.ПриходнаяНакладная.ФормаСписка", ПараметрыФормы);
КонецПроцедуры

Этот метод предпочтительнее, так как платформа берет на себя всю работу по применению фильтра к основному реквизиту формы (Динамическому списку). Нам не нужно создавать лишние реквизиты в форме списка и писать дополнительный код для их обработки.

Способ 2. Фиксированные настройки динамического списка

Иногда требуется передать не просто равенство, а сложный отбор (например, вхождение в список или вид сравнения "Больше"). В этом случае стандартный параметр Отбор может не подойти. Проанализируем использование Фиксированных настроек.

Фиксированные настройки хороши тем, что пользователь не сможет изменить или удалить такой отбор через меню "Настроить список". Это гарантирует, что логика приложения не будет нарушена действиями пользователя.

Разберем алгоритм реализации:

  1. В вызывающей форме подготавливаем структуру отбора.
  2. Передаем её в форму списка.
  3. В форме списка в событии ПриСозданииНаСервере применяем настройки к компоновщику динамического списка.

Пример кода в вызывающем модуле:


&НаКлиенте
Процедура ОткрытьСписокСЖесткимОтбором(Команда)
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ВыбранныйТовар", Элементы.Список.ТекущаяСтрока);
    
    ОткрытьФорму("Документ.ПриходнаяНакладная.ФормаСписка", ПараметрыФормы);
КонецПроцедуры

Пример кода в модуле открываемой формы (ПриСозданииНаСервере):


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Параметры.Свойство("ВыбранныйТовар") Тогда
        ЭлементОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Товар");
        ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
        ЭлементОтбора.ПравоеЗначение = Параметры.ВыбранныйТовар;
        ЭлементОтбора.Использование = Истина;
    КонецЕсли;
КонецПроцедуры

Способ 3. Синхронизация через параметры запроса

Если в вашей форме списка используется динамический список с произвольным запросом, вы можете передать значение фильтра напрямую в параметр запроса. Выясним, как это сделать наиболее элегантно.

Предположим, в форме списка ПриходнаяНакладная в тексте запроса динамического списка написано:

ВЫБРАТЬ * ИЗ Документ.ПриходнаяНакладная ГДЕ Товар = &ПараметрТовар

В этом случае мы можем связать параметр запроса с реквизитом формы. Выполним следующие шаги:

  1. Создаем в форме списка реквизит ФильтрТовар.
  2. В свойствах динамического списка открываем "Настройка списка" -> "Параметры".
  3. Для параметра &ПараметрТовар в колонке "Выражение" указываем имя нашего реквизита: ФильтрТовар.
  4. Устанавливаем флаг "Использовать всегда".

Теперь, как только мы программно изменим значение реквизита ФильтрТовар, список автоматически обновится. Это именно то, что пытался сделать автор примера с ИТС, но с использованием более глубокой интеграции с механизмом динамических списков.

Важные нюансы: ПолучитьФорму против ОткрытьФорму

Проанализируем разницу между этими двумя методами. В старых примерах часто используется ПолучитьФорму(). Однако в современном стандарте разработки 1С рекомендуется использовать ОткрытьФорму().

Почему это важно?

Конфликты имен и приоритеты

Чтобы избежать ошибок при работе с реквизитами формы, важно помнить приоритет обращения к именам внутри модуля формы. Рассмотрим ситуацию, когда у вас есть локальная переменная и реквизит формы с одинаковым именем:


&НаКлиенте
Процедура Тест()
    Переменная1 = 10; // Локальная переменная
    // Если мы напишем просто Переменная1, мы обратимся к локальной переменной.
    // Чтобы гарантированно обратиться к реквизиту формы, используем:
    ЭтотОбъект.Переменная1 = 20; 
КонецПроцедуры

Выясним, в каком порядке платформа ищет идентификатор, если он написан без префикса:

  1. Локальные переменные процедуры/функции.
  2. Реквизиты формы (те, что видны в дереве реквизитов справа в редакторе).
  3. Экспортные переменные модуля формы.
  4. Свойства самой платформенной формы как объекта.

Именно из-за этого "сваливания в кучу" разработчики в обсуждении называют прямой доступ к реквизитам "серьезным просчетом". Чтобы ваш код был понятным и легко поддерживаемым, старайтесь использовать структуру Параметры и обрабатывать их внутри события ПриСозданииНаСервере. Это сделает ваши формы более независимыми и предсказуемыми в работе.

Итоги

Рассмотренное "шаманство" с ФормаСписка.ФильтрПоТовару — это легитимная, но не самая лучшая практика работы в управляемом приложении 1С. Для качественной разработки рекомендуется использовать механизм параметров формы и настройки компоновщика данных динамического списка. Это обеспечит стабильность кода при обновлениях платформы и упростит чтение вашей логики другими программистами.

← На главную