Как программно ограничить выбор номенклатуры конкретной группой в 1С?

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

В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача сузить круг выбора для пользователя. Например, при заполнении табличной части документа необходимо сделать так, чтобы при нажатии на ячейку Номенклатура открывался не весь справочник, а только конкретная папка (группа). Это не только ускоряет работу пользователя, но и минимизирует риск ввода некорректных данных. В данной статье мы разберем несколько способов реализации этой задачи — от самых простых настроек в конфигураторе до продвинутого программного кода.

Способ 1. Использование свойств реквизита (без программирования)

Прежде чем приступать к написанию кода, давайте проанализируем штатные возможности платформы. В управляемых формах реализован механизм Параметры выбора. Если группа, по которой нужно фильтровать список, заранее известна и статична (например, папка «Услуги»), мы можем задать её прямо в свойствах реквизита.

Рассмотрим пошагово, как это сделать:

  1. Откроем конфигуратор и найдем нужный реквизит (в справочнике или табличной части документа).
  2. В палитре свойств найдем пункт Параметры выбора.
  3. Нажмем на кнопку выбора (три точки) и добавим новый параметр.
  4. Выберем поле Отбор.Родитель (если нужно выбрать только из конкретной папки) или Отбор.Ссылка.
  5. Укажем значение конкретной группы из справочника Номенклатура.

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

Способ 2. Программная реализация в событии НачалоВыбора

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

Разберем типичный пример кода, который решает поставленную задачу. Обратите внимание, что крайне важно передавать в отбор именно Ссылку на объект, а не его наименование в виде строки.


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

&НаСервереБезКонтекста
Функция НайтиГруппуБумагаНаСервере()
    Возврат Справочники.Номенклатура.НайтиПоНаименованию("Бумага", Истина);
КонецФункции

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

Способ 3. Проблема «Родителя» и использование иерархии

Проанализируем важный нюанс, упомянутый в обсуждении. Если вы используете отбор по полю Родитель, система покажет только те элементы, которые лежат непосредственно в этой папке. Если внутри группы «Бумага» есть подпапки «Офисная» и «Фотобумага», то элементы из них не отобразятся. Это частая ошибка начинающих разработчиков.

Для того чтобы увидеть все вложенные элементы (всю иерархию), необходимо использовать вид сравнения ВИерархии. Однако простая структура отбора в параметрах формы 1С поддерживает только сравнение на «Равенство». Чтобы реализовать отбор по иерархии, нам нужно использовать ФиксированныеНастройки компоновки данных.

Посмотрим, как изменить наш код для работы с иерархией:


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

Использование ФиксированныеНастройки — это самый мощный и надежный способ. Он гарантирует, что пользователь не сможет случайно отключить этот отбор в форме выбора через настройки списка.

Способ 4. Связи параметров выбора (динамическая фильтрация)

Выясним еще одну ситуацию: что если группа отбора зависит от значения другого реквизита? Например, в таблице есть колонка КатегорияНоменклатуры, и мы хотим, чтобы в колонке Товар предлагались элементы только из выбранной категории.

Для этого в 1С существует механизм Связи параметров выбора. Рассмотрим алгоритм настройки:

  1. В свойствах реквизита Номенклатура найдем поле Связи параметров выбора.
  2. Добавим новую связь.
  3. В поле Параметр выбора укажем Отбор.Родитель.
  4. В поле Поле формы выберем реквизит, в котором хранится нужная нам группа (например, Объект.Товары.ТекущаяКатегория).

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

Почему форма открывается «пустой» или не позволяет выбрать?

Как отмечалось в сообщениях форума (сообщение 9), иногда разработчики сталкиваются с тем, что форма открывается, но данные в ней не соответствуют ожиданиям или выбор не срабатывает. Разберем основные причины:

  1. Передача строки вместо ссылки: Если вы напишете Отбор.Вставить("Родитель", "Бумага"), 1С будет искать папку, ссылка которой буквально равна строке "Бумага", чего никогда не случится. Всегда используйте методы типа НайтиПоНаименованию или НайтиПоКоду на сервере.
  2. Режим выбора: При программном открытии формы обязательно указывайте параметр РежимВыбора = Истина. Без него форма откроется в режиме обычного просмотра списка, и двойной клик по элементу просто откроет карточку товара вместо того, чтобы выбрать его в документ.
  3. Тип значения: Убедитесь, что реквизит Родитель в справочнике Номенклатура имеет тип СправочникСсылка.Номенклатура. Если в конфигурации используется сложная иерархия или разные типы данных, это может потребовать уточнения.

Рекомендации по современным стандартам разработки

Начиная с версий платформы 8.3.15 и выше, компания 1С рекомендует отказываться от модальных окон (как в сообщении 9). Вместо ОткрытьФормуМодально мы используем обычное ОткрытьФорму с передачей владельца. Если же вам нужно выполнить какой-то специфический код сразу после выбора значения (а не просто вставить его в поле), используйте ОписаниеОповещения.

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

← На главную