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